How to generate SQL statement from List? - c#

If I have a list of Strings, ie. List<String>, how can I generate a SQL statement such as:
SELECT Column1 FROM Table1 WHERE Column1 IN ('String1','String2','String3')
where 'String1','String2','String3' are the contents of List<String>?
No LINQ etc. as I am using VS2005.

Take a look on following version
[Test]
public void Test()
{
var list = new List<string> {"String1", "String2", "String3"};
string values = ArrayToString(list);
string sql = string.Format("SELECT Column1 FROM Table1 WHERE Column1 IN ( {0} )", values);
}
private static string ArrayToString(IEnumerable<string> array)
{
var result = new StringBuilder();
foreach (string element in array)
{
if (result.Length > 0)
{
result.Append(", ");
}
result.Append("'");
result.Append(element);
result.Append("'");
}
return result.ToString();
}
result statement SELECT Column1 FROM Table1 WHERE Column1 IN ( 'String1', 'String2', 'String3' )

List<string> lst=new List<string>();lst.Add("Hello");lst.Add("Hello World");
string s="";
foreach(string l in lst)s+="\""+l+"\"";
s=Regex.Replace(s,"\"\"","\",\"");
string output="SELECT Column1 FROM Table1 WHERE Column1 ("+s+")";

try :
List<String> strlist = new List<string>();
strlist.Add("st1");
strlist.Add("st2");
strlist.Add("st3");
string query = "SELECT Column1 FROM Table1 WHERE Column1 IN (";
for (int i = 0; i < strlist.Count; i++)
{
query += "\'" + strlist[i] + "\'" + (i == strlist.Count - 1 ? "" : ",");
}
query += ")";

List<string> items = new List<string>();
items.Add("string1");
items.Add("string2");
items.Add("string3");
string AllItems = "";
foreach (string item in items)
{
AllItems += string.Format("\"{0}\",",item);
}
AllItems = AllItems.TrimEnd(',');
string YourSQLQuery = string.Format("SELECT Column1 FROM Table1 WHERE Column1 IN ({0})", AllItems);
MessageBox.Show(YourSQLQuery);

Don't for get to guard against SQL Injection.
string sql_list = "";
foreach (string s in lst)
sql_list+=string.Format("{0},",s.Replace("'","''"));
sql_list = string.Format("({0})",sql_list.substring(0,sql_list.length-2));
that might help some, and use string builder, or not.

Please don't use the other answers that have been submitted so far. They contain SQL injection for no obvious reason.
List<String> strlist = new List<string>();
strlist.Add("st1");
strlist.Add("st2");
strlist.Add("st3");
var dynamicPart = string.Join(", ",
Enumerable.Range(0, strlist.Count).Select(i => "#" + i).ToArray());
for(i = 0 to strlist.Count)
{ /* add parameter to SqlCommand here with name ("#" + i) */ }
string query = "SELECT Column1 FROM Table1 WHERE Column1 IN (" +
dynamicPart + ")";
Use parameters instead of literals for multiple reasons (research them!).
And instead of a clumsy concatenation loop use string.Join which does all of that for us.

To properly handle sql injection, a better answer may be to make the query of the form...
select results.* from (
select pk from table where column=value1 union
select pk from table where column=value2 union
select pk from table where column=value3 union
select pk from table where column=value4 union
select pk from table where column=value5
) filtered join table as results on filtered.pk = results.pk
and then make it more c# friendly
string items_filter = "";
int item_index=0;
OracleParameterCollection parameters = new OracleParameterCollection(); // Not sure what class to use here exactly, but just collect a bunch of stored procedure parameters
foreach (string item in list_of_items) {
string item_name = string.Format("i_item{0}",item_index);
string item_sql = string.Format("select pk from table where column=:{0} union",item_name);
parameters.Add(new Parameter("item_name",item));
item_index+=1;
}
if (items_filter.IsNullOrEmpty())
return;
string sql = String.Format("select results.* from ({0}) filtered join table as results on filtered.pk = results.pk",items_filter);
OracleCommand c = new OracleCommand();
c.command = sql;
c.parameters = parameters;
c.execute();
More or less.

Since you said its an internal operation and hence there is no need to be worried about SQL Injection, then you can achieve what you want by this.
string str = "";
foreach(string s in list)
str += "'" + s.Replace("'", "''") + "',";
str = str.SubString(0, str.Length - 1);
str = "SELECT Column1 FROM Table1 WHERE Column1 IN (" + str + ")";
//str will have your command ready.
I have tested it. It works perfectly.

// Assume your list (List<string>) is named "myList"
// Please put the next line in an external string resource...
string selectStatement = "SELECT Column1 FROM Table1 WHERE Column1 IN ({0})";
StringBuilder stringBuilder = new StringBuilder("(");
foreach(string colName in myList)
stringBuilder.Append(String.Format("'{0}',", colName));
stringBuilder.Append(")");
return String.Format(selectStatement, stringBuilder.ToString().Replace(",)", ")");

Related

Using code for creating SQL query

I like to do something like this in code:
string[] columns = new string[]{"col1, col2"};
var query = SELECT(columns).FROM("ANY_TABLE");
string strQuery = query.ToString();
and strQuery should contain now a sql query as string like:
SELECT col1, col2 FROM ANY_TABLE
I tried already to find something like this but I don't know any labels which I could use.
I know there is LINQ but I think it only works with EF and not sure whether it can output such a string.
THANKS
A simple approach could be:
string[] columns = new string[] { "col1", "col2" };
var query = #"SELECT ";
foreach(var column in columns)
{
query += " " + column + ", ";
}
query = query.Substring(0, query.Length-2);
query += #" FROM ANY_TABLE ";
string strQuery = query.ToString();

How to send several strings separated by comma to be used in the WHERE IN clause through 1 SqlParameter?

I've a query that looks like:
string sqlText = #"SELECT col1, col3, col3
FROM table
WHERE col1 IN (#listOFValues)";
string listOfValues = GetListOfValues(userName);
paramList.Add(new SqlParameter("#listOFValues", listOFValues));
//..
private string GetListOfValues(string userName)
{
var dt = ExecuteSqlQueryReturnsDataTable(userName); //this returns a datatable.
string listOfValues = new StringBuilder();
if(dt.Rows.Count == 1)
{
listOfValues.Append("'" + dt.Rows[0]["myColumnName"] + "'");
}
if (dt.Rows.Count > 1)
{
for (int i = 0; i < dt.Rows.Count - 1; i++)
{
listOfValues.Append("'" + dt.Rows[i]["myColumnName"] + "', ");
}
listOfValues.Append("'" + dt.Rows[dt.Rows.Count - 1]["myColumnName"] + "'");
}
return listOfValues.ToString();
}
Bottom line, all I want is to be able to generate something like 'val1', 'val2', 'val3' to be plugged in the WHERE clause like this WHERE col1 IN ('val1', 'val2', 'val3')
Thanks for helping
Firstly, it's a little dangerous to rely on just commas, since your data may contain one, causing the only thing to break.
With that note, you could do the following:
string sqlText = #"
SELECT col1, col3, col3
FROM table
WHERE col1 IN ({0})";
string[] arrOfValues = GetListOfValues(userName).Split(',');
string[] paramArray = arrOfValues.Select((x, i) => "#value" + i).ToArray();
cmd.CommandText = string.Format(sqlText, string.Join(",", paramArray));
for (int i = 0; i < arrOfValues.Length; ++i)
{
cmd.Parameters.Add(new SqlParameter("#value" + i, arrOfValues[i]));
}

SQL find rows with key specified in list, C#

I want to make a sql query in C# that finds all rows with a key that is specified in a list. Can I do this with one query? I suppose that is much more efficent than my solution which finds one item at the time inside a for loop, se below:
foreach (int i in list)
{
string Q = "... where pk = " + i.ToString();
using (SqlCommand CM = new SqlCommand(Q, C))
{
using (SqlDataReader R = CM.ExecuteReader())
{
while (R.Read())
{
...
}
}
}
}
list contains different in values.
Thanks in advance!
Replace
string Q = "... where pk = " + i.ToString();
with
string Q = "... where pk IN ('" + string.Join("','", list)+"')";
then you can remove the loop. The result should look like ... where pk IN ('1','2','3')
You can use the IN keyword and pass your list by converting it to a comma seperated string in your query.
Something like
string Q = "select * from tablename where pk IN " + (comma seperated list here);

Compare query from database with string C#

I am making a program in C# with access database. I want to check if a string from the database is in a string.
I have a table named keyword and I have a string who has some text in it. So, I want to check if any of the strings in the database is in the text, one by one.
Let's say I have this in my database:
"ABC", "CDE", "EFG"
and I have this text:
string a = "and abc asd dsa efg"
And I want to fill a label - if is true "The string has ABC, EFG" else "NO MATCH"
Thanks in advance,
dnisko
First populate table column values into a string List.
SqlConnection cnn = new SqlConnection(/*Database connection credentails*/);
SqlDataAdapter da = new SqlDataAdapter("select columnName from table", con);
DataSet ds = new DataSet();
da.Fill(ds);
List<string> keyValues= new List<string>();
foreach(DataRow row in ds.Tables[0].Rows)
{
keyValues.Add(row["columnName"].ToString());
}
Then search for string in text one by one.
string a = "and abc asd dsa efg";
string matchedKeys=string.Empty;
bool matchFound = false;
foreach(string key in keyValues)
{
if(a.Contains(key))
{
matchFound=true;
matchedKeys + = key + ",";
}
}
if(matchFound)
lbl.Text = "The string has " + matchedKeys;
else
lblText = " NO Match Found !";
will be easier to achieve on Database side. For SQL Server it will be like
#lookup as your parameter
SELECT k.Word FROM Keywords k
WHERE #lookup like '%' + k.Work + '%'
This will return you a collection of keywords that were found in the string you passed as parameter to this query string (stored procedure)
try to use this
// list from DB
var list = new List<string> { "ABC", "CDE", "EFG" };
var selectedResult = new List<string>();
var a = "and abc asd dsa efg";
list.ForEach(x =>
{
var result = a.ToUpperInvariant().Contains(x.ToUpperInvariant());
if (result)
{
selectedResult.Add(x);
}
});
var joined = selectedResult.Count > 0 ? string.Join(",", selectedResult) : "No Match";

How to get table name from string that contain SELECT statement

i have a string that contain a sql command,
something like this:
strCommand = "Select [Feild1],
[Feild2]
From TableName
Order By [Feild1] desc" ;
How can find table name in this string?
The solutions so far have all gone with the searching within strings approach. You've not mentioned if your SQL queries will always look similar, but there are many variants of a query to include which these solutions will break on. Consider...
SELECT Field1, Field2 FROM TableName
SELECT Field1, Field2 FROM [TableName]
SELECT Field1, Field2 FROM dbo.TableName
SELECT Field1, Field2 FROM Table1Name, Table2Name
If the query you're trying to parse is one you have the database for, you can get SQL server to do the hard work of parsing the query for you, instead of trying to account for all the cases in SQL. You can execute a query using SET SHOWPLAN_ALL ON, which will produce a table of the query plan. You can then analyse the Arguments column, which contains all of the fields the query will involve in a standard format. An example program is below:
SqlConnection conn = new SqlConnection(CONNECTIONSTRING);
conn.Open();
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "SET SHOWPLAN_ALL ON";
cmd.ExecuteNonQuery();
cmd.CommandText = "SELECT [Field1], [Field2] FROM [TableName]";
DataTable dt = new DataTable();
dt.Load(cmd.ExecuteReader());
Regex objectRegex = new Regex(#"^OBJECT:\(\[(?<database>[^\]]+)\]\.\[(?<schema>[^\]]+)\]\.\[(?<table>[^\]]+)\]\.\[(?<field>[^\]]+)\]\)$", RegexOptions.ExplicitCapture);
List<string> lstTables = new List<string>();
foreach (DataRow row in dt.Rows)
{
string argument = row["Argument"].ToString();
if (!String.IsNullOrEmpty(argument))
{
Match m = objectRegex.Match(argument);
if (m.Success)
{
string table = m.Groups["schema"] + "." + m.Groups["table"];
if (!lstTables.Contains(table))
{
lstTables.Add(table);
}
}
}
}
Console.WriteLine("Query uses the following tables: " + String.Join(", ", lstTables));
This will deal with all forms of query name and return all tables which are involved in the query, no matter how they are included.
If this is the same pattern all of the time then:
string tableName = strCommand.Split(' ', strCommand)[4];
but if you can add / remove fields just iterate through the splitted string and search for "From", and the next string will be your table name
I would say- what is after "From" as a more reliable way of getting the table name. Loop through the array created, when you reach "From", the next one is the table.
This is the Method which gives us tablename just change the SQL query string, connection String
Works with simple query, joins too
public static List<string> getTablenames(string connString, string QueryString)
{
SqlConnection con = new SqlConnection(connString);
con.Open();
DataTable dt = con.GetSchema("Tables");
List<string> getTableName = new List<string>();
List<string> tablenames = new List<string>();
foreach (DataRow dr in dt.Rows)
tablenames.Add(dr[2].ToString());
for (int i = 0; i < dt.Rows.Count; i++)
{
string myTable = tablenames[i];
Boolean checkMyTable = QueryString.Contains(myTable);
if (checkMyTable == true)
getTableName.Add(myTable);
}
con.Close();
return getTableName;
}
You can use the substring (This way it does not matter how many column you have to select)
string table = strCommand.ToLower().Substring(strCommand.IndexOf("FROM".ToLower())).Split(' ')[0];
ISun's answer met my needs but one change is required to get the table name:
string table = strCommand.ToLower().Substring(strCommand.IndexOf("FROM".ToLower())).Split(' ')[1];
not
string table = strCommand.ToLower().Substring(strCommand.IndexOf("FROM".ToLower())).Split(' ')[0];
If you want a solution in SQL, try this
declare #q varchar(1000) = 'Select [Feild1], [Feild2] From TableName Order By [Feild1] desc',
#tableName varchar(100) = '',
#temp varchar(1000),
#temp2 char(1)
declare #frmIndex int = CHARINDEX('From', #q, 0);
declare #flag int = 0, #counter int = 1;
select #temp = SUBSTRING(#q, #frmIndex, len(#q))
set #temp = LTRIM(REPLACE(#temp,'From',''))
while(#flag <> 1)
begin
set #temp2 = SUBSTRING(#temp, #counter, 1)
if(#temp2 = ' ')
set #flag = 1
select #tableName = #tableName + #temp2
set #counter = #counter + 1
end
select #tableName as TableName

Categories