SQLite command.Parameters.Add() not working - c#

Here's my code.
public void setUpdate(List<string> code, string tableName)
{
SQLiteConnection con = new SQLiteConnection(connection);
SQLiteCommand UPDATE = new SQLiteCommand("UPDATE #TableName SET #ColumnName = #Value WHERE Key = #PK", con);
UPDATE.Parameters.AddWithValue("#TableName", "TEST");
UPDATE.Parameters.AddWithValue("#ColumnName", code[1]);
UPDATE.Parameters.AddWithValue("#Value", code[2]);
UPDATE.Parameters.AddWithValue("#PK", code[0]);
using (con)
{
con.Open();
UPDATE.ExecuteNonQuery();
}
}
And I'm getting this exception
System.Data.SQLite.SQLiteException: 'SQL logic error
near "#TableName": syntax error'
I already tried using
UPDATE.Parameters.Add(new SQLiteParameter("#TableName", DbType.String) .Value = tableName);
Still getting the same exception.
I don't know anymore how to solve this.
I don't wanna use the concatenation because it screws up the query when you pass a value like the one below.
Smith's
EDIT:
I placed a breakpoint on
using (con)
Then checked the commandText. The result is:
"UPDATE #TableName SET #ColumnName = #Value WHERE Key = #PK"

I think there is the problem with table name as a parameter.
So firstly try to left all parameters except of table name (hardcode 'TEST' into query temporarily) and if it works take a look on this:
C# query with dynamic tablename

Again, trying to build a query with from and column names you can't do as PARAMETER. They need to be fixed in the string. BUT CAUTION. DO NOT Allow the table/column/etc parts that you build come from an untrusted source, especially the web for damage of SQL-Injection.
If your system is controlling the origin AND QUALIFIED, or otherwise internally control the table name being passed in, AND you control / qualify the column name being passed in, I would adjust your function as follows:
public void setUpdate(List<string> code, string tableName)
{
SQLiteConnection con = new SQLiteConnection(connection);
SQLiteCommand UPDATE = new SQLiteCommand(
"UPDATE " + tableName + " set " + code[1] + " = #Value WHERE Key = #PK", con);
UPDATE.Parameters.AddWithValue("#Value", code[2]);
UPDATE.Parameters.AddWithValue("#PK", code[0]);
using (con)
{
con.Open();
UPDATE.ExecuteNonQuery();
con.Close();
}
}
Again, this is on the premise that YOU are controlling and sanitizing the origins of the tableName parameter, and your code array, second element via [1] representing the column name. The setting value EQUAL TO and where key EQUALS are ok for parameters.
And if that does not work, I would start with a query that you know is legit/clear just to TEST the functionality with parameters.
"UPDATE YourTable set YourColumn = #Value WHERE Key = #PK"

Related

Setting SQL query parameter to Int32 in C#

I'm having problems with some code I'm trying to write. I'm doing something for suppliers orders, so I have a table which is named "encomendas_fornecedores" with a autoincrement field before the key that is the code of sale which consists in a EF before the number(which is a text field).
Here is the code:
connection.Open();
OleDbCommand comando1 = new OleDbCommand();
OleDbCommand comando2 = new OleDbCommand();
OleDbCommand comando3 = new OleDbCommand();
comando1.Connection = connection;
comando2.Connection = connection;
comando3.Connection = connection;
comando1.CommandText = "INSERT INTO encomendas_fornecedores (cod_encomenda_forn, cod_metodo, cod_forn, total_pagar_forn) VALUES('FO', '" + txtcodmetodo.Text + "', '" + txtcodforn.Text + "', '" + lbltotalapagar.Text + "'); ";// insert into table the values with a FO to cod
comando1.ExecuteNonQuery();
comando2.CommandText = "Select MAX(num_encomenda) From encomendas_fornecedores;";// selecting maximum num encomenda so I can isolate it and add to a text before(btw I do this in php/sql no problems
int numero = Convert.ToInt32(comando2.ExecuteScalar());//max num_encomenda
string codencomendaforn= "EF"+Convert.ToString(numero);// sales code completed
comando3.CommandText = "UPDATE encomendas_fornecedores SET cod_encomenda_forn = '"+codencomendaforn+"' WHERE num_encomenda = '"+ numero +"';";//query that is giving me the problems, it says something like "type of data incorrect in data expression"
comando3.ExecuteScalar();//giving me error this line
connection.Close();
But now here's the catch the cod_encomenda_forn is text and the num_encomenda auto increment as it is in the sql, and I tried to show the query in a textbox to see if its anything is wrong but nothing seems wrong.
"UPDATE encomendas_fornecedores SET cod_encomenda_forn = '"+codencomendaforn+"' WHERE num_encomenda = **'**"+ **numero** +"**'**;";//query that is giving me the problems,it says something like "type of data incorrect in data expression"
You are passing a string numero to a where statement that seems like it is expecting a number. As long as it is numeric it should work, but definitely not gauranteed to work. Second you are passing anothercodencomendaforn string to encomenda what is encomenda 's data type?
It appears that you are not handling potential datatype differences between your c# code and your SQL query. In addition single quoting '' around a value in a SQL statement tells the database engines that it is a string even if that is '1234'. While SQL will automatically convert some values it doesn't always. In addition c# .net library also looks for some conversion etc. before sending the SQL statement. To fix appropriately use parameters that are data typed to the database type in the SQL table. To fix it simply in the statement figure out your data types and fix the '' single quotes appropriately.
PS the people trying to help you in the comments were being nice and telling you the professional way of keeping your job in the future when you graduate after fixing this issue.

OleDBException was unhandled: Syntax error in query (Incomplete query clause)

I'm trying to execute a very simple SQL statement on an Access database through C#.
The statement is something like this:
select M_PASSWORD from TB_USERS where M_USERNAME = 'myuser'
and this is the C# code I'm using to execute the SQL statement:
string connString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + sources.global_variables.db_source;
using (OleDbConnection connection = new OleDbConnection(connString))
{
connection.Open();
OleDbDataReader reader = null;
OleDbCommand command = new OleDbCommand("SELECT #1 from #2 WHERE #3='#4'", connection);
command.Parameters.AddWithValue("#1", db_column);
command.Parameters.AddWithValue("#2", db_table);
command.Parameters.AddWithValue("#3", db_where_column);
command.Parameters.AddWithValue("#4", db_where_value);
reader = command.ExecuteReader();
//rest of code
Once I get to the line reader = command.ExecuteReader();, the reader fails the execution of the query giving me the following error message: OleDBException was unhandled: Syntax error in query (Incomplete query clause).
I've debugged the code to see if I could see any wrong assignment in the parameters values, but they look fine.
Moreover, executing the exact same query on the Query Analyzer of the Database, I retrieve the value I want.
Could anyone give a tip to spot the problem and understand where I'm wrong?
I think you cant pick column names as parameter such that. It might be the problem.
Use if statement or other conditional statements for parameter and move your query to inside of your conditional statement.
I don't believe that parameters can be used in the fashion you posted. Parameters are used for filling in values (ie, placing a DateTime value into an update statement as the value of a DateTime column to be updated in a table).
Try changing your code such that the column names and table names are provided in text or are filled in as a string. You can build the query string up if you want to fill in different column names, different table names, and different column names in your where clause. So instead of what you posted, try something more like this:
string connString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + sources.global_variables.db_source;
using (OleDbConnection connection = new OleDbConnection(connString))
{
connection.Open();
OleDbDataReader reader = null;
string strQuery = "SELECT " + constStringColumnName1 + " FROM " + theTableNamePassedInAsString + " WHERE " + strWhereClauseBuiltEarlierInThisFunction + " = '#1'";
OleDbCommand command = new OleDbCommand( strQuery , connection);
command.Parameters.AddWithValue("#1", db_where_value);
reader = command.ExecuteReader();
//rest of code
}
Of course, you could format the string and plug in your changing selection column name, your table name, and your where clause. Build your select/command string, then use Parameters to fill in the actual value is the normal usage.
Try remove the ' on where parameter and use ? insted of # like that
OleDbCommand command = new OleDbCommand("SELECT ? from ? WHERE ?=?", connection);
command.Parameters.AddWithValue("column", db_column);
command.Parameters.AddWithValue("table", db_table);
command.Parameters.AddWithValue("where_column", db_where_column);
command.Parameters.AddWithValue("where_value", db_where_value);
I dont know if you can use parameters on column name. If it won´t running try to execute the query without parameters using concat and only use parameters on where value

Create Table SQL query - select table name from string

I'm attempting to programmatically create a SQL table. I can create a table with a query, this is no issue at all. But I'd like the table name to have some relevance to the data inserted into it, as it's being used for quotations and invoices. Data entered from a DataGridView will be inserted into it (probably via bulkcopy, or something similar).
using (SqlCeCommand command = new SqlCeCommand(
"CREATE TABLE table1' (Weight INT, Name NVARCHAR, Breed NVARCHAR)", con))
works perfectly. However I'd like this code to work:
using (SqlCeConnection con = new SqlCeConnection(#"Data Source=|DataDirectory|\LWADataBase.sdf"))
{
con.Open();
try
{
string tableName = "" + quotenameTxt.Text + "-" +firstTxt.Text+ "-" + surenameTxt.Text;
using (SqlCeCommand command = new SqlCeCommand(
"CREATE TABLE '"+tableName.ToString()+"' (Weight INT, Name NVARCHAR, Breed NVARCHAR)", con))
{
command.ExecuteNonQuery();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Any suggestions? I get an error (as expected) but are unsure what I need to do.
I'm using SqlCe (and before anyone says "BulkCopy isn't supported", I know, I've got a reference that allows it)
The error I get is :
There was an error parsing the query. [ Token line number = 1,Token line offset = 16,Token in error = 1-2-3 ]
// "1-2-3" being the textbox values.
Change the dashes to underscores or surround the entire table name with [square brackets]
As was mentioned in comments above, make the following changes:
using (SqlCeCommand command = new SqlCeCommand(
"CREATE TABLE '"+tableName+"' (Weight INT, Name NVARCHAR, Breed NVARCHAR)", con))
tableName is already a string. No need to use .ToString() on it.
Also, you have a leading white space in your declaration of tableName:
string tableName = "" + quotenameTxt.Text + "-" + firstTxt.Text + "-"
+ surenameTxt.Text;
This makes the string " 1-2-3", not the "1-2-3" you are expecting.
Lastly, surround your tableName with [] to get it to work correctly:
using (SqlCeCommand command = new SqlCeCommand(
"CREATE TABLE '[" + tableName + "]' (Weight INT, Name NVARCHAR, Breed NVARCHAR)", con))

why we use "#" while inserting or updating or deleting data in sql table

I just want to know why we use "#" while inserting or updating or deleting data in sql table, as I used #name like below.
cmd.Parameters.Add(new SqlParameter("#fname", txtfname.Text));
See: SqlParameter.ParameterName Property - MSDN
The ParameterName is specified in the form #paramname. You must
set ParameterName before executing a SqlCommand that relies on
parameters.
# is used by the SqlCommand so that the value of the parameter can be differentiatd in the Command Text
SqlCommand cmd = new SqlCommand("Select * from yourTable where ID = #ID", conn);
^^^^^^^
//This identifies the parameter
If # is not provided with the parameter name then it is added. Look at the following source code, (taken from here)
internal string ParameterNameFixed {
get {
string parameterName = ParameterName;
if ((0 < parameterName.Length) && ('#' != parameterName[0])) {
parameterName = "#" + parameterName;
}
Debug.Assert(parameterName.Length <= TdsEnums.MAX_PARAMETER_NAME_LENGTH, "parameter name too long");
return parameterName;
}
}
EDIT:
If you don't use # sign with the parameter then consider the following case.
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand cmd = new SqlCommand())
{
conn.Open();
cmd.CommandText = "SELECT * from yourTable WHERE ID = ID";
cmd.Connection = conn;
cmd.Parameters.AddWithValue("ID", 1);
DataTable dt = new DataTable();
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
}
}
The above will fetch all the records, since this will translate into SELECT * from yourTable WHERE 1=1, If you use # above for the parameter ID, you will get only the records against ID =1
OK, no offense to the posters before me but I will try to explain it to you as simple as possible, so even a 7 year old understands it. :)
From my experience '#' in .SQL is used when you are "just not making it clear what exact data type or exact name will be used". "Later" you are pointing out what the exact value of '#' is.
Like, say, someone has developed some huge .SQL query which contains, say, the name of every person who has received it.
SELECT column_name,column_name FROM table_name WHERE column_name = #YOURNAME;
#YOURNAME = 'John Doe';
So, in this case, it's easier for everyone to just write their name at #YOURNAME and it will automatically convert the query to (upon launch):
SELECT column_name,column_name FROM table_name WHERE column_name = 'John Doe';
P.S: I am sorry for my syntax errors and incorrect terminology but I am sure you should have understood it by now. :)
Variables and parameters in SQL Server are preceded by the # character.
Example:
create procedure Something
#Id int,
#Name varchar(100)
as
...
When you create parameter objects in the C# code to communicate with the database, you also specify parameter names with the # character.
(There is an undocumented feature in the SqlParameter object, which adds the # to the parameter name if you don't specify it.)

My SQLParameter isn't passing NULL correctly

I have this C# webform that has has a date picker box. If the date is set to nothing (the default) I want it to pass NULL to the database. This happens inside my parametrized query.
SqlParameter CMActionDate = new SqlParameter();
CMActionDate.ParameterName = "#ActionDate";
if (ActionDate.Equals(""))
{
CMActionDate.Value = System.Data.SqlTypes.SqlDateTime.Null;
}
else
{
CMActionDate.Value = ActionDate;
}
When I turn on debugging I see that the date is indeed "" so it goes into the IF statement and sets the actiondate.value to {Null} like I think it should.
However.
When it then goes to execute the nonquery, I click the magnifying glass and see this:
UPDATE table SET [action_date] = '' WHERE [id] = 2488
What I would like to see is this:
UPDATE table SET [action_date] = 'Null' WHERE [id] = 2488
Since the action_date never really gets set to NULL, then the value in the datetime field reverts to "01/01/1900 12:00:00AM" and that's a pain in itself.
I have tried setting CMActionDate.Value to the following values to no avail (I get the same result as above.):
DBNull.Value;
"NULL";
SqlDateTime.Null;
null;
Yes, of course the parametrized query looks like this:
"UPDATE CM_Codebase SET [action_date] = '" + #ActionDate + "' WHERE [id] = " + #CM_id + "";
But when I am debugging this thing in VS, I put a breakpoint right before ExecuteNonQuery(); so I can see the SQL it's trying to run. It's there that I see the actual SQL and see the bit where action_date=''.
You shouldn't see either '' or 'Null'. If you're using parameterized queries correctly it should look like this:
UPDATE table SET [action_date] = #ActionDate WHERE [id] = #ID
The whole point of a parameterized query is that the actual parameter value is never substituted directly into the query string.
Your query code should look something like this:
string sql = "UPDATE table SET [action_date]= #ActionDate WHERE [id]= #CM_id";
using (var cn = new SqlConnection("your connection string here."))
using (var cmd = new SqlCommand(sql, cn))
{
cmd.Parameters.Add("#ActionDate", SqlDbTypes.DateTime).Value =
ActionDate.Equals("")? DBNull.Value : DateTime.Parse(ActionDate);
cmd.Parameters.Add("#CM_id", SqlDbTypes.Int).Value = 2488;
cn.Open();
cmd.ExecuteNonQuery();
}
The result of this code is that your query parameters are sent to the server as data. At no point in your C# code will you ever be able to view the query string with your data substituted in: it's sent to the server separately.
This prevents any possibility of the server executing a parameter value as code because of an error in sanitizing your parameter value. The data is completely separate, and doesn't need to be sanitized for that context in the first place. It also allows the server to cache and reuse the execution plan for the query, resulting in a (small) performance boost.
Your parametized query should show
UPDATE table SET [action_date] = #ActionDate WHERE [id] = #id
And the parameter value should have a null equivalent value.
Your sql is
"UPDATE CM_Codebase SET [action_date] = '" + #ActionDate + "'
WHERE [id] = " + #CM_id + "";
Which doesn't really make sense. You should let sql replace the #ActionDate and #CM_ID, not build a dynamic sql query.
Your sql should literally be:
String sql = "UPDATE table SET [action_date] = #ActionDate WHERE [id] = #CM_id"
There should be no string concatenation around the variables, and they should not be wrapped in quotes.
Your query most certainly does not look like the ones posted.
Your #parameter needs to be inside your string, in order to be read correctly. You are seeing ActionDate = '' because #ActionDate does not exist, most likely.
You need something like
string sql = "UPDATE CM_Codebase SET [action_date] = #ActionDate WHERE [id] = #CM_id";
Notice that there is no string concatenation taking place.

Categories