i have this sql query
"select * from table where name like ?"
but I want it to work as
"select * from table where name like ?* "
what is the query please
I am using access with c#
Add * to your parameter. I.e., instead of
myCommand.Parameters.AddWithValue("#search", searchValue);
use
myCommand.Parameters.AddWithValue("#search", searchValue + "*");
Keep your SQL as it is.
If you want to do a wildcard search (instead of a "literal *"), note that ADO.NET uses %, not *:
myCommand.Parameters.AddWithValue("#search", searchValue + "%");
Related
I have a utility that generates query strings, but the static code analyzers (and my coworkers) are complaining because of risk of "SQL Injection Attack".
Here is my C# code
public static string[] GenerateQueries(string TableName, string ColumnName)
{
return new string[] {
"SELECT * FROM " + TableName,
"SELECT * FROM " + TableName + " WHERE 1=2",
"SELECT * FROM " + TableName + " WHERE [" + TableName + "Id] = #id",
"SELECT * FROM " + TableName + " WHERE [" + TableName + "Id] = IDENT_CURRENT('" + TableName + "')",
"SELECT * FROM " + TableName + " WHERE [" + ColumnName + "] = #value"
};
}
In the code I always call it only with constant strings, such as
var queryList = GenerateQueries("Person", "Name");
Is there any way to rewrite this function so that it is "safe"? For example, if I were using C instead of C#, I could write a macro to generate the strings safely.
At the moment, the only choice I have is to copy/paste this block of SELECT statements for every single table, which is ugly and a maintenance burden.
Is copy/paste really my only option?
EDIT:
Thank you for the replies, esp William Leader. Now I see that my question is wrong-headed. It isn't just the fact that I am concatenating query strings, but also storing them in a variable. The only proper way to do this is to construct the SqlDataAdapter using a constant such as,
var adapter = new SqlDataAdapter("SELECT * FROM PERSON");
There is no other choice. So yes, there will be a lot of copy/paste. I'm starting to regret not using EF.
I was shocked at first, but on reflection this is no different than having an SQL statement already in your code that looks like this:
"SELECT * FROM Person"
We do that kind of thing all the time.
IF
There's an important caveat here. That only remains true if you can control how the function is called. So if this method is a private member of a data layer class somewhere, you might be okay. But I also wonder how useful this really is. It seems like you're not saving much over what you'd get from just writing the queries.
Additionally, it's not good to be in the habit of ignoring your static analysis tools. Sometimes they give you stuff you just know is wrong, but you change it anyway so that when they do find something important you're not conditioned to ignore it.
What your Code analyser is telling you is that you should most likely be calling a procedure with some parameters instead of sending SQL across the wire.
It does not mater a single bit whether or not you use a macro to generate your SQL statements, if you are sending raw SQL across the wire you are open to SQL Injection Attacks
Sending SQL commands to an endpoint making a non sanctioned call. If we fire up a network packet sniffer, we can see that you have a database configured to allow SQL commands to be sent, so we can inject illegal SQL into the system
You could still rely on a single procedure for calling your updates, but if you elect to move to procedures, why would you want to do that?
EDITED to provide an example
create PROC sp_CommonSelectFromTableProc #tableName varchar(32)
AS
-- code to check the tableName parameter does not contain SQL and/or is a valid tableName
-- your procedure code here will probable use
-- exec mydynamicSQLString
-- where mydynamicSQLString is constructed using #tableName
END;
or maybe a table specific procedure
create PROC sp_SelectFromSpecificTableProc
AS
SELECT * FROM SpecificTable
END;
What is important to remember is that SQL injection is independent of the technology used for the underlying application.
It is just overt when the application contains such constructs as
return new string[] {
"SELECT * FROM " + TableName,
"SELECT * FROM " + TableName + " WHERE 1=2",
"SELECT * FROM " + TableName + " WHERE [" + TableName + "Id] = #id",
"SELECT * FROM " + TableName + " WHERE [" + TableName + "Id] = IDENT_CURRENT('" + TableName + "')",
"SELECT * FROM " + TableName + " WHERE [" + ColumnName + "] = #value"
SQL Injection must be addressed at both ends of the data channel.
Here is a pretty good starting point for understanding how to mitigate for SQL Injection attacks
Here is the code,.
var query = "SELECT * FROM [dbo].[LDDAP-ADA_Header] WHERE ADANo LIKE '%' + '" + data + "' + '%'";
That is how the Like operator works.
SELECT column_name(s)
FROM table_name
WHERE column_name LIKE pattern
The "%" sign is used to define wildcards (missing letters)
WHERE title LIKE '%computer%' finds all strings with the word 'computer' anywhere in the string.
It's a combination of C# string concatenation and SQL string concatenation.
C# part:
string b = "B";
string x = "A" + b + "C";
//gives you "ABC"
SQL:
'A' + 'B' + 'C'
// gives you 'ABC'
Combined:
sql = "'A' + '" + b + "' + 'C'";
Results in C# string
sql = "'A' + 'B' + 'C'"
Which results in SQL in
'ABC'
In your case, it results in
ADANo LIKE '%mydata%'
while mydata is the contents of data. It uses the LIKE comparsion operator on the field ADANo, which returns all the records where data is contained in ADANo. The % characters are wildcards, which mean that any number of any character can be before or after data.
By the way, if data is coming from the user, this kind of code is vulnerable to SQL injection. It means, that a user can execute arbitrary SQL on the database by passing it as data with some tricks. To avoid this, use a parameterized query.
It indeed looks redundant to split the `'%' and 'data'.
If we use the new $ syntax we get this:
var query = $"SELECT * FROM [dbo].[LDDAP-ADA_Header] WHERE ADANo LIKE '%' + '{data}' + '%'";
Now suppose data is foobar.
This results in
var query = $"SELECT * FROM [dbo].[LDDAP-ADA_Header] WHERE ADANo LIKE '%' + 'foobar' + '%'";
Which in turn results in
SELECT * FROM [dbo].[LDDAP-ADA_Header] WHERE ADANo LIKE '%foobar%'
So you can rewrite your statement to:
var query = $"SELECT * FROM [dbo].[LDDAP-ADA_Header] WHERE ADANo LIKE '%{data}%'";
Or with your string concat syntax:
var query = "SELECT * FROM [dbo].[LDDAP-ADA_Header] WHERE ADANo LIKE '%" + data + "%'";
Do notice that this approach (in general, not before or after these changes) is vulnerable to SQL Injection.
For example, what's the query when data is "FOO'; DELETE FROM [dbo].[LDDAP-ADA_Header]; --"
So your end result then is
"SELECT * FROM [dbo].[LDDAP-ADA_Header] WHERE ADANo LIKE '%FOO'; DELETE FROM [dbo].[LDDAP-ADA_Header]; --%'"
Which will clear out your table.
That's a plain-text search with the LIKE operator.
LIKE uses escape sequences like % to signify "any number of any characters/numbers here".
Basically the SQL-equivalent of a regex-search/comparison.
SELECT * FROM dbo.[LDDAP-ADA_Header]
WHERE ADANo LIKE '%' + 'foo' + '%'";
However, this code contains two mistakes:
1. Not using parameters, so it's vulnerable to SQL-injection.
2. Not escaping characters inside the string, like %
More correctly, this would be:
var query = "SELECT * FROM [dbo].[LDDAP-ADA_Header] WHERE ADANo LIKE '%' + '" + data.Replace("'", "''") + "' + '%'";
assuming data cannot be NULL, which probably doesn't have to be that way.
But for this to actually work, you'd need to use ESCAPE in the like-clause (and concat all characters in the string with \).
e.g. "% of size" ==> "\%\ \o\f\ \s\i\z\e"
SELECT * FROM [dbo].[LDDAP-ADA_Header]
WHERE ADANo LIKE '%' + #data + '%' ESCAPE '\'
The problem is, "data" is most-likely a user input field.
The (possibly malicious) user can put into that textbox whatever he wants.
And if you don't do data.Replace("'", "''"), he/she/it can set "data" to
string data = "'; DROP DATABASE whatever; -- "
and then you will have a problem (e.g. if I put "master" in place of "whatever")
Warning
Don't put that string into your data variable, unless you want to miss your master database.
I have following query that works.
string sqlCommandText = "SELECT * FROM Admin_T where AdminID =
'" + textBox.Text + "'";
It is a fix command and I cannot use it with user given Table names and Column names at run time.
What I am actually trying to make is command like
string sqlCommandText = "SELECT * FROM Admin_T where
'" + UserGivenColumnName + "' = '" + conditionTB.Text + "'";
"UserGivenColumnName" can be any column that is part of that specific table.
Trying to create flexibility so that same command can be used under different circumstances.
SqlCommand and none of related classes used by ADO.NET does not support such a functionality as far as I know.
Of course your should never build your sql queries with string concatenation. You should always use parameterized queries. This kind of string concatenations are open for SQL Injection attacks.
But prepared statements only for values, not column names or table names. If you really wanna put your input string to your column name, create a whitelist and use it as a validation before you put it in your query.
http://codeblog.jonskeet.uk/2014/08/08/the-bobbytables-culture/
I think an Object-Relational Mapper (ORM) is perhaps the droid you are looking for. Entity Framework might be a good place to start.
Please also do take the time to understand what SQL injection is, as the other users have also prompted you to.
It is not returning anything as it is just comparing two strings
With the 'UserGivenColumnName' it is a string comparison
And those two strings are not equal
You can do it (column) by just not including the '
But it is still a bad idea
SQLinjection is a very real and very bad thing
string sqlCommandText =
"SELECT * FROM Admin_T where " + UserGivenColumnName + " = '" + conditionTB.Text + "'";
or
string sqlCommandText =
"SELECT * FROM Admin_T where [" + UserGivenColumnName + "] = '" + conditionTB.Text + "'";
I'm having troubles trying to execute a SQL query with repeated parameters using entity framework.
The query is a keyword search, that looks in different tables, therefore using the same parameter many times. I'm using LIKE statements (yes, I know I should be using FULLTEXTSEARCH, but I don't have time for that right now).
I've tried all the syntax explained here: How to use DbContext.Database.SqlQuery<TElement>(sql, params) with stored procedure? EF Code First CTP5 and none of them make the query work (I get zero returned rows).
I even tried building a string array in runtime, with length equal to the number of times the parameter repeats in the query, and then populating all the elements of the array with the keyword search term. Then I passed that as the object[] parameters. Didn't work either.
The only thing that works is to make a search&replace that is obviously a bad idea because the parameter comes from a text input, and I'll be vulnerable to SQL injection attacks.
The working code (vulnerable to SQL injection attacks, but the query returns rows):
//not the real query, but just for you to have an idea
string query =
"SELECT Field1, " +
" Field2 " +
"FROM Table1 " +
"WHERE UPPER(Field1) LIKE '%{0}%' " +
"OR UPPER(Field2) LIKE '%{0}%'";
//keywordSearchTerms is NOT sanitized
query = query.Replace("{0}", keywordSearchTerms.ToUpper());
List<ProjectViewModel> list = null;
using (var context = new MyContext())
{
list = context.Database.SqlQuery<ProjectViewModel>(query, new object[] { }).ToList();
}
return list;
I'm using ASP.NET MVC 4, .NET 4.5, SQL Server 2008 and Entity Framework 5.
Any thoughts on how to make the SQLQuery<> method populate all the occurrences of the parameter in the query string? Thank you very much for your time.
Try this:
string query =
#"SELECT Field1,
Field2
FROM Table1
WHERE UPPER(Field1) LIKE '%' + #searchTerm + '%'
OR UPPER(Field2) LIKE '%' + #searchTerm + '%'";
context.SqlQuery<ProjectViewModel>(query, new SqlParameter("#searchTerm", searchTerm)).ToList();
You can use parameters in your query. Something like this
string query =
"SELECT Field1, " +
" Field2 " +
"FROM Table1 " +
"WHERE UPPER(Field1) LIKE #searchTerm" +
"OR UPPER(Field2) LIKE #searchTerm";
string search= string.Format("%{0}%", keywordSearchTerms);
context.SqlQuery<ProjectViewModel>(query, new SqlParameter("#searchTerm", search)).ToList();
how about try this
string query =
string.Format("SELECT Field1, Field2 FROM Table1 WHERE UPPER(Field1) LIKE '%{0}%'
OR UPPER(Field2) LIKE '%{0}%'",keywordSearchTerms.ToUpper());
context. Database.SqlQuery< ProjectViewModel >(query)
This Oracle SQL query written in c# is giving me the following error : invalid character
qur = " select * from emp where name LIKE '%" + TextBox1.Text + "%'";
How can I solve this?
The problem is your query is very open to Sql Injection attacks. Since you are not using parametrized queries anything entered in TextBox1 can crush your query.
for example if I enter : ' char in Textbox your query will be select * from emp where name LIKE '%'%' and it will throw error. And apart from that it is vulnerability and you should not use such queries.
You can change query to :
SqlCommand cmd= new SqlCommand( " select * from emp where name LIKE #myParam");
cmd.Parameters.AddWithValue("#myParam", "%" + TextBox1.Text + "%");
you missed #
How do parameterized queries help against SQL injection?
C# constructing parameter query SQL - LIKE %
you should use it as below:
qur = " select * from emp where name LIKE '%'" + TextBox1.Text + "'%'";