Usage of Oracle binding variables with LIKE in C# - c#

As part of an effort to stop using dynamic SQL generation and encourage use of bind variables, I am running into some problems.
I am querying an Oracle 9i database from an ASP.NET page using Oracle Data Providers for .NET
The query is
sql = "SELECT somedata FROM sometable WHERE machine = :machineName ";
I define the Oracle Parameter as follows
OracleParameter parameter = new OracleParameter();
parameter.ParameterName = "machineName";
parameter.OracleDbType = OracleDbType.Varchar2;
parameter.Value = machine; //machine is a variable of type string
parameterList.Add(parameter);
This works fine for "=" operator. But I just can't seem to get it to work with "LIKE". I don't know how to format the query so that it accepts usage of the "%" wildcard.
I have tried:
sql = "SELECT somedata FROM sometable WHERE machine LIKE :machineName% ";
sql = "SELECT somedata FROM sometable WHERE machine LIKE ':machineName%' ";
sql = "SELECT somedata FROM sometable WHERE machine LIKE :machineName||% ";
and also:
parameter.Value = machine+'%';
but all I get are ORA-00911 (illegal character) and ORA-01036 (illegal name/value) exceptions.
What am I doing wrong?

Try:
sql = "SELECT somedata FROM sometable WHERE machine LIKE :machineName || '%' ";
Because of the BIND variable, there wouldn't need to be single quotes around it. But the % is not, so I would expect it needing to be encapsulated.

Here is a full query example:
string commandText = "SELECT LastName, FirstName FROM PEOPLE WHERE UPPER(LastName) LIKE '%' || :lastName || '%' AND UPPER(FirstName) LIKE '%' || :firstName || '%'";
string oradb = "yourDatabaseConnectionStringHere"; // Might want to add Using statement for this code and try catch
OracleConnection conn = new OracleConnection(oradb); // C#
conn.Open();
OracleCommand cmd = new OracleCommand
{
Connection = conn,
CommandText = commandText,
CommandType = CommandType.Text
};
/*IMPORTANT: adding parameters must be in order how they are in order in the SQL statement*/
cmd.Parameters.Add(new OracleParameter("lastName", model.LastName.Trim().ToUpper()));
cmd.Parameters.Add(new OracleParameter("firstName", model.FirstName.Trim().ToUpper()));
OracleDataReader dr = cmd.ExecuteReader();

Related

OleDbException Thrown - no value given for Button Click method [duplicate]

I am trying to create an SQL statement using user-supplied data. I use code similar to this in C#:
var sql = "INSERT INTO myTable (myField1, myField2) " +
"VALUES ('" + someVariable + "', '" + someTextBox.Text + "');";
var cmd = new SqlCommand(sql, myDbConnection);
cmd.ExecuteNonQuery();
and this in VB.NET:
Dim sql = "INSERT INTO myTable (myField1, myField2) " &
"VALUES ('" & someVariable & "', '" & someTextBox.Text & "');"
Dim cmd As New SqlCommand(sql, myDbConnection)
cmd.ExecuteNonQuery()
However,
this fails when the user input contains single quotes (e.g. O'Brien),
I cannot seem to get the format right when inserting DateTime values and
people keep telling me that I should not do this because of "SQL injection".
How do I do it "the right way"?
Use parameterized SQL.
Examples
(These examples are in C#, see below for the VB.NET version.)
Replace your string concatenations with #... placeholders and, afterwards, add the values to your SqlCommand. You can choose the name of the placeholders freely, just make sure that they start with the # sign. Your example would look like this:
var sql = "INSERT INTO myTable (myField1, myField2) " +
"VALUES (#someValue, #someOtherValue);";
using (var cmd = new SqlCommand(sql, myDbConnection))
{
cmd.Parameters.AddWithValue("#someValue", someVariable);
cmd.Parameters.AddWithValue("#someOtherValue", someTextBox.Text);
cmd.ExecuteNonQuery();
}
The same pattern is used for other kinds of SQL statements:
var sql = "UPDATE myTable SET myField1 = #newValue WHERE myField2 = #someValue;";
// see above, same as INSERT
or
var sql = "SELECT myField1, myField2 FROM myTable WHERE myField3 = #someValue;";
using (var cmd = new SqlCommand(sql, myDbConnection))
{
cmd.Parameters.AddWithValue("#someValue", someVariable);
using (var reader = cmd.ExecuteReader())
{
...
}
// Alternatively: object result = cmd.ExecuteScalar();
// if you are only interested in one value of one row.
}
A word of caution: AddWithValue is a good starting point and works fine in most cases. However, the value you pass in needs to exactly match the data type of the corresponding database field. Otherwise, you might end up in a situation where the conversion prevents your query from using an index. Note that some SQL Server data types, such as char/varchar (without preceding "n") or date do not have a corresponding .NET data type. In those cases, Add with the correct data type should be used instead.
Why should I do that?
It's more secure: It stops SQL injection. (Bobby Tables won't delete your student records.)
It's easier: No need to fiddle around with single and double quotes or to look up the correct string representation of date literals.
It's more stable: O'Brien won't crash your application just because he insists on keeping his strange name.
Other database access libraries
If you use an OleDbCommand instead of an SqlCommand (e.g., if you are using an MS Access database), use ? instead of #... as the placeholder in the SQL. In that case, the first parameter of AddWithValue is irrelevant; instead, you need to add the parameters in the correct order. The same is true for OdbcCommand.
Entity Framework also supports parameterized queries.
VB.NET Example Code
This is the example code for the wiki answer in vb.net, assuming Option Strict On and Option Infer On.
INSERT
Dim sql = "INSERT INTO myTable (myField1, myField2) " &
"VALUES (#someValue, #someOtherValue);"
Using cmd As New SqlCommand(sql, myDbConnection)
cmd.Parameters.AddWithValue("#someValue", someVariable)
cmd.Parameters.AddWithValue("#someOtherValue", someTextBox.Text)
cmd.ExecuteNonQuery()
End Using
UPDATE
Dim sql = "UPDATE myTable SET myField1 = #newValue WHERE myField2 = #someValue;"
' see above, same as INSERT
SELECT
Dim sql = "SELECT myField1, myField2 FROM myTable WHERE myField3 = #someValue;"
Using cmd As New SqlCommand(sql, myDbConnection)
cmd.Parameters.AddWithValue("#someValue", someVariable)
Using reader = cmd.ExecuteReader()
' ...
End Using
' Alternatively: Dim result = cmd.ExecuteScalar()
' if you are only interested in one value of one row.
End Using

Query returns empty set when parameters are passed from GET variables

I have a simple query with a where clause that has no results when it is run from code.
This query works fine if it is ran from the SQL Server Management studio, but when i pass some variables that are taken from GET parameters this query will show no results.Request.QueryString["q"] is not NULL.Command.ExecuteReader(); executes fine.
Connection = new SqlConnection(ConnectionString);
Connection.Open();
Command = new SqlCommand("", Connection);
if (Request.QueryString["q"] != null)
{
Query = Request.QueryString["q"].ToString();
Command.CommandText = "SELECT * FROM [device] WHERE [display_name] LIKE N'%#query%' OR [address] LIKE N'%#query%' ";
Command.Parameters.AddWithValue("#query", Query);
Reader = Command.ExecuteReader();
while (Reader.Read())//Here Reader.HasRows=False
{
//Do Stuff
}
There is a single row in the table that has its [display_name] is equal to KHR and its [address] is equal to تست.
passing ?q=kh to the page, i get no result form this query where it actually should return a single row.
[display_name] LIKE N'%#query%' will search for a row where display_name contains the text '#query' not the value of the variable #query. C# doesn't inject the value of a parameter.
You need to do something like this:
Command.CommandText = "SELECT * FROM [device] WHERE [display_name] LIKE N'%' + #query + N'%' OR [address] LIKE N'%' + #query + N'%';";
Command.Parameters.Add("#query", SqlDbType.NVarChar, 50);
Command.Parameters["#query"].Value = Query;
Note I have also removed AddWithValue (Can we stop using AddWithValue Already?)

How to save data of DateTimePicker into database [duplicate]

I am trying to create an SQL statement using user-supplied data. I use code similar to this in C#:
var sql = "INSERT INTO myTable (myField1, myField2) " +
"VALUES ('" + someVariable + "', '" + someTextBox.Text + "');";
var cmd = new SqlCommand(sql, myDbConnection);
cmd.ExecuteNonQuery();
and this in VB.NET:
Dim sql = "INSERT INTO myTable (myField1, myField2) " &
"VALUES ('" & someVariable & "', '" & someTextBox.Text & "');"
Dim cmd As New SqlCommand(sql, myDbConnection)
cmd.ExecuteNonQuery()
However,
this fails when the user input contains single quotes (e.g. O'Brien),
I cannot seem to get the format right when inserting DateTime values and
people keep telling me that I should not do this because of "SQL injection".
How do I do it "the right way"?
Use parameterized SQL.
Examples
(These examples are in C#, see below for the VB.NET version.)
Replace your string concatenations with #... placeholders and, afterwards, add the values to your SqlCommand. You can choose the name of the placeholders freely, just make sure that they start with the # sign. Your example would look like this:
var sql = "INSERT INTO myTable (myField1, myField2) " +
"VALUES (#someValue, #someOtherValue);";
using (var cmd = new SqlCommand(sql, myDbConnection))
{
cmd.Parameters.AddWithValue("#someValue", someVariable);
cmd.Parameters.AddWithValue("#someOtherValue", someTextBox.Text);
cmd.ExecuteNonQuery();
}
The same pattern is used for other kinds of SQL statements:
var sql = "UPDATE myTable SET myField1 = #newValue WHERE myField2 = #someValue;";
// see above, same as INSERT
or
var sql = "SELECT myField1, myField2 FROM myTable WHERE myField3 = #someValue;";
using (var cmd = new SqlCommand(sql, myDbConnection))
{
cmd.Parameters.AddWithValue("#someValue", someVariable);
using (var reader = cmd.ExecuteReader())
{
...
}
// Alternatively: object result = cmd.ExecuteScalar();
// if you are only interested in one value of one row.
}
A word of caution: AddWithValue is a good starting point and works fine in most cases. However, the value you pass in needs to exactly match the data type of the corresponding database field. Otherwise, you might end up in a situation where the conversion prevents your query from using an index. Note that some SQL Server data types, such as char/varchar (without preceding "n") or date do not have a corresponding .NET data type. In those cases, Add with the correct data type should be used instead.
Why should I do that?
It's more secure: It stops SQL injection. (Bobby Tables won't delete your student records.)
It's easier: No need to fiddle around with single and double quotes or to look up the correct string representation of date literals.
It's more stable: O'Brien won't crash your application just because he insists on keeping his strange name.
Other database access libraries
If you use an OleDbCommand instead of an SqlCommand (e.g., if you are using an MS Access database), use ? instead of #... as the placeholder in the SQL. In that case, the first parameter of AddWithValue is irrelevant; instead, you need to add the parameters in the correct order. The same is true for OdbcCommand.
Entity Framework also supports parameterized queries.
VB.NET Example Code
This is the example code for the wiki answer in vb.net, assuming Option Strict On and Option Infer On.
INSERT
Dim sql = "INSERT INTO myTable (myField1, myField2) " &
"VALUES (#someValue, #someOtherValue);"
Using cmd As New SqlCommand(sql, myDbConnection)
cmd.Parameters.AddWithValue("#someValue", someVariable)
cmd.Parameters.AddWithValue("#someOtherValue", someTextBox.Text)
cmd.ExecuteNonQuery()
End Using
UPDATE
Dim sql = "UPDATE myTable SET myField1 = #newValue WHERE myField2 = #someValue;"
' see above, same as INSERT
SELECT
Dim sql = "SELECT myField1, myField2 FROM myTable WHERE myField3 = #someValue;"
Using cmd As New SqlCommand(sql, myDbConnection)
cmd.Parameters.AddWithValue("#someValue", someVariable)
Using reader = cmd.ExecuteReader()
' ...
End Using
' Alternatively: Dim result = cmd.ExecuteScalar()
' if you are only interested in one value of one row.
End Using

ASP.NET SqlParameter [duplicate]

I am trying to create an SQL statement using user-supplied data. I use code similar to this in C#:
var sql = "INSERT INTO myTable (myField1, myField2) " +
"VALUES ('" + someVariable + "', '" + someTextBox.Text + "');";
var cmd = new SqlCommand(sql, myDbConnection);
cmd.ExecuteNonQuery();
and this in VB.NET:
Dim sql = "INSERT INTO myTable (myField1, myField2) " &
"VALUES ('" & someVariable & "', '" & someTextBox.Text & "');"
Dim cmd As New SqlCommand(sql, myDbConnection)
cmd.ExecuteNonQuery()
However,
this fails when the user input contains single quotes (e.g. O'Brien),
I cannot seem to get the format right when inserting DateTime values and
people keep telling me that I should not do this because of "SQL injection".
How do I do it "the right way"?
Use parameterized SQL.
Examples
(These examples are in C#, see below for the VB.NET version.)
Replace your string concatenations with #... placeholders and, afterwards, add the values to your SqlCommand. You can choose the name of the placeholders freely, just make sure that they start with the # sign. Your example would look like this:
var sql = "INSERT INTO myTable (myField1, myField2) " +
"VALUES (#someValue, #someOtherValue);";
using (var cmd = new SqlCommand(sql, myDbConnection))
{
cmd.Parameters.AddWithValue("#someValue", someVariable);
cmd.Parameters.AddWithValue("#someOtherValue", someTextBox.Text);
cmd.ExecuteNonQuery();
}
The same pattern is used for other kinds of SQL statements:
var sql = "UPDATE myTable SET myField1 = #newValue WHERE myField2 = #someValue;";
// see above, same as INSERT
or
var sql = "SELECT myField1, myField2 FROM myTable WHERE myField3 = #someValue;";
using (var cmd = new SqlCommand(sql, myDbConnection))
{
cmd.Parameters.AddWithValue("#someValue", someVariable);
using (var reader = cmd.ExecuteReader())
{
...
}
// Alternatively: object result = cmd.ExecuteScalar();
// if you are only interested in one value of one row.
}
A word of caution: AddWithValue is a good starting point and works fine in most cases. However, the value you pass in needs to exactly match the data type of the corresponding database field. Otherwise, you might end up in a situation where the conversion prevents your query from using an index. Note that some SQL Server data types, such as char/varchar (without preceding "n") or date do not have a corresponding .NET data type. In those cases, Add with the correct data type should be used instead.
Why should I do that?
It's more secure: It stops SQL injection. (Bobby Tables won't delete your student records.)
It's easier: No need to fiddle around with single and double quotes or to look up the correct string representation of date literals.
It's more stable: O'Brien won't crash your application just because he insists on keeping his strange name.
Other database access libraries
If you use an OleDbCommand instead of an SqlCommand (e.g., if you are using an MS Access database), use ? instead of #... as the placeholder in the SQL. In that case, the first parameter of AddWithValue is irrelevant; instead, you need to add the parameters in the correct order. The same is true for OdbcCommand.
Entity Framework also supports parameterized queries.
VB.NET Example Code
This is the example code for the wiki answer in vb.net, assuming Option Strict On and Option Infer On.
INSERT
Dim sql = "INSERT INTO myTable (myField1, myField2) " &
"VALUES (#someValue, #someOtherValue);"
Using cmd As New SqlCommand(sql, myDbConnection)
cmd.Parameters.AddWithValue("#someValue", someVariable)
cmd.Parameters.AddWithValue("#someOtherValue", someTextBox.Text)
cmd.ExecuteNonQuery()
End Using
UPDATE
Dim sql = "UPDATE myTable SET myField1 = #newValue WHERE myField2 = #someValue;"
' see above, same as INSERT
SELECT
Dim sql = "SELECT myField1, myField2 FROM myTable WHERE myField3 = #someValue;"
Using cmd As New SqlCommand(sql, myDbConnection)
cmd.Parameters.AddWithValue("#someValue", someVariable)
Using reader = cmd.ExecuteReader()
' ...
End Using
' Alternatively: Dim result = cmd.ExecuteScalar()
' if you are only interested in one value of one row.
End Using

How can I add user-supplied input to an SQL statement?

I am trying to create an SQL statement using user-supplied data. I use code similar to this in C#:
var sql = "INSERT INTO myTable (myField1, myField2) " +
"VALUES ('" + someVariable + "', '" + someTextBox.Text + "');";
var cmd = new SqlCommand(sql, myDbConnection);
cmd.ExecuteNonQuery();
and this in VB.NET:
Dim sql = "INSERT INTO myTable (myField1, myField2) " &
"VALUES ('" & someVariable & "', '" & someTextBox.Text & "');"
Dim cmd As New SqlCommand(sql, myDbConnection)
cmd.ExecuteNonQuery()
However,
this fails when the user input contains single quotes (e.g. O'Brien),
I cannot seem to get the format right when inserting DateTime values and
people keep telling me that I should not do this because of "SQL injection".
How do I do it "the right way"?
Use parameterized SQL.
Examples
(These examples are in C#, see below for the VB.NET version.)
Replace your string concatenations with #... placeholders and, afterwards, add the values to your SqlCommand. You can choose the name of the placeholders freely, just make sure that they start with the # sign. Your example would look like this:
var sql = "INSERT INTO myTable (myField1, myField2) " +
"VALUES (#someValue, #someOtherValue);";
using (var cmd = new SqlCommand(sql, myDbConnection))
{
cmd.Parameters.AddWithValue("#someValue", someVariable);
cmd.Parameters.AddWithValue("#someOtherValue", someTextBox.Text);
cmd.ExecuteNonQuery();
}
The same pattern is used for other kinds of SQL statements:
var sql = "UPDATE myTable SET myField1 = #newValue WHERE myField2 = #someValue;";
// see above, same as INSERT
or
var sql = "SELECT myField1, myField2 FROM myTable WHERE myField3 = #someValue;";
using (var cmd = new SqlCommand(sql, myDbConnection))
{
cmd.Parameters.AddWithValue("#someValue", someVariable);
using (var reader = cmd.ExecuteReader())
{
...
}
// Alternatively: object result = cmd.ExecuteScalar();
// if you are only interested in one value of one row.
}
A word of caution: AddWithValue is a good starting point and works fine in most cases. However, the value you pass in needs to exactly match the data type of the corresponding database field. Otherwise, you might end up in a situation where the conversion prevents your query from using an index. Note that some SQL Server data types, such as char/varchar (without preceding "n") or date do not have a corresponding .NET data type. In those cases, Add with the correct data type should be used instead.
Why should I do that?
It's more secure: It stops SQL injection. (Bobby Tables won't delete your student records.)
It's easier: No need to fiddle around with single and double quotes or to look up the correct string representation of date literals.
It's more stable: O'Brien won't crash your application just because he insists on keeping his strange name.
Other database access libraries
If you use an OleDbCommand instead of an SqlCommand (e.g., if you are using an MS Access database), use ? instead of #... as the placeholder in the SQL. In that case, the first parameter of AddWithValue is irrelevant; instead, you need to add the parameters in the correct order. The same is true for OdbcCommand.
Entity Framework also supports parameterized queries.
VB.NET Example Code
This is the example code for the wiki answer in vb.net, assuming Option Strict On and Option Infer On.
INSERT
Dim sql = "INSERT INTO myTable (myField1, myField2) " &
"VALUES (#someValue, #someOtherValue);"
Using cmd As New SqlCommand(sql, myDbConnection)
cmd.Parameters.AddWithValue("#someValue", someVariable)
cmd.Parameters.AddWithValue("#someOtherValue", someTextBox.Text)
cmd.ExecuteNonQuery()
End Using
UPDATE
Dim sql = "UPDATE myTable SET myField1 = #newValue WHERE myField2 = #someValue;"
' see above, same as INSERT
SELECT
Dim sql = "SELECT myField1, myField2 FROM myTable WHERE myField3 = #someValue;"
Using cmd As New SqlCommand(sql, myDbConnection)
cmd.Parameters.AddWithValue("#someValue", someVariable)
Using reader = cmd.ExecuteReader()
' ...
End Using
' Alternatively: Dim result = cmd.ExecuteScalar()
' if you are only interested in one value of one row.
End Using

Categories