Command parameters - c#

How to correct send parameters to oledb query?
MyCode is
cmd.CommandText = "UPDATE #target SET [#columnname] = Replace([#columnname], Chr(10), '');";
cmd.Parameters.Add(new OleDbParameter("#target", OleDbType.VarChar)).Value = tb_tablename.Text.Trim();
cmd.Parameters.Add(new OleDbParameter("#columnname", OleDbType.VarChar)).Value = column.ColumnName;
And it's not working). I need to add in query #target ( table name ) and #columnname ( column name ).
Modified to code with ?
cmd.CommandText = "UPDATE ? SET [?] = Replace([?], Chr(10), '');";
cmd.Parameters.Add(new OleDbParameter("#target", OleDbType.VarChar)).Value = tb_tablename.Text.Trim();
cmd.Parameters.Add(new OleDbParameter("#columnname", OleDbType.VarChar)).Value = column.ColumnName;
cmd.Parameters.Add(new OleDbParameter("#columnname", OleDbType.VarChar)).Value = column.ColumnName;
Got error:
syntax error in update statement
Concatenation style got error
string query = "UPDATE " + tb_tablename.Text.Trim() + " SET [" + column.ColumnName + "] = Replace([" + column.ColumnName + "], Chr(10), '');";
data type mismatch in criteria expression
Full code:
DataTable dt = new DataTable();
using (OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM " + tb_tablename.Text, conn))
{
adapter.Fill(dt);
}
foreach (DataColumn column in dt.Columns)
{
if (column.DataType == typeof(String))
{
if (column.ColumnName != "ID1" && column.ColumnName != "ID" && column.ColumnName != "Geometry" && column.ColumnName != "Geometry_SK")
{
string query = "UPDATE " + tb_tablename.Text.Trim() + " SET [" + column.ColumnName + "] = Replace([" + column.ColumnName + "], Chr(10), '');";
using (OleDbCommand cmd = new OleDbCommand(query, conn))
{
cmd.ExecuteNonQuery();
}
}
}
}
Whats helped: string query = "UPDATE " + tb_tablename.Text.Trim() + " SET " + column.ColumnName + " = Replace(" + column.ColumnName + ", Chr(10), \"\") WHERE " + column.ColumnName + " <> \"\";";
Blank data + reserved column name brokes all. ColumnNames Date,Type,Note brokes all - exclude it from cycle.

You're getting a syntax error because cannot make a SQL identifier (table name, column name etc) a parameter. Only values can be parameterized
Your query would hence have to look like:
cmd.CommandText = "UPDATE "+tb_tablename.Text+" SET ["+...+"] = Replace(["+...+"], Chr(10), '');";
Never concatenate values supplied by the user, into an SQL. Because you're forced in this instance to concat take and column names in you should absolutely make sure that only safe values are provided. Ideally you should take the value provided for the the table name and column name and have a lot of all table and column names (you can query the db for this) and only permit the sql to build if the values provided are in that list
This is a very unusual requirement- almost no one here seeks to parameterize table names etc. If you're trying to write some sort of mini library to make your data access life easier, I would recommend you use one that already exists like Dapper

You indicated in a comment that you're trying to run a replace on all columns in a db with minimal effort. For this you can consider the following:
use the GetSchema method of your DbConnection object to get a list of the tables in the db
loop Over it, concatenate a string sql of the table name into "SELECT * FROM "+tablename+" WHERE 1=0" and run this sql using a DataAdapter to return an empty datatable with all the columns of the target table
loop over the datatable.Columns collection returned from the above select, running your REPLACE sql, subbing the table and column names in via string concat (it's safe and non hackable because you retrieved the list and are not concatting values provided by a user
if you have non string columns (dates,ints) then examine the datatype of the DataColumn and only run th replace if it's a string/varchar or similar
Helpful links:
https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/getschema-and-schema-collections
https://sizious.com/2015/05/11/how-to-load-an-access-database-into-a-dataset-object-in-c/ - goes part way- add a where clause to this guy's code so that no rows are returned (you only want the columns)

You cannot substitute table and column names with parameters.
Parameters can only be applied as follows:
UPDATE SomeTable SET SomeColumn = ?
It is best to allow the user to choose the names of tables and columns from Comboboxes/ListBoxes with ready-made values. Something like this:
var table = tablesComboBox.SelectedItem;
var column = columnsComboBox.SelectedItem;
var query = "UPDATE " + table + " SET " + column +
" = Replace(" + column + ", Chr(10), '''');";
Note that you must escape single quote characters.

Related

Pass Null Values In A SQL Command (For Two Columns) - Adding In Foreach Loop

I want to select rows from my SQL Server table (it has 3 columns) and to display them into my Datagridview. My problem about null values. How can I pass null values? (Sometimes the first column and the second column are empty.
).
Below is my code:
string cm = "SELECT column1, column2, column3 FROM mytablename WHERE column1='"
+ sIS[mSI] + "' AND column2='" + sR[mSSI] + "' OR column1='" + sR[mSSI]
+ "' AND column2='" + sIS[mSI] + "'";
Note: I edited my code.
You should be using parameters to pass values into a SQL statement or else you will be vulnerable to SQL injection attacks. You can create a SqlCommand object, create SqlParameter objects, then set values on them. If any of your values are null, then you can pass DBNull.Value as the parameter value.
SqlCommand cmd = con.CreateCommand();
string cm = "SELECT column1, column2, column3 "
cm += "FROM mytablename "
cm += "WHERE column1=#mSI "
cm += "AND column2=#mSSI OR column1=#mYSI AND column2=#mSI";
cmd.CommandText = cm;
for(int mSSI=0; mSSI<sR.Count(); mSSI++)
{
cmd.Parameters.AddWithValue("#mSI ", sR[mSI]);
// check for a null value
if (sr[mSSI] == null)
{
cmd.Parameters.AddWithValue("#mSSI", DBNull.Value);
}
else
{
cmd.Parameters.AddWithValue("#mSSI", sR[mSSI]);
}
cmd.Parameters.AddWithValue("#mYSI", sR[mYSI]);
SqlDataAdapter sd = new SqlDataAdapter(cmd);
DataTable dat = new DataTable();
sd.Fill(dat);
// clear parameters after each iteration
cmd.Parameters.Clear()
}
I think the answer to your question is using "DBNull.Value" as mentioned above, something like this;
string cm = "SELECT column1, column2, column3 FROM mytablename WHERE column1='"
+ DBNull.Value + "' AND column2='" + DBNull.Value + "' OR column1='" + sR[mSSI]
+ "' AND column2='" + DBNull.Value + "'";

Using Subquery as Parameter Value [duplicate]

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.

Read Data from .dbf File with OdbcConnection

I am using visual studio 2010 on Win 7. I want to read a .dbf file and get the minimum value of a selected column.
Here is what I have:
System.Data.Odbc.OdbcConnection oConn = new System.Data.Odbc.OdbcConnection();
oConn.ConnectionString = #"Driver={Microsoft dBase Driver (*.dbf)};SourceType=DBF;SourceDB=" + ImportDirPath + ";Exclusive=No; Collate=Machine;NULL=NO;DELETED=NO;BACKGROUNDFETCH=NO;";
oConn.Open();
// Update time
string nowTime = DateTime.Now.ToString("HHmmss");
oCmd.CommandText = #"UPDATE " + tableName + " SET HQCJBS = " + nowTime + " WHERE HQZQDM = ?";
oCmd.Parameters.AddWithValue("row2", "000000");
oCmd.ExecuteNonQuery();
string query = "SELECT MIN(" + colName + ") FROM " + tableName + " WHERE HQZQDM <> 000000";
OdbcDataAdapter da = new OdbcDataAdapter(query, oConn);
DataSet ds = new DataSet();
da.Fill(ds);
Suppose colName and tableName are correct. I have two question.
Two Questions:
When the code da.Fill(ds); is hit, I got an error data type mismatch in criteria expression access, What is wrong?
After I get the minimum value from the database, how can I input it into the memory as a double, for example double min = ds.Tables[0];
Your update command should apply TWO parameters... one for the set, another for the where clause. Use the "?" place-holder for each respectively and add the parameters in the same order as they appear in the query.
string nowTime = DateTime.Now.ToString("HHmmss");
oCmd.CommandText = #"UPDATE " + tableName + " SET HQCJBS = ? WHERE HQZQDM = ?";
oCmd.Parameters.AddWithValue("setParm", nowTime );
oCmd.Parameters.AddWithValue("whereParm, "000000");
oCmd.ExecuteNonQuery();
For your select MIN() query, it appears your WHERE criteria column is a string and by having the literal numbers without quotes is applying it as a numeric... Again, stick with "?" parameters
OdbcCommand getMinCmd = new OdbcCommand("", oConn);
getMinCmd.CommandText = "SELECT MIN(" + colName
+ ") FROM " + tableName + " WHERE HQZQDM <> ?";
getMinCmd.Parameters.AddWithValue("whereParm, "000000");
OdbcDataAdapter da = new OdbcDataAdapter(getMinCmd);
DataSet ds = new DataSet();
da.Fill(ds);
Finally, to get the value OUT of the retrieved query into memory, you need to get the row of the table (only 1 record result set, zero-based index) and column-0 too. Since you did not assign a column name, you don't know the column and just go with 0-index...
int lowestValue = (int)ds.Tables[0].Rows[0][0];
Think of the above as the hierarchy...
ds
tables[0]
rows[0]
[column 0]
rows[1] -- but your query would only have one row anyhow
[column 0]
tables[1] -- if your query had multiple queries, this might be available
but at least it shows where the pieces are.
Now, if you change your query slightly to something like
select MIN( colName ) as MyMinValue ...
then your reference would be where you explicitly name the column from the row retrieved
int lowestValue = (int)ds.Tables[0].Rows[0]["MyMinValue"];

How to insert bind column and unbind column datagridview values in database

I am inserting datagirdview column values into database. Datagridview has 4 columns 1st column is bind to a table of database. I have written this query to insert all this data to my table but I am getting error "invalid column name 'w'". Somebody help me to figure it out. In the database table I have these columns: SupplierId, Item, Quantity, PricePerItem,Total,BillNo ..The Query I used is :
string q = #" INSERT INTO PurchaseInvo(SupplierId,Item,Quantity,PricePerItem,Total,BillNo) VALUES (" + comboBox1.Text + ", " + dataGridView1.Rows[i].Cells["Item"].Value + ", " + dataGridView1.Rows[i].Cells["Quantity"].Value + ", " + dataGridView1.Rows[i].Cells["PricePerItem"].Value + ", " + dataGridView1.Rows[i].Cells["Total"].Value + ", " + bill + ")";
string q =
#" INSERT INTO PurchaseInvo
(SupplierId, Item, Quantity, PricePerItem, Total, BillNo)
VALUES
(#SupplierID, #Item, #Quantity, #PricePerItem, #Total, #Bill)";
SqlCommand cmd = new SqlCommand(q, connectionString);
cmd.Parameters.AddWithValue("#SupplierID", comboBox1.Text);
cmd.Parameters.AddWithValue("#Item", dataGridView1.Rows[i].Cells["Item"].Value);
cmd.Parameters.AddWithValue("#Qauntity", dataGridView1.Rows[i].Cells["Quantity"].Value);
cmd.Parameters.AddWithValue("#PricePerItem", dataGridView1.Rows[i].Cells["PricePerItem"].Value);
cmd.Parameters.AddWithValue("#Total", dataGridView1.Rows[i].Cells["Total"].Value);
cmd.Parameters.AddWithValue("#Bill", bill);
cmd.ExecuteNonQuery();
You should always use sql command parameters. This will prevent you from sql injection and also from errors like this. The code written like this should work.

C# Parameterized Oracle Update fails on ExecuteNonQuery

I am attempting to dynamically update a set of database tables. I have two variables;
table_name & field_name. These are populated by a foreach loop, that loops through a DataTable. Everytime we hit a new row in the DataTable the names change respectively. Within this loop I create a new Oracle Connection and attempt to write an update with the current table_name/field_name. But Oracle keeps giving me an error on my ExcecuteNonQuery command.
Any help is greatly appreciated!!
EDIT: I have reformatted to include parameters, still does not work does anyone have any ideas on what I am doing wrong?
foreach (DataRow fieldtable in setofTables.Tables[0].Rows)
{
//do work
table_name = fieldtable["table_name"].ToString().Trim();
field_name = fieldtable["field_name"].ToString().Trim();
MessageBox.Show(table_name + field_name);
//create parameters
OracleParameter fieldParamater = new OracleParameter("field_name", OracleDbType.Varchar2);
OracleParameter diffParameter = new OracleParameter("mark_diff_oracle", OracleDbType.BinaryFloat);
OracleParameter wellIdParameter = new OracleParameter("id", OracleDbType.Char);
//wellIdParameter.Size = 10;
//create oracle connection and open
OracleConnection OrclCon2 = new OracleConnection("Data Source=" + dbname + "; User Id=" + userid + ";Password=" + password1 + ";");
OrclCon2.Open();
//prepare sql to be passed to oracle
string UpdateOraSQL = "UPDATE " +table_name+ " set :field_name = :field_name - (:mark_diff_oracle) where id = ':id' and :field_name is not null;";
MessageBox.Show(UpdateOraSQL);
//create dommand
OracleCommand UpdateDB = new OracleCommand(UpdateOraSQL, OrclCon2);
UpdateDB.CommandType = CommandType.Text;
//add parameters
UpdateDB.Parameters.Clear();
UpdateDB.Prepare();
UpdateDB.Parameters.Add(fieldParamater).Value = field_name;
UpdateDB.Parameters.Add(diffParameter).Value = mark_diff_oracle;
UpdateDB.Parameters.Add(wellIdParameter).Value = id;
Remove the semicolon from the end of the sql statement. Change the following code
string UpdateOraSQL = "UPDATE " +table_name+ " set :field_name = :field_name - (:mark_diff_oracle) where id = ':id' and :field_name is not null;";
to
string UpdateOraSQL = "UPDATE " +table_name+ " set :field_name = :field_name - (:mark_diff_oracle) where id = ':id' and :field_name is not null";
See the following link for more information
why the semicolon couldn't place in the CommandText of a OracleCommand when C#
If the problem is still not resolved, it might be helpful if you post the entire exception message also.
AFAIK, you cannot use parameters to define the column that you're updating.
AFAIK, you can only use parameters for the values that you'd want to set.
So, you'll have to create the query using string concat:
string sql = "UPDATE " + tableName + " SET " + fieldName + " = :p_Value WHERE id = :p_Id";
OracleCommand UpdateDB = new OracleCommand(sql, OrclCon2);
UpdateDB.Parameters.Add ("p_Value", ... ).Value = "foo";
UpdateDB.Parameters.Add ("p_Id", ...).Value = 4;
Offcourse, you should make sure that the variables you're adding to the string do not contain any harmfull statements. You should do sanity checks on them.
Perhaps, you can even verify if the tableName or the fieldName that has been passed, is a valid / existing tableName/columnname.
In SQL, one does not say COLUMN <> NULL. The proper syntax is COLUMN IS NOT NULL.

Categories