I'm not sure what the issue is but my code looks like:
function() {
string sqltext2;
sqltext2 = "INSERT into myTable";
SqlCommand myCommand2 = new SqlCommand(sqltext2, MyConnection2);
if (cond1) {
sqltext2 = sqltext2 + "SELECT" + "#initOwnerFirstName" + "," + "#ownerFirstName" + "UNION ALL ";
SqlParameter param = new SqlParameter();
param.ParameterName = "#initOwnerFirstName";
param.Value = initOwnerFirstName;
SqlParameter param2 = new SqlParameter();
param2.ParameterName = "#ownerFirstName";
param2.Value = owner.FirstName;
myCommand2.Parameters.Add(param);
myCommand2.Parameters.Add(param2);
I'm completely new with parameterized SQL but the syntax seems right to me. The error I keep getting is:
Must declare the scalar variable "#initOwnerFirstName".
The reason I'm writing the statement like that is because I intend to have multiple other if statements that will add to the SQLtext
EDIT: Here is the full part of the code after the if statement since my syntax makes little sense without the other variables. This is cleaned up after what JYelton suggested but I'm still getting the same error.
sqltext2 = sqltext2 + "SELECT" + "'" + currentUserId2 + "'," + "'" + owner.Id.ToString() + "'," + "'" + DateTime.Now + "'," + "'FirstName', #initOwnerFirstName, #ownerFirstName UNION ALL ";
myCommand2.Parameters.AddWithValue("initOwnerFirstName", initOwner.FirstName);
myCommand2.Parameters.AddWithValue("OwnerFirstName", owner.FirstName);
Problem could be that you are concatenating your strings without spaces. You don't need to concatenate either. See my update below:
function() {
string sqltext2;
sqltext2 = "INSERT into dbo.OwnerChanges ";
SqlCommand myCommand2 = new SqlCommand(sqltext2, MyConnection2);
if (cond1) {
//no concatenating
sqltext2 = sqltext2 + " SELECT #initOwnerFirstName , #ownerFirstName UNION ALL ";
SqlParameter param = new SqlParameter();
param.ParameterName = "#initOwnerFirstName";
param.Value = initOwnerFirstName;
SqlParameter param2 = new SqlParameter();
param2.ParameterName = "#ownerFirstName";
param2.Value = owner.FirstName;
myCommand2.Parameters.Add(param);
myCommand2.Parameters.Add(param2);
I'm not sure what the rest of your code does but I suspect you are leaving a trailing UNION ALL at the end of all that. You could probably benefit by just putting each sub query into an array and using String.Join on them.
UPDATE:
I think I see the issue. You need to update CommandText and not the original string. So change this:
sqltext2 = sqltext2 + " SELECT #initOwnerFirstName , #ownerFirstName UNION ALL ";
to this:
myCommand2.CommandText= sqltext2 + " SELECT #initOwnerFirstName , #ownerFirstName UNION ALL ";
Here's how parameterized queries work:
using (SqlConnection conn = new SqlConnection("connectionstring"))
{
using SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = #"INSERT INTO mytable
(initOwnerFirstName, ownerFirstName)
VALUES (#initOwnerFirstName, #ownerFirstName);";
cmd.Parameters.AddWithValue("initOwnerFirstName", initOwner.FirstName);
cmd.Parameters.AddWithValue("ownerFirstName", owner.FirstName);
// ... execute query
}
}
It looks like you are inserting into myTable the results of a SELECT statement, but you are trying to pass parameters where the column names should go. The Parameter will replace the #variablename with the value, thus: Parameters are for the values, not the column names.
For multiple values, use parenthesis to specify the set, separated by commas:
INSERT INTO mytable (col1, col2) VALUES ("a", "b"), ("c", "d"), ("e", "f");
You can modify the query string appropriately to fit this syntax.
More information: SQL Insert Syntax
Related
updatequery = #"UPDATE EMP_DETAILS SET ADVANCE_SAL = 'ADVANCE_SAL + '" +
Convert.ToDecimal(txtADV.Text) + "'' WHERE EMP_ID = '" +
Convert.ToInt64(txtEID.Text) + "')";
What is wrong with the above code?
.
.
.
The modified code which has an error [Scalar variable #ADVANCE_SAL not declared] is as follows:
var c = dtimePick.Value.TimeOfDay;
SqlParameter param = new SqlParameter("#ADVANCE_SAL", SqlDbType.Decimal);
param.Value = Convert.ToDecimal(txtADV.Text);
command.Parameters.Add(param);
updatequery = #"UPDATE EMP_DETAILS SET ADVANCE_SAL = ADVANCE_SAL + #ADVANCE_SAL , LATEST_ADVANCE_DATE = '"+c+"' WHERE ENAME = '"+txtEID.Text+"' ";
The error is that you are enclosing ADVANCE_SAL with single quote. To make it cleaner and safer from sql injection, you must parameterized the query,
updatequery = #"UPDATE EMP_DETAILS
SET ADVANCE_SAL = ADVANCE_SAL + #ADVANCE_SAL
WHERE EMP_ID = #EMP_ID"
using (SqlConnection connection = new SqlConnection(/* connection info */))
{
using (SqlCommand command = new SqlCommand(updatequery , connection))
{
// must do proper error handling
connection.Open();
command.Parameters.Add(new SqlParameter("ADVANCE_SAL", Convert.ToDecimal(txtADV.Text)));
command.Parameters.Add(new SqlParameter("EMP_ID", Convert.ToInt64(txtEID.Text)));
int results = command.ExecuteNonQuery();
}
}
Why you are adding single quote to the EMP_ID and ADVANCE_SAL they are numeric and don't need ', i think following is what you wanted...
updatequery = #"UPDATE EMP_DETAILS SET ADVANCE_SAL = ADVANCE_SAL + " +
Convert.ToDecimal(txtADV.Text) + " WHERE EMP_ID = " +
Convert.ToInt64(txtEID.Text) + ")";
There are many problems with your implementation.
1- SQL injection vulnerability - Rad more on this here
2- Your query building is not correct, it should be like following. (Quotes are not correct for ADVANCE_SAL)
updatequery = #"UPDATE EMP_DETAILS SET ADVANCE_SAL = ADVANCE_SAL + " +
Convert.ToDecimal(txtADV.Text) + " WHERE EMP_ID = '" +
Convert.ToInt64(txtEID.Text) + "'";
3- If any employee have not opted for advance salary (in that case the ADVANCE_SAL value can be null in the table). Your query will update it with NULL as NULL + SomeValue = NULL
For example
SELECT NULL +10.0 AS Total
Output
Total
-----
NULL
try this
updatequery = #"UPDATE EMP_DETAILS SET ADVANCE_SAL = 'ADVANCE_SAL + '" +
Convert.ToDecimal(txtADV.Text) + "'' WHERE ( EMP_ID = '" +
Convert.ToInt64(txtEID.Text) + "')";
I've currently got a WHERE clause in a SQL string that looks like this:
CmdTxt = CmdTxt + "Where FA.CSE_LAN = '" + UID + "' ";
It eventually culminates in a call to Oracle:
OracleCommand cmd = new OracleCommand(CmdTxt, connection);
cmd.Connection = connection;
cmd.CommandText = CmdTxt;
cmd.CommandType = CommandType.Text;
OracleDataAdapter da = new OracleDataAdapter(cmd);
da.Fill(dt);
What I now need to do is change that WHERE logic, so that it first looks at a column called FA.BUILD_CSE_LAN. If that has a value, it will use that column in the WHERE clause.
If it doesn't have a value, it will use the column FA.CSE_LAN in the WHERE clause.
How can I do this? I'm using C# code-behind in an ASP.Net environment against an Oracle 12c database, if any of that is important.
I am no expert on oracle but I would try something like this.
CmdTxt = CmdTxt + "Where FA.BUILD_CSE_LAN = #UID OR ( FA.BUILD_CSE_LAN IS NULL AND FA.CSE_LAN = #UID)";
That way it if your build field is null, no value, it checks the other one.
And declare #UID as a parameter on your command to avoid injection or special character issues.
This doc on Oracle might help: NVL or COALESCE could help here.
CmdTxt = CmdTxt + "Where NVL(FA.BUILD_CSE_LAN, FA.CSE_LAN) = '" + UID + "' ";
or
CmdTxt = CmdTxt + "Where COALESCE(FA.BUILD_CSE_LAN, FA.CSE_LAN) = '" + UID + "' ";
Im trying to perform a parameterized query in SQLite from C#, and the method im using is along the lines of creating a static command with
SQLiteCommand cmd = new SQLiteCommand(
"SELECT [ID]" +
",[email]" +
",[serializedata]" +
",[restrictions]" +
" FROM " + UserTable +
" WHERE #search = #searchparam", SQLConnection);
cmd.Parameters.Add(new SQLiteParameter("#searchparam"));
cmd.Parameters.Add(new SQLiteParameter("#search"));
and calling it like this:
Command.Parameters["#searchparam"].Value = searchdata;
Command.Parameters["#search"].Value = search;
SQLiteDataAdapter slda = new SQLiteDataAdapter(UserSelectUsernameCommand);
DataSet ds = new DataSet();
slda.Fill(ds);
User[] array = new User[ds.Tables[0].Rows.Count];
int index = 0;
foreach (DataRow row in ds.Tables[0].Rows)
{
array[index] = new User(this, row);
index++;
}
return array;
but im getting an error along the line of " '#search' is not a correct column name " or something like that. if i use a constant column name, and only use the data for parameters it works, but i dont want to create 10 different commands for when i need to search by different column names.
What is the issue here?
Generally things like column names (or table names) can not be parameterised - and the fact that there are different indices means that it will have to be a different plan internally. So you will have to use concatenation - but be careful to white-list the known column names to prevent sql injection:
SQLiteCommand cmd = new SQLiteCommand(#"
SELECT [ID],[email],[serializedata],[restrictions]
FROM " + whiteListedUserTable + #"
WHERE [" + whiteListedColumnName + #"] = #searchparam", SQLConnection);
cmd.Parameters.Add(new SQLiteParameter("#searchparam"));
...
Command.Parameters["#searchparam"].Value = searchdata;
You cannot use a query parameter in that fashion -- to indicate a column name. You can only use it to supply values.
Consider something like this instead:
SQLiteCommand cmd = new SQLiteCommand(
"SELECT [ID]" +
",[email]" +
",[serializedata]" +
",[restrictions]" +
" FROM " + UserTable +
" WHERE [" + search + "] = #searchparam", SQLConnection);
cmd.Parameters.Add(new SQLiteParameter("#searchparam"));
If you control all of the input to this function and none if it can be supplied by someone other than you, this should be safe. But if search comes from an untrusted third party, be sure to make the appropriate security checks on the value.
How to update bool in a database a sql query
below is the code i have but i am unsure of how to implement the checkbox.
Thank you for any help.
i have updated the code to remove the sql injection problems.
con.Open();
OleDbCommand cmd = new OleDbCommand(String.Concat("Select * From ", comboBox1.Text), con);
cmd.CommandType = CommandType.Text;
string tableName = comboBox1.Text.ToString();
cmd.CommandText = #"UPDATE [" + tableName + "] SET"
+"People_Call_Status = #People_Call_Status,"
+"Research_Date=#Research_Date,"
+ "tblCompanies_Area_Dialling_Code = #tblCompanies_Area_Dialling_Code,"
+ "Work_Number = #Work_Number,"
+ "building_Address = #building_Address,"
+ "[Street Address] = #[Street Address],"
+ "suburb = #suburb,"
+ "city = #city,"
+ "res_Code = #res_Code,"
+ "industry_Vertical_ID = #industry_Vertical_ID,"
+ "pO_Box = #pO_Box,"
+ "post_Office = #post_Office,"
+ "postal_Code = #postal_Code,"
+ "country_ID = #country_ID,"
+ "province_ID = #province_ID," //this line
+ "prospect = #prospect"
+ "WHERE Company_ID = #Company_ID ";
cmd.Parameters.AddWithValue("#People_Call_Status", Status_textBox1.Text);
cmd.Parameters.AddWithValue("#Research_Date", Date_textBox.Text);
cmd.Parameters.AddWithValue("#Company_Name", company_NameTextBox.Text);
cmd.Parameters.AddWithValue("#tblCompanies_Area_Dialling_Code", tblCompanies_Area_Dialling_CodeTextBox.Text);
cmd.Parameters.AddWithValue("#Work_Number", work_NumberTextBox.Text);
cmd.Parameters.AddWithValue("#building_Address", building_AddressTextBox.Text);
cmd.Parameters.AddWithValue("#[Street Address]", street_AddressTextBox.Text);
cmd.Parameters.AddWithValue("#suburb", suburbTextBox.Text);
cmd.Parameters.AddWithValue("#city", cityTextBox.Text);
cmd.Parameters.AddWithValue("#res_Code", res_CodeTextBox.Text);
cmd.Parameters.AddWithValue("#industry_Vertical_ID", industry_Vertical_IDTextBox.Text);
cmd.Parameters.AddWithValue("#pO_Box", pO_BoxTextBox.Text);
cmd.Parameters.AddWithValue("#post_Office", post_OfficeTextBox.Text);
cmd.Parameters.AddWithValue("#postal_Code", postal_CodeTextBox.Text);
cmd.Parameters.AddWithValue("#country_ID", country_IDTextBox.Text);
cmd.Parameters.AddWithValue("#province_ID", province_IDTextBox.Text);
cmd.Parameters.AddWithValue("#prospect", prospectCheckBox.Checked);
cmd.Parameters.AddWithValue("#Company_ID", company_IDTextBox.Text);
cmd.ExecuteNonQuery();
{
MessageBox.Show("Update Success!");
con.Close();
}
In SQL Server, bool is mapped as a bit datatype with 0 and 1 values.
So what you need to do is:
"', prospect = '" + prospectCheckBox.Checked ? 1 : 0
Side-Note:
Don't concatenate strings to build up your query from user data input, this is vulnerable to SQL injection. Instead, use parameterized queries or stored procedures.
What DBMS platform are you using, and can you show the DDL for the table?
I can't guarantee this will work, but instead of using AddWithValue try using the Add method with explicit types declared:
cmd.Parameters.Add(new OleDbParameter("#People_Call_Status", OleDbType.VarChar));
cmd.Parameters.Add(new OleDbParameter("#Research_Date", OleDbType.VarChar));
...
cmd.Parameters.Add(new OleDbParameter("#prospect", OleDbType.Boolean));
cmd.Parameters.Add(new OleDbParameter("#Company_ID", OleDbType.VarChar));
cmd.Parameters[0].Value = Status_textBox1.Text;
cmd.Parameters[1].Value = Date_textBox.Text;
...
cmd.Parameters[16].Value = prospectCheckBox.Checked;
cmd.Parameters[17].Value = company_IDTextBox.Text;
Also, with regards to SQL Injection, you still have a theoretical vulnerability:
cmd.CommandText = #"UPDATE [" + tableName + "] SET"
+ "People_Call_Status = #People_Call_Status,"
+ "Research_Date=#Research_Date,"
...
+ "prospect = #prospect"
+ "WHERE Company_ID = #Company_ID ";
I realize it's an obscure possibility, but if the tableName variable were to contain this string or something like it:
Table1 set foo = 'bar';
truncate table ba2;
update table3
You could see how it would compile, execute and do something other than what you had in mind. Again, I realize this is reaching, and your input does come from a combo box, but it's still a theoretical risk.
I am trying to perform dynamic sql select where I am selecting from a table using a parameter.
SELECT null FROM #TableName
However I am getting error must declare table variable #TableName. I suspect this is because I am selecting from a table using a variable. I have not needed to do this before.
List<SqlParameter> sqlParams = new List<SqlParameter>()
{
new SqlParameter("TableName", "testtable"),
new SqlParameter("FieldName", "testfield"),
new SqlParameter("Find", "testfind"),
};
string sqlSelect = "SELECT null FROM #TableName
WHERE #FieldName LIKE '%' + #Find + '%' ";
DataTable dtSelect = SqlHelper.ExecuteDataset(sqlConn, CommandType.Text,
sqlSelect, 30, sqlParams.ToArray()).Tables[0];
//30 = timeout
How can I perform the above using dynamic sql? (no stored procedures please)
You cannot use parameters for things like table and column names. For those you could have a whitelist of possible values and then use string concatenation when building the SQL query.
You can't use parameters like that, so you have to build the query as a string. You could do that in SQL, but you can also just create the string in the C# code.
Make sure that the table name and field name are safe and trusted values, and doesn't come directly from an unsafe source like a web request.
string tableName = "testtable";
string fieldName = "testfield";
List<SqlParameter> sqlParams = new List<SqlParameter>() {
new SqlParameter("Find", "testfind"),
};
string sqlSelect =
"SELECT null " +
"FROM " + tableName + " " +
"WHERE " + fieldName + " LIKE '%' + #Find + '%' ";
private DataTable ExecuteDynamic(string TableName,string FieldName, string Find)
{
string sqlSelect = "SELECT * FROM " + TableName +
" WHERE " + FieldName + " LIKE '%'" + Find + "'%' ";
using (connection = new SqlConnection(Strcon))
connection.Open();
{
using (cmd = new SqlCommand(sqlSelect, connection))
{
cmd.CommandType = CommandType.Text;
cmd.CommandTimeout = 60;
adpt = new SqlDataAdapter(cmd);
dt = new DataTable();
adpt.Fill(dt);
return (dt);
}
}
}