I Have a problem with a prepared statement in C#:
OdbcCommand cmd = sql.CreateCommand();
cmd.CommandText = "SELECT UNIQUE_ID FROM userdetails WHERE USER_ID = ?";
cmd.Parameters.Add("#USER_ID", OdbcType.VarChar, 250).Value = email;
(of course email contains a valid email address, with # sign).
This code returns a random error -
"The connection has been disabled"
{"ERROR [01000] [Microsoft][ODBC SQL
Server Driver][TCP/IP
Sockets]ConnectionWrite (send()).
ERROR [08S01] [Microsoft][ODBC SQL
Server Driver][TCP/IP Sockets]General
network error. Check your network
documentation."}
However if I run my code without a prepared statement, meaning:
cmd.CommandText = "SELECT UNIQUE_ID FROM userdetails WHERE USER_ID = '"+email+"'";
Everything works perfectly.
Maybe it's related to the fact that I have a # sign in the parametrized value? I tend to think I'm not the first one trying to create a prepared statement with an email address...
I have no idea what's wrong! Other prepared statements work normally...
Can you please help? :)
Thanks,
Nili
Indeed, ODBC has its share of issues with supporting named parameters.
However, certain usage of named parameters is possible.
For example, in your case the following syntax works:
OdbcCommand cmd = sql.CreateCommand();
cmd.CommandText = "SELECT UNIQUE_ID FROM userdetails WHERE USER_ID = ?";
cmd.Parameters.Add("USER_ID", OdbcType.VarChar, 250).Value = email;
More tricky situation is when you don't have a unique match for the parameter like USER_ID = ?; e.g., when you want to use the IN operator in the WHERE clause.
Then the following syntax would do the job:
OdbcCommand cmd = sql.CreateCommand();
cmd.CommandText = "SELECT UNIQUE_ID FROM userdetails WHERE USER_ID IN (?, ?)";
cmd.Parameters.Add("?ID1", OdbcType.VarChar, 250).Value = email1;
cmd.Parameters.Add("?ID2", OdbcType.VarChar, 250).Value = email2;
Please note the usage of ? (question mark) instead of # (at sign) within the parameter name. Although note that substitution of parameters' values in this case has nothing to do with their names, but only with their order with the parameters collection.
I hope this helps :-)
Use '#USER_ID' instead of '?' and all should work:
OdbcCommand cmd = sql.CreateCommand();
cmd.CommandText = "SELECT UNIQUE_ID FROM userdetails WHERE USER_ID = #USER_ID";
cmd.Parameters.Add("#USER_ID", OdbcType.VarChar, 250).Value = email;
Is there a specific reason you're using OdbcCommand rather than using the SqlClient provider?
With the SqlClient provider, you should be using named parameters as others have suggested.
But according to MSDN:
The .NET Framework Data Provider for OLE DB and .NET Framework Data Provider for ODBC do not support named parameters for passing parameters to an SQL statement or a stored procedure. In this case, you must use the question mark (?) placeholder, as in the following example.
So I'm not sure named parameters will work in this case.
Related
FbCommand fbCmm =
new FbCommand("INSERT INTO PRODUTO
(CODIGO,EAN,DESCRICAO,VAL_PRODUTO,VAL_CUSTO,CAT_PRECO)"
+ "Values (#txt_codigo.Text, #txt_ean, #txt_descricao,
#txt_valPro, #txt_valCus, #txt_catPre)", ConexaoFirebird.Conexao);
What's wrong with that sentence?
I did a open connection in other class - ConexaoFirebird.Conexao();
You're executing a parameterized query without providing values for those parameters. See the documentation:
FbCommand cmd = new FbCommand("insert into t1(id, text) values (#id, #text);");
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add("#id", 123);
cmd.Parameters.Add("#text", "my string");
cmd.ExecuteNonQuery();
Here they bind the values 123 and "my string" to the parameters named id and text respectively.
Also note that parameter names are generally rescticted to alphanumeric, so txt_codigo.Text isn't likely going to work.
You should use quote for decimal, string field types, your statement is correct but not clear, you can create clear sql text with sql command builder or you can use Command object of your connection.
I am trying to execute a query with a condition like if username already present then update the row, else insert username and password.
This is my code below:
using (SqlCommand cmd = new SqlCommand("INSERT INTO Users(Username,Password) VALUES(#User,#password) ON DUPLICATE KEY UPDATE Username=VALUES(Username), Password=VALUES(Password)"))
{
cmd.Connection = con;
cmd.Parameters.AddWithValue("#User", TextBox3.Text);
cmd.Parameters.AddWithValue("#password", Pwd);
con.Open();
cmd.ExecuteNonQuery();
}
I got the following error:
Incorrect syntax near the keyword 'ON'.
I am not able to figure out what is wrong in this. Can anyone please help me out?
In SQL Server you need to use a query something like this:
-- check if exists (by username) - if found, update password
IF EXISTS (SELECT * FROM dbo.Users WHERE Username = #User)
UPDATE dbo.Users
SET Password = #password
WHERE Username = #User
ELSE
INSERT INTO dbo.Users(Username, Password)
VALUES(#User, #password)
And as mentioned in my comments - do not use the .AddWithValue function (see linked blog post for details) but use this instead:
cmd.Parameters.Add("#User", SqlDbType.VarChar, 100).Value = TextBox3.Text;
And also, please do not store your passwords in clear text in the database!
It looks like you're using MySQL syntax. I don't think SQL Server has ON DUPLICATE KEY. You'd probably want a MERGE statement.
#marc_s
String query = #"IF EXISTS (SELECT * FROM Users WHERE Username = # User)
UPDATE Users
SET Password = #password
WHERE Username = # User
ELSE
INSERT INTO Users(Username, Password)
VALUES(# User, #password)";
using (SqlCommand cmd = new SqlCommand(query))
I used the code you gave and used to debug points to check if the code is executing ,and it was, still it is not updating or Inserting the values .I cant run the query in SQL server cause each time i open the query window VSudio restarts,i am using trial version of Visual Studio
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.)
I am trying to develop an application ASP MVC 3 using the C # language and the Visual Studio 2010 and SQL Server 2005 data.
I want to make records in my database, but I can not because the parametres which i enter ,,,,are taken as NULL (when I put the cursor on the parameters in the statement of Insert (matricule, ...), the editor tells me that they are NULL)
This is the error which the application show :
The INSERT statement is in conflict with the FOREIGN KEY constraint "FK_Users_Account". The conflict occurred in database "Range" table "dbo.Account", column 'Type_User'.
The statement has been terminated.
PS
When I change this statement :
SqlCommand cmd = new SqlCommand("Insert Into Users(Matricule, Nom_User,PassWord, Type_User )Values('"+Matricule+"','"+Nom_User+"','"+passWord+"','"+Type_User+"')", cn);
By this :
SqlCommand cmd = new SqlCommand("Insert Into Users(Matricule, Nom_User,PassWord, Type_User )Values('user2','anouar','anouar','Admin')", cn);
It's working manually that's mean without putting the values in the form
Thanks for the answers , I changed the code like this but always the same problem :
public int Insert(string Matricule, string Nom_User, string passWord, string Type_User, string ID_UF)
{
SqlConnection cn = new SqlConnection(#"Data Source = SWEET-DE396641E \ SQLEXPRESS; User Id = adminUser; Password = adminUser; Initial Catalog = Gamme");
cn.Open();
string sqlquery = ("Insert Into Users(Matricule, Nom_User,PassWord, Type_User, ID_UF )Values(#Matricule, #Nom_User, #passWord, #Type_User, #ID_UF)");
SqlCommand cmd = new SqlCommand(sqlquery, cn);
cmd.Parameters.AddWithValue("#Matricule", this.Matricule);
cmd.Parameters.AddWithValue("#Nom_User", this.Nom_User);
cmd.Parameters.AddWithValue("#passWord", this.passWord);
cmd.Parameters.AddWithValue("#Type_User", this.Type_User);
cmd.Parameters.AddWithValue("#ID_UF", this.ID_UF);
return cmd.ExecuteNonQuery();
}
and this the error :
The parameterized query '(# Matricule nvarchar (4000), # user_name nvarchar (4000), # passWord nv' expects parameter # Club number has not been specified.
You might be confusing database null values and c# null values. Try sending in DBNull.Value for any null values.
Also, I would recommend that you use parameterized queries. They make your code easier to read and avoids serious security issues (even if this is just homework, it's best to practice safe code).
Something like this (not tested, but the concept is here)...
SqlCommand cmd = new SqlCommand("Insert Into Users(Matricule, Nom_User,PassWord, Type_User )Values(#Matricule, #Nom_User, #passWord, #Type_User)", cn);
cmd.Parameters.Add("#Matricule", Matricule ?? DBNull.Value);
cmd.Parameters.Add("#Nom_User", Nom_User?? DBNull.Value);
cmd.Parameters.Add("#PassWord", PassWord?? DBNull.Value);
cmd.Parameters.Add("#Type_User ", Type_User ?? DBNull.Value);
First of all, as Nomad101 suggested, you need to be sure your post fields are being populated and that your controller method has the [HttpPost] attribute on it and debug/step into your code to verify the values are populated.
Second, the way you are creating your query is leaving you wide open to hacker attacks. Never, ever concatenate your parameters into your query. I notice that Brian posted a description of the correct way as I was typing this. Additionally, you'll want to learn about the Data Access Object design pattern I alluded to here.
well, the question is clear i hope, the code is this:
string sql = "delete from #tabelnaam";
SqlCommand sc = new SqlCommand();
sc.Connection = getConnection();
sc.CommandType = CommandType.Text;
sc.CommandText = sql;
SqlParameter param = new SqlParameter();
param.Direction = ParameterDirection.Input;
param.ParameterName = "#tabelnaam";
param.Value = tableName;
sc.Parameters.Add(param);
OpenConnection(sc);
sc.ExecuteScalar();
tableName is supplied to this function.
I get the exception:
Must declare the table variable #tabelnaam
IIRC, you cant use a substitute the table name for a parameter.
Rather build the SQL string containing the correct table name.
Make to changes
rather than using paramter use this
string sql = string.format( "delete from {0}",tableName);
make use of executenonquery intead of ExecuteScalar
sc.ExecuteNonQuery();
As mentioned by others, you can't parameterise the table name.
However, as you rightly mention in comments on other answers, using simple string manipulation potentialy introduces a SQL injection risk:
If your table name input is fro an untrusted source, such as user input, then using this:
string sql = string.format( "DELETE FROM {0}",tableName);
leaves you open to the table name "myTable; DROP DATABASE MyDb" being inserted, to give you:
DELETE FROM myDb; DROP DATABASE MyDB
The way round this is to delimit the table name doing something such as this:
string sql = string.format("DELETE FROM dbo.[{0}]", tableName);
in combination with checking that the input does not contain either '[' or ']'; you should probably check it also doesn't contain any other characters that can't be used as a table name, such as period and quotes.
I dont think you can parameterize the table name. From what I have read you can do it via Dynamic sql and calling sp_ExecuteSQL.
Your SQL is incorrect, you are deleting from a table variable yet you haven't defined that variable.
Update: as someone has pointed out, you are trying to dynamically build a query string but have inadvertantly used SQL parameters (these do not act as place holders for string literals).
More here:
Parameterise table name in .NET/SQL?
You cannot parameterise the table name, you have to inject it into the command text.
What you can and should do is protect yourself against SQL injection by delimiting the name thus:
public static string Delimit(string name) {
return "[" + name.Replace("]", "]]") + "]";
}
// Construct the command...
sc.CommandType = CommandType.Text;
sc.CommandText = "delete from " + Delimit(tableName);
sc.ExecuteNonQuery();
See here and here for more background info.