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();
}
Related
I have the following code that runs on a button click:
protected void Button2_Click(object sender, EventArgs e)
{
String str = "SELECT * " +
"FROM ConcernTicket INNER JOIN Employee " +
"ON ConcernTicket.EmployeeReportedToID = Employee.EmployeeId " +
"WHERE (Employee.FirstName LIKE '%' + #search2 + '%')";
SqlCommand xp = new SqlCommand(str, vid);
xp.Parameters.Add("#search2", SqlDbType.NVarChar).Value =
TextBox1.Text;
vid.Open();
xp.ExecuteNonQuery();
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = xp;
DataSet ds = new DataSet();
da.Fill(ds, "Employee.FirstName");
GridView2.DataSource = ds;
GridView2.DataBind();
vid.Close();
}
The problem I am facing is that the search runs with no errors but instead of just returning the results where the FirstName variable matches, it displays all current Concern Tickets. I am assuming it is a fairly simple fix with the SELECT statement, but for some reason I have not been able to figure out what is going wrong. I just started working with sql so I apologize that I am having such a silly issue, any help would be appreciated, thanks!
Check that TextBox1.Text is not empty. If it is empty, the query will be:
WHERE (Employee.FirstName LIKE '%%')";
Also check that #search2 is being replaced properly. The + operator is not what you would expect in MySQL. Perhaps this is what you're looking for:
"WHERE (Employee.FirstName LIKE '%#search2%')";
Hope that helps
your problem is not the SQL query. In fact you use ExecuteNonQuery() to extract select result. ExecuteNonQuery() just returns a single integer.Please use a code like this and let me know if the problem persists.
string connetionString = null;
SqlConnection connection ;
SqlDataAdapter adapter = new SqlDataAdapter();
DataSet ds = new DataSet();
int i = 0;
connetionString = "Data Source=ServerName;Initial Catalog=DatabaseName;User ID=UserName;Password=Password";
connection = new SqlConnection(connetionString);
try
{
connection.Open();
adapter.SelectCommand = new SqlCommand("Your SQL Statement Here", connection);
adapter.Fill(ds);
connection.Close();
for (i = 0; i <= ds.Tables[0].Rows.Count - 1; i++)
{
MessageBox.Show(ds.Tables[0].Rows[1].ItemArray[1].ToString());
}
}
I have an UPDATE stored procedure that works good from SQL Server query:
GO
ALTER PROCEDURE [dbo].[UpdateMedicalCard]
#RecordingCode int,
#BeginTreatmentDate date,
#EndTreatmentDate date,
#MainDiagnosis nchar(100),
#AttendantDiagnosis nchar(100),
#TreatmentResult nchar(50)
AS
BEGIN
UPDATE MedicalCard
SET BeginTreatmentDate = #BeginTreatmentDate,
EndTreatmentDate = #EndTreatmentDate,
MainDiagnosis = #MainDiagnosis,
AttendantDiagnosis = #AttendantDiagnosis,
TreatmentResult = #TreatmentResult
WHERE RecordingCode = #RecordingCode
END
But when i call this procedure from Visual studio it does not update.
SqlConnection connection = new SqlConnection();
connection.ConnectionString = #"Data Source=.;Initial Catalog=Policlinic;Integrated Security=SSPI";
connection.Open();
SqlCommand myCommand = connection.CreateCommand();
myCommand.CommandType = CommandType.StoredProcedure;
myCommand.CommandText = "UpdateMedicalCard";
myCommand.Parameters.Add("#RecordingCode", System.Data.SqlDbType.Int);
myCommand.Parameters["#RecordingCode"].Value = dataGridView1.CurrentRow.Cells[0].Value;
myCommand.Parameters.Add("#BeginTreatmentDate", System.Data.SqlDbType.Date);
myCommand.Parameters["#BeginTreatmentDate"].Value = dataGridView1.CurrentRow.Cells[3].Value;
myCommand.Parameters.Add("#EndTreatmentDate", System.Data.SqlDbType.Date);
myCommand.Parameters["#EndTreatmentDate"].Value = dataGridView1.CurrentRow.Cells[4].Value;
myCommand.Parameters.Add("#MainDiagnosis", System.Data.SqlDbType.NChar);
myCommand.Parameters["#MainDiagnosis"].Value = "qwe";
myCommand.Parameters.Add("#AttendantDiagnosis", System.Data.SqlDbType.NChar);
myCommand.Parameters["#AttendantDiagnosis"].Value = dataGridView1.CurrentRow.Cells[6].Value;
myCommand.Parameters.Add("#TreatmentResult", System.Data.SqlDbType.NChar);
myCommand.Parameters["#TreatmentResult"].Value = dataGridView1.CurrentRow.Cells[7].Value;
var dataAdapter = new SqlDataAdapter(myCommand);
var dataTable = new DataTable();
dataAdapter.Update(dataTable);
connection.Close();
I think i do smth wrong at the last 4 rows. Help please.
Your command isn't going to return any result rows, so you don't need to use a DataTable or DataAdapter. You just need to call connection.ExecuteNonQuery() instead.
You may also want to double check that the data (specifically the dates, as they can be tricky since the field may or may not also store a time component depending on how the table is defined, match an existing row.
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("'", "''").
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
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)