I'm trying to fix a problem in an ASP.NET application which uses DataContext.ExecuteQuery to execute sql statement. The query has this part:
LEFT OUTER JOIN dbo.Contacts ON dbo.Accounts.SalesRepId = dbo.Contacts.ContactId WHERE " + string.Join(" AND ", whereClauses) + #"
where "whereClauses" is a List of strings. This way, a search functionality is implemented into the query. Problem appears when an open search is run for a string like "O'Donnel" which obviously run query into an error. I have been asked to fix this problem. My approach was to substitute the where statement with "{0}" in the query and then pass it as a parameter in ExecuteQuery method. What I achieved is:
LEFT OUTER JOIN dbo.Contacts ON dbo.Accounts.SalesRepId = dbo.Contacts.ContactId {0}
var where = "WHERE 1=1";
_db.ExecuteQuery<AccountModel>(query, where)
but it doesn't work? When I substitute the whole where part with just a parameter for it everything is fine:
LEFT OUTER JOIN dbo.Contacts ON dbo.Accounts.SalesRepId = dbo.Contacts.ContactId WHERE 1={0}
var where = "1";
_db.ExecuteQuery<AccountModel>(query, where)
My question - is it then possible to inject the whole where statement dynamically into DataContext.ExecuteQuery method, or can I pass specific parameters only using this method?
Here's the help page for the ExecuteQuery method.
You can't pass the whole where clause as a parameter because a query like select * from myTable #param isn't valid SQL, whereas select * from myTable where myField = #param is valid SQL.
So, in answer to your specific question - no, you can't do this by passing parameters to ExecuteQuery.
However, why not build up the query in code before you pass it to ExecuteQuery?
e.g.
var query = "select * from myTable where 1=1" + string.Join(" AND ", whereClauses);
var result = _db.ExecuteQuery<AccountModel>(query);
Related
This question already has answers here:
IN Operator in OLEDB
(2 answers)
Closed 1 year ago.
I have some data like name,firstname,surname,std,Rollno.
Using C#, I want to convert this into
('name', 'surname', 'std', 'Rollno')
so that I can use this this data to query into the SQL/MySQL DB like -
SELECT *
FROM Table1
WHERE UserCommunicationId IN ('name', 'surname', 'std', 'Rollno');
Instead of
SELECT *
FROM Table1
WHERE UserCommunicationId IN ('name,surname,std,Rollno');
You can try below below logic
public static class SQLQueryExtensions
{
public static string ColumnFormat(this String str)
{
return "(" + //Include first parenthesis
string.Join(", ", str.Split().Select(x => $"'{x}'")) //Add single quote to each column
+ ")"; //Include last parenthesis
}
}
You can do it in one line as well,
var inputStr = "name,firstname,surname,std,Rollno";
var result = "(" + string.Join(", ", inputStr.Split().Select(x => $"'{x}'")) + ")";
Try Online
Use blow logic, will solve your problem.
string inputStr = "name,firstname,surname,std,Rollno";
string result = string.Join(",", inputStr.Split(',').Select(x => string.Format("'{0}'", x)).ToList());
Output = 'name','firstname','surname','std','Rollno'
One approach I can come up is that:
Set the whole string into query as a parameter.
Split it in a WITH query.
LEFT JOIN it in the main query.
NOT NULL to check if there's any hit.
I've wrote an example below, but I am Oracle user so I am not sure if these syntax are right, not even tested, just googled around. Only take it as an reference to the explanation of the idea.
WITH RECURSIVE targets (stringBuffer, word) AS (
SELECT
#Parameter
,NULL
UNION ALL
SELECT
SUBSTRING(stringBuffer, LEAST(LENGTH(SUBSTRING_INDEX(stringBuffer, ',', 1) + 1, LENGTH(stringBuffer)))
,SUBSTRING_INDEX(stringBuffer, ',', 1)
WHERE LENGTH(word) > 0
OR LENGTH(stringBuffer) > 0 -- I am not really sure about these
)
SELECT *
FROM Table1
LEFT JOIN targets ON targets.word = Table1.UserCommunicationId
WHERE targets.word IS NOT NULL;
Then, in C#, set Parameter for your query command in string like this
string s = "name,firstname,surname,std,Rollno";
Edit:
Or, simply:
SELECT *
FROM Table1
WHERE REGEXP_LIKE(UserCommunicationId, #Parameter)
;
While setting the Parameter in C# as:
string s = "name|firstname|surname|std|Rollno";
Notice that if the keywords can be input by user, you still have the problem where user may enter .+ and it responds every data to them as long as there's no other condition added.
But personally, I think there's a potential issue in your design if you really need an unknown length of IN-CLAUSE in your query. If keywords that can be applied are limited in number, you can, rough but it's my team's current criteria, concat the WHERE section keyword by keyword in C#.
I am trying to use interceptor to add WITH (NO LOCK) for some queries (not for all queries, so ReadUncommitted is not a choice).
Code looks like this:
var rawSql = sql.ToString();
if (!rawSql.Contains(IQueryOverExtensions.QueryHintNoLockString))
return sql;
var noWhere = rawSql.Substring(0, rawSql.IndexOf(WhereKeyword, StringComparison.InvariantCulture));
var from = noWhere.Substring(noWhere.IndexOf(FromKeyword, StringComparison.InvariantCulture));
var fromWithNoLock = from.Replace("_ ", $"_ {WithNoLock} ");
var sqlWithNoLock = rawSql.Replace(from, fromWithNoLock);
return base.OnPrepareStatement(new SqlString(sqlWithNoLock));
Here, I take part form FROM clause to WHERE clause and to each alias add WITH (NO LOCK)
The issue is, that the final SQL's parameters are all "?" and exception is thrown that SQL is not valid. Why parameters are not filled in and how to fix it?
Thanks in advance
Finally I got it. I had to get number of parameters by calling sql.GetParameterCount() and then replace all question marks with #p0, #p1, #p2, etc.
I'm facing a problem in PetaPoco, and I can't figure it out.
I'm using this code :
var db = new OracleConnection(_connectionString);
var query = Sql.Builder;
query.Append("SELECT * FROM City WHERE ID = #0", 1);
return db.Query<City>(query.SQL).ToList();
PetaPoco is not adding the parameter to my sql query.
This is an example from their official website :
var id=123;
var sql=PetaPoco.Sql.Builder
.Append("SELECT * FROM articles")
.Append("WHERE article_id=#0", id);
For you information : I'm using the last version of PetaPoco (5.0.1)
I'd skip Sql.Builder (it's gaining you nothing here), and as a side-note, use db.Fetch as it already returns a List. So:
var query = "SELECT * FROM City WHERE ID = #0";
return db.Fetch<City>(query, 1);
Just query to the Query<> method, not just the sql.
Otherwise you need to pass the Arguments as the second parameter.
I am currently trying to build up the where clause of an SqlCommand.
something similar to this
myCommand.CommandText = "SELECT * " +
"FROM TABLE1 " +
"#whereClause";
//I build up the where clause with a StringBuilder
myCommand.Parameters.AddWithValue("#whereClause" theClause.ToString());
But it doesn't seem like this is possible. I got the exception :
SqlException Incorrect syntax near '#whereClause'
The reason I want to do something like this is because I want to avoid X call to the database and this way I leave sorting and filtering to the server.
Is there anyway to do something similar to this?
/edit : The where clause would look something like this WHERE (TABLE1.COL1 = 'the value' OR TABLE1.COL1 = 'another value' OR TABLE1.COL1 = 'this value' ... )
/edit Finaly this was due to a stupid typo error... after I changed to not use the parametrize query. I'll upvote those answer who helped my out. I will mark as answer what was to closer to fix my situation even if it didn't fixed my (stupid) bug
It seems you're trying to add the entire WHERE clause as a parameter - that won't work!
So suppose you need to build something like this
SELECT * from TABLE1 WHERE Field1=#Field1Value and Field2=#Field2Value
And assuming
you have a List<WhereField> of fields to include in the WHERE clause
and that all clauses are ANDed together
and WhereField looks something like this
public class WhereField
{
public string FieldName{get;set;}
public object FieldValue{get;set;}
public string ComparisonOperator{get;set;}
}
then you have something like this:
var whereClause = new StringBuilder();
foreach (var field in WhereFields)
{
whereClause.Append(field.FieldName)
.Append(field.ComparisonOperator)
.Append("#")
.Append(field.FieldName).Append("Value")
.Append (" AND ");
//add the parameter as well:
myCommand.Parameters.AddWithValue("",field.FieldName+"Value");
}
//cleanly close the where clause
whereClause.Append("1=1");
And now you can execute
myCommand.CommandText = "SELECT * " +
"FROM TABLE1 WHERE " + whereClause.ToString();
You can't use a clause (where) with parameters, you are only allowed to use parameters with command.Parameters.
To build a dynamic Where clause, you have to build your query based on conditions and string concatenation and then add the parameters accordingly.
Something like:
sb.Append("SELECT * FROM TABLE1 ");
if (someCondition)
{
sb.Append("WHERE XColumn = #XColumn");
myCommand.Parameters.AddWithValue("#XColumn", "SomeValue");
}
else
{
sb.Append("WHERE YColumn = #YColumn");
myCommand.Parameters.AddWithValue("#YColumn", "SomeOtherValue");
}
myCommand.CommandText = sb.ToString();
May be you need
myCommand.CommandText = "SELECT * " +
"FROM TABLE1 WHERE " +
"#whereClause";
I've got the following query that returns 2 records (in DataSet's query builder)
SELECT EmpID, Name, id
FROM Users
WHERE (CAST(id AS Varchar(20)) IN ('5688','5689'))
Now if I do the same query passing the parameter instead from code behind: String param = "'5688','5689'"; it returns null.
WHERE (CAST(id AS Varchar(20)) IN (#param))
I tried taking off the very first and last ', but that did not make a diffrence.
!!!id is a unique PK!!!
Anyone's got a clue?
The solution I found is quite simple, this works like a charm and there's no need for sps or other functions;
SQL:
SELECT whatever
FROM whatever
WHERE (PATINDEX('%''' + CAST(id AS Varchar(20)) + '''%', #param) > 0)
C#:
String param = "'''1234'',''4567'''";
dataTable1 = tableAdapter1.getYourValues(param);
A variable is not allowed in the IN clause.
You are expecting the values as a comma delimited string you could use the split function (user defined and non-standard) to join them with the original tables:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=326300&SiteID=1
For more information you can visit this
('5688','5689') is an array of values.
Defining String param = "'5688','5689'"; and using it as (#param) makes ('5688','5689') a string. Which wont work.
Bibhas is correct. For me this worked:
string param="'1234','4567'"; we can't use param as SQL Parameter(#param).
command = new SqlCommand("SELECT * FROM table WHERE number IN (" + param + ")", connection);
command.ExcecuteReader();