pass null parameter to SQL server query - sql

How can I pass a null parameter to a SQL server query.
I have a simple table with a nullable int column.
If I pass a .NET null value, I get a sql error. If I pass DBNull.Value, no row matches the filter. Is there a simple way to do this without using ISNULL.
OleDbConnection connection = new OleDbConnection();
connection.ConnectionString = ...;
connection.Open();
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = connection;
cmd.CommandText = "select * from myTable where myColumn = ?";
OleDbParameter parameter = cmd.Parameters.Add(null, OleDbType.Integer);
parameter.DbType = System.Data.DbType.Int32 ;
parameter.IsNullable = true;
parameter.Value = DBNull.Value; // no row returned
parameter.Value = null; // sql error
var reader = cmd.ExecuteReader();
...

Since NULL does not match anything (even NULL = NULL is false), you have no choice other than using the IS NULL statement.

As ocdecio mention, NULL is not equal to itself. But you do have another option. If you are worried about NULL in this scenario, you can just put an empty string in your parameter value and write the query itself like this:
select * from myTable where COALESCE(myColumn,'') = ?

In SQL, null acts a bit differently to other values - you can't just evaluate things as being = null, as this doesn't really work, you need to use "myColumn is null" instead.
In your case, when you need to match either a value or a null, you might need to use a case statement in your where clause.
A bit of reading: wikipedia

Related

Passing null value from textbox to sql query

I am new with VB.net. I am having problems passing a null value from a VB.net textbox to the sql query string. this is my current code:
Dim sqlstatement as string
If generic_jobTxt.Text == '' Then
generic_jobTxt = DBNull.Value
End If
sqlstatement = "Insert into Job_db (generic_job) values('"+generic_jobTxt+"')"
how can i pass a null value to the sql string so that when i run the sql i get a null value in the generic_job column. Thank you!
First, never concatenate strings to build your sql query, instead use parameterized queries. Otherwise you're open for sql injection and other issues.
On that way you also don't need to fiddle around with apostrophes. But you should use the correct types.
Presuming you're using SQL-Server and the column type is varchar:
Dim sqlstatement = "Insert into Job_db (generic_job) values(#generic_job)"
Using con As New SqlConnection("connection-string")
Using insertCommand = New SqlCommand(sqlstatement, con)
Dim sqlParam = New SqlParameter("#generic_job", SqlDbType.VarChar)
Dim jobTxt As String = generic_jobTxt.Text.Trim()
sqlParam.Value = If(String.IsNullOrEmpty(jobTxt), Nothing, jobTxt)
insertCommand.Parameters.Add(sqlParam)
con.Open()
Dim inserted As Int32 = insertCommand.ExecuteNonQuery()
End Using
End Using

Add the same parameter twice and execute query

Dim b as integer = 1
cmd = New SqlCommand
With cmd
.Connection = connecti
.CommandTimeout = 0
.CommandText = "INSERT INTO HEZDDD(ID,Number,Dates) VALUES (#Id,#Number,#Dates)"
With .Parameters
.AddWithValue("#ID", NextId())
.AddWithValue("#Dates", date.now)
If b = 1 Then
.AddWithValue("#Number", 1)
cmd.ExecuteNonQuery()
End if
If b>10 Then
.AddWithValue("#Number", 2)
cmd.ExecuteNonQuery()
End if
End With
End With
Looking forward to execute the same query twice using different parameters. The output of this simple query should be two rows.
This is simple example i didnt want to put entire code with around 25 parameters.
First use Parameters.Add(string parameterName, SqlDbType sqlDbType) to add parameters without values.
cmd.Parameters.Add("#ID", SqlDbType.Int);
Before you execute the command, provide the values for the parameters:
cmd.Parameters["#ID"].Value = NextId();
Actually, it's always better to use Parameters.Add(string parameterName, SqlDbType sqlDbType), even if you want to set the value immediately. If you use AddWithValue, the db type of the parameter has to be inferred from the value. It usually works well, but you might have some surprises. And because Add returns the added parameter, you can assign the value in the same line:
cmd.Parameters.Add("#ID", SqlDbType.Int).Value = NextId();
It's already in the parameter collection, you just need to change the value on it on the second one.
.Parameters("#Number").Value = 2
Or out of the with..
cmd.Parameters("#Number").Value = 2

Parameterized SQL in FROM clause

Using OleDbCommand. I can add SQL parameters and thus keep the query safe from SQL-injection, but is there a way to do this within the FROM cluase.See below
THIS WORKS
query = "Select * From Company Where #param = 1";
OleDbCommand Command = new OleDbCommand(query, sqlConnStr);
DataTable Table = new DataTable();
DataSet dataSet = new DataSet();
Table = null;
//Add Parameters
Command.Parameters.AddWithValue("param", "ID");
Command.ExecuteNonQuery();
adapter.SelectCommand = Command;
adapter.Fill(dataSet);
Table = dataSet.Tables[0];
it returns a nice table with the wonderful row where id = 1
BUT
I am looking for something like this, note the FROM CLAUSE
query = "Select * From #tableName Where #param = 1";
OleDbCommand Command = new OleDbCommand(query, sqlConnStr);
DataTable Table = new DataTable();
DataSet dataSet = new DataSet();
Table = null;
//Add Parameters
Command.Parameters.AddWithValue("param", "ID");
Command.Parameters.AddWithValue("tableName", "Company");
Command.ExecuteNonQuery();
adapter.SelectCommand = Command;
adapter.Fill(dataSet);
Table = dataSet.Tables[0];
The DBMS keeps returning with "Error in From clause"
PS everything is spelled correctly - I triple checked
To All - Thanks but Alas i shall stick to just Parameterized SQL. I don't like Dynamic SQL One BIT
You'd have to execute a dynamically concatenated SQL string, which unfortunately would compromise whatever benefits parametrized SQL had afforded you to begin with. See this post.
DECLARE #SQL varchar(250)
SELECT #SQL = 'Select * From ' + #TableName + ' Where ' + #param + ' = 1'
Exec(#SQL)
Not advisable, if you can predetermine the table name through some other means instead.
SQL doesn't support the FROM clause to be parameterized. You can't do it the way you are trying. Probably you can do like this:
query = "Select * From" + tableName + "Where #param = 1";
You cannot use paramaterised object names. You would have to do somthing like
string.format("SELECT * FROM [{0}] WHERE [{1}] = 1", tableName, columnName);
DO SO AT YOUR OWN PERIL
It could be worth checking for square brackets in the input, this is the only way I can currently think off to "Inject" the above example. I am no hacker though and not versed in sql injection. Something like this might work:
if (tableName.Contains("]"))
{
throw new ArgumentException();
}

How to put double quotes in ADO.NET query?

I am trying to prevent any SQL injection in all my queries and would like to know how to put double quotes in this query. Thanks
string.Format("SELECT TOP 10 article_guid, article_title
FROM article
WHERE article.article_isdeleted = 0 AND
FREETEXT(article_title, #val)");
Step 1: Don't do this. Use a parameterized query instead.
Parameterized queries remove most of the risk associated with SQL injection attacks.
From the link:
private void CallPreparedCmd() {
string sConnString =
"Server=(local);Database=Northwind;Integrated Security=True;";
string sSQL =
"UPDATE Customers SET City=#sCity WHERE CustomerID=#sCustomerID";
using (SqlConnection oCn = new SqlConnection(sConnString)) {
using (SqlCommand oCmd = new SqlCommand(sSQL, oCn)) {
oCmd.CommandType = CommandType.Text;
oCmd.Parameters.Add("#sCustomerID", SqlDbType.NChar, 5);
oCmd.Parameters.Add("#sCity", SqlDbType.NVarChar, 15);
oCn.Open();
oCmd.Prepare();
oCmd.Parameters["#sCustomerID"].Value = "ALFKI";
oCmd.Parameters["#sCity"].Value = "Berlin2";
oCmd.ExecuteNonQuery();
oCmd.Parameters["#sCustomerID"].Value = "CHOPS";
oCmd.Parameters["#sCity"].Value = "Bern2";
oCmd.ExecuteNonQuery();
oCn.Close();
}
}
}
That being said, you can insert quotes into a string by escaping the double quotes like this:
string newstring = " \"I'm Quoted\" ";
To prevent SQL Injection you must only use SqlParameter objects for all your queries, like so:
SqlCommand command = new SqlCommand("update tblFoo set x = #x");
SqlParamter param = new SqlParameter("#x", SqlDbType.NVarChar);
param.Value = "hello\"";
command.Parameters.Add(param);
Why did you use string.Format? You are using #parameterized query and it is Type-Safe.
Use Type-Safe SQL Parameters for Data Access
I'm not sure if double quotes will help you (which you can add if you like by escaping the quote, as in \"). What I've done in the past is to be mindful of single quotes, so I performed a replace on the content of #val prior to including it in the query, as in val.Replace("'", "''").

Using an 'IN' operator with a SQL Command Object and C# 2.0

I would like to call a sql statement such as:
Select * From Table Where Column in ('value1', 'value2', 'value3')
Is it as simple as setting a command parameter's value equal to "('value1', 'value2', 'value3')"?
#Charles: You're going into the right direction, but we're using parametrized queries to mainly prevent SQL injections. Putting 'external' values (params string[] args) hardcoded in queries is asking for trouble. You can iterate the arguments, but you still have to use parameters like this:
string[] values = new [] {"value1", "value2", "value3", "value4"};
StringBuilder query = new StringBuilder("Select * From Table Where Column in (");
SqlCommand cmd = new SqlCommand();
cmd.Connection = new SqlConnection("Your connection string");
for(int i = 0; i < columns.Length; i++)
{
string arg = string.Format("#arg{0}", i);
cmd.Parameters.AddwithValue(arg, SanatizeSqlString(columns[i]));
sb.AppendFormat("{0}, ", arg);
}
sb = sb.Remove(sb.Length -2, 2);
sb.Append(")");
cmd.CommandText = sb.ToString();
This way you'll end up with a query like:
select * from table where column in (#arg0, #arg1, #arg2, #arg3)
Another option is to set the SqlCommand's commandtype to "text" and construct the entire Sql string in code... Assuming Column is a varchar, and you have the Values in a string arrray, named "paramValues"
StringBuilder sbSql = new StringBuilder
("Select * From Table Where Column in (");
string[] paramValues = new string[] {"value1", "value2", "value3"};
foreach (string val in paramValues)
sbSql.Append("'" + val + "', ");
sbSql = sbSql.Remove(sbSql.Length - 2, 2);
sbSql.Append(")");
SqlCommand cmd = new SqlCommand(sbSql.ToString());
cmd.CommandType = CommandType.Text;
if you only have three parameters for the in clause then yes you can use the parameters. Otherwise you can build dynamic SQL (Be careful of SQL injection attacks).
Another approach is to create a UDF which takes a delimited string and returns a table. then you could modify your query to be:
select * from
table inner join
dbo.fn_stringToTable(#params)