Using items from List<string> in SQL query - c#

Ok, I have a list that consists of a bunch of values from a sql query, that part works fine. What I want to do is use the items in that list to tell another query what to look for. So, what it is saying is that, it should return all columns from CMMReports where PartNumber is like %listItem1..2...3%, Any advice?
List<string> ImportedParts = GetImportedPartNumbers();
string query = "SELECT * FROM CMMReports WHERE (RacfId IS NULL OR RacfId = '') AND (FilePath NOT LIKE '%js91162%') AND PartNumber LIKE %" + ImportedParts + "% ORDER BY CreatedOn DESC;";

Not that I condone this as you should be using parameterized queries. However, this should work:
StringBuilder partNumbers = new StringBuilder();
foreach (string queryValue in ImportedParts)
{
string q = "PartNumber LIKE '%" + queryValue + "%'";
if (string.IsNullOrEmpty(partNumbers.ToString())
{
partNumbers.Append(q);
}
else
{
partNumbers.Append(" OR " + q);
}
}
string query = string.Format("SELECT * FROM CMMReports WHERE (RacfId IS NULL OR RacfId = '') " +
"AND (FilePath NOT LIKE '%js91162%') AND ({0}) " +
"ORDER BY CreatedOn DESC;", partNumbers.ToString());

You might look up the IN clouse for SQL that way you get the answer for the parts that SQL Server can find in the database. Using WHERE x = y for all the items means that if one item can't be found the whole query returns nothing.

I would consider doing this in a stored procedure and passing in your list as an Xml parameter.
See the following article for more info on using Xml parameters in a stored proc:
Passing lists to SQL Server 2005 with XML Parameters - By Jon Galloway
Form there you can easily use your list data inside your stored proc using the Xml syntax and treat it almost as another table of data.

Untested, but you should get the idea:
List<string> ImportedParts = GetImportedPartNumbers();
SqlCommand cmd = myConnection.CreateCommand();
cmd.CommandText = "SELECT * FROM CMMReports WHERE (RacfId IS NULL OR RacfId = '') AND (FilePath NOT LIKE '%js91162%') AND (";
int i = 0;
foreach (string part in ImportedParts) {
cmd.AddParameterWithValue("#param" + i.ToString(), "%" + part + "%");
if (i != 0) cmd.CommandText += " OR"
cmd.CommandText += " PartNumber LIKE #param" + i.ToString();
i++;
}
cmd.CommandText += ") ORDER BY CreatedOn DESC;";
This solution uses a parameterized query instead of just appending strings in the SQL, which is considered a potential security risk.

Related

C# SQLite multiple keyword with like command

I used SQLite. The user will pull the days from checkbox and I'll show it in data grid view but the date is recorded as day and time so I have to use like instead of in command.
DataSet dataSet122;
listBox1.Items.Clear();
SQLiteConnection connection = new SQLiteConnection("Data Source =log.sqlite;Version=3;");
string search = checkBoxComboBox1.Text;
string[] array = search.Split(',');
for (int i = 0; i < array.Length; i++)
{
array[i] = "'" + array[i] + "'";
}
string names = String.Join(",", array);
listBox2.Items.Add(names);
string query = "SELECT * FROM Gemkay1 WHERE ZAMAN LIKE (" + names + ")";
command = new SQLiteCommand(query, connection);
connection.Open();
adapter = new SQLiteDataAdapter(command);
dataSet122 = new DataSet();
adapter.Fill(dataSet122, "Gemkay1");
dataGridViewSummary1.DataSource = dataSet122.Tables["Gemkay1"];
SQL syntax for all people where name ends with SMITH or WRIGHT:
WHERE name LIKE '%SMITH' OR name LIKE '%WRIGHT'
LIKE is not the same as IN - it accepts a single string argument on the right hand side. If you want multiple LIKEs you must repeat the LIKE clause separated by OR
IN can be used with multiple string but it does not accept wildcards:
WHERE name IN ('playwright', 'cartwright', 'shipwright')
If you try and put a wildcard in it will literally match that character.
-
As an aside, don't make SQL like you're doing there, with string concatenation of the values. Concatenate parameters in instead and give them values, for example:
var names = new []{"%wright", "%smith"};
var sql = new SqliteCommand("SELECT * FROM t WHERE 1=0 ");
for(int p = 0; p<names.Length; p++){
sql.CommandText += " OR name like #p" + p;
sql.Parameters.AddWithValue("#p"+p, names[p]);
}
This I what I mean when I say "concatenate parameters in, then give them a value".
If you ever work with sqlserver read this blog post
Use IN operator to select data where multiple values
"SELECT * FROM Gemkay1 WHERE ZAMAN IN ('2021-02-01','2021-02-02')";
to ignore time from date you can use date function:
"SELECT * FROM Gemkay1 WHERE date(ZAMAN) IN ('2021-02-01','2021-02-02')";
See SQLite date and time functions documentation for more info.

C#: How to pass parmeterize values to System.Data.Entity.SqlSquery

I'm going to execute SQL query directly on database.
I've define connection to my database using:
System.Data.Entity.DbContext rawDbContext = new DbContext(connectionString);
I don't want to insert parameters directly to query string to avoid SQL Injection so I want to set parametrized values for my SQL query this way:
string sqlCommandString =
"IF EXISTS(select* from #MappingTableName where " + Environment.NewLine +
"BranchID= #PrimaryKeyID and " + Environment.NewLine +
"BranchNo = #BranchNo and " + Environment.NewLine +
"TableName = #TableName and " + Environment.NewLine +
"BranchSchema = #SchemaNameInBranch and " + Environment.NewLine +
"TableID = #TableID) " + Environment.NewLine +
" select 1" + Environment.NewLine +
"ELSE " + Environment.NewLine +
"select 0 " + Environment.NewLine;
SqlParameter parameterMappingTableName = new SqlParameter("#MappingTableName", vipMappingTableName);
SqlParameter parameterSchemaNameInBranch = new SqlParameter("#SchemaNameInBranch", schemaName);
SqlParameter parameterPrimaryKeyInBranch = new SqlParameter("#PrimaryKeyID", primaryNodeId);
SqlParameter parameterBranchNo = new SqlParameter("#BranchNo", branchNo);
SqlParameter parameterTableId = new SqlParameter("#TableID", tableId);
SqlParameter parameterTableName = new SqlParameter("#TableName", tableName);
DbRawSqlQuery<int> result = rawDbContext.Database.SqlQuery<int>(sqlCommandString,
new[] {
parameterMappingTableName,
parameterSchemaNameInBranch,
parameterPrimaryKeyInBranch,
parameterBranchNo,
parameterTableId,
parameterTableName
});
int finalResult = result.Single();
Running this query leads to excpetion "Must declare the table variable \"#MappingTableName\"."
How can I fix this?
Check this from Microsoft forums
Database objects (tables, stored procedures or any other objects)
cannot be passed as parameters. Only actual values for columns or
variables can be parameters. You need to build your SQL statement
dynamically in this case
Which basically means that you have to provide and/or build the table name, under the danger that this can be compromised.
How to mitigate the risk. Declare a set of probable table name and do an exact match.
Then build your query with text concatenation. This is something that can't be done with parameters cause you can't expect the possible values, but can be done with tables because they are only so many. Be carefull to use Equals instead of Contains in your list of names.

How to use c# variable with sql server query?

I have to use "messageId" and "parrentId" c# variables in sql query, but when I use error raise: "Incorrect syntax near '.2'.".
How can I use "messageId" and "parrentId" in below query?
internal DataTable getAllMessages(string messageId, string parrentId)
{
Query = "SELECT DISTINCT T1.* FROM mail_Reply T2 JOIN mail_Messages T1 ON (T2."
+ messageId + "=T1." + messageId + " OR T2." + parrentId + "=T1."
+ messageId + ")";
return ExecuteDataTable();
}
Thanks in advance.
Don't try and build a query string like that - it opens you up to a vulnerablity known as SQL Injection - and that is something you need to go away and read about right now...
Once you're done with that, read about Command objects - SqlCommand and friends...
Alternatively, consider embracing Entity Framework...
if you column names are like integer values 1,2,3, then try this,
Query = "SELECT DISTINCT T1.* FROM mail_Reply T2 JOIN mail_Messages T1 ON (T2.["
+ messageId + "]=T1.[" + messageId + "] OR T2.[" + parrentId + "]=T1.["
+ messageId + "])";
return ExecuteDataTable();
use string.format or build the query seperatly in a string variable and assign it to Query

Parameterized dynamic sql query

I have a list of keywords that i store in a list.
To fetch records from a table, am using the following query:
sqlBuilder.Append("SELECT name, memberid FROM members WHERE");
StringBuilder sqlBuilder = new StringBuilder();
foreach (string item in keywords)
{
sqlBuilder.AppendFormat(" LOWER(Name) LIKE '%{0}%' AND", item);
}
string sql = sqlBuilder.ToString();
As you might have noticed, my query is vulnerable to sql injection, thus i want to use parameters using SqlCommand(). I have tried the following but still doesn't work:
foreach (string item in keywords)
{
sqlBuilder.AppendFormat(" LOWER(Name) LIKE '%' + #searchitem + '%' AND", item);
SqlCommand cmd = new SqlCommand(sqlBuilder.ToString());
cmd.Parameters.AddWithValue("#searchitem",item);
}
Where could i be making the mistake, or rather, how should i got about it?
You are doing a few things wrong here:
You give all your parameters the same name #searchitem. That won't work. The parameters need unique names.
You create a new SqlCommand for each item. That won't work. Create the SqlCommand once at the beginning of the loop and then set CommandText once you are done creating the SQL.
Your SQL ends with AND, which is not valid syntax.
Improvement suggestions (not wrong per se, but not best practice either):
As Frederik suggested, the usual way is to put the % tokens in the parameter, rather than doing string concatenation inside the SQL.
Unless you explicitly use a case-sensitive collation for your database, comparisons should be case-insensitive. Thus, you might not need the LOWER.
Code example:
SqlCommand cmd = new SqlCommand();
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.Append("SELECT name, memberid FROM members ");
var i = 1;
foreach (string item in keywords)
{
sqlBuilder.Append(i == 1 ? " WHERE " : " AND ");
var paramName = "#searchitem" + i.ToString();
sqlBuilder.AppendFormat(" Name LIKE {0} ", paramName);
cmd.Parameters.AddWithValue(paramName, "%" + item + "%");
i++;
}
cmd.CommandText = sqlBuilder.ToString();
Do not put the wildcard characters in your querystring, but add them to your parameter-value:
sql = "SELECT name FROM members WHERE Name LIKE #p_name";
...
cmd.Parameters.AddWithValue("#p_name", "%" + item + "%");
When you add the wildcard characters inside your query-string, the parameter will be escaped, but the wildcard chars will not; that will result in a query that is sent to the DB that looks like this:
SELECT name FROM members WHERE Name LIKE %'somename'%
which is obviously not correct.
Next to that, you're creating a SqlCommand in a loop which is not necessary. Also, you're creating parameters with a non-unique name, since you're adding them in a loop, and the parameter always has the same name.
You also need to remove the last AND keyword, when you exit the loop.

Compare date from database using parameters

string queryString = "SELECT SUM(skupaj_kalorij)as Skupaj_Kalorij "
+ "FROM (obroki_save LEFT JOIN users ON obroki_save.ID_uporabnika=users.ID)"
+ "WHERE (users.ID= " + a.ToString() + ") AND (obroki_save.datum= #datum)";
using (OleDbCommand cmd = new OleDbCommand(queryString,database))
{
DateTime datum = DateTime.Today;
cmd.Parameters.AddWithValue("#datum", datum);
}
loadDataGrid2(queryString);
I tried now with parameters. But i don't really know how to do it correctly. I tried like this, but the parameter datum doesn't get any value(according to c#).
please try this :
database = new OleDbConnection(connectionString);
database.Open();
date = DateTime.Now.ToShortDateString();
string queryString = "SELECT SUM(skupaj_kalorij)as Skupaj_Kalorij "
+ "FROM (obroki_save LEFT JOIN users ON obroki_save.ID_uporabnika=users.ID)"
+ "WHERE users.ID= " + a.ToString()+" AND obroki_save.datum= '" +DateTime.Today.ToShortDateString() + "'";
loadDataGrid2(queryString);
when you use with Date, you must write like this
select * from table where date = '#date'
not like
select * from table where date = #date
While it's usually useful to post the error, I'd hazard a guess and say that you're getting a conversion error with your date.
You should really look at parameterising your queries...
You should read this: http://www.aspnet101.com/2007/03/parameterized-queries-in-asp-net/
And if you can't be bothered reading that, then try changing your 'a' variable to '1; DROP TABLE obroki; --' (but only after you back up your database).
Perhaps you need to write your SQL string in the SQL dialect of the database you're using. In Jet/ACE SQL (what's used by Access), the delimiter for date values is #, so you'd need this:
obroki_save.datum= #" +DateTime.Today.ToShortDateString() + "#"
Of course, some data interface libraries translate these things for you, so that may not be the problem here.

Categories

Resources