Problem with db.Database.SqlQuery() usage in C# - c#

I am a newbie in C#. I wrote a code as below
TestDBEntities db = new TestDBEntities();
string data = db.Database.SqlQuery<string>("select PASSWORD from User where USERNAME='admin'").FirstOrDefault();
When I execute this code, an error appears:
Incorrect syntax near the keyword 'User'
Why did this happen? I already have a table named "User".
Thanks for the comments.

Change you sql query to below code:
"select [PASSWORD] from [User] where [USERNAME]='admin'"
and let us know, which database are you using? (SQL Server or MySQL or ...)
"And avoid naming your DB tables, columns, etc. using reserved keywords"

User is a typical SQL reserved word.
Not a good practice to use SQL reserved words for a table name.
A list of reserved words here: https://www.drupal.org/docs/develop/coding-standards/list-of-sql-reserved-words

Related

Syntax Error In Insert Statement SQL C#

I'm having trouble with the df.ExecuteNonQuery(); claiming that the insert statement has SQL errors. I'm not sure why the other parts of the program is working with the Insert statement, but the student one just refuses to work.
Database: http://puu.sh/hoTCv/c1ccb77551.png
OleDbCommand df = new OleDbCommand("INSERT into Students(ID,Password,FirstName,LastName,Street,City,State,Zip,EMail,GPA)" + "VALUES (?,?,?,?,?,?,?,?,?,?)", db);
//creating parameters
df.Parameters.AddWithValue("#ID", iDText.Text);
df.Parameters.AddWithValue("#Password", PassText.Text);
df.Parameters.AddWithValue("#FirstName", fnText.Text);
df.Parameters.AddWithValue("#LastName", LnText.Text);
df.Parameters.AddWithValue("#Street", StreetText.Text);
df.Parameters.AddWithValue("#City", CityText.Text);
df.Parameters.AddWithValue("#State", StateText.Text);
df.Parameters.AddWithValue("#Zip", ZipText.Text);
df.Parameters.AddWithValue("#EMail", EmailText.Text);
df.Parameters.AddWithValue("#GPA", GPAText.Text);
df.ExecuteNonQuery();
db.Close();
Password is a reserved keyword in Microsoft OLE DB Provider. You need to use square brackets like [Password]. As a best practice, change your column name to non-reserved word.
Also don't use AddWithValue method. It may generate unexpected results. Use .Add() overloads to specify your OleDbType and your parameter size.
And would be better to use using statement to dispose your OleDbConnection and OleDbCommand automatically instead calling .Close() or .Dispose() methods manually.
Can this:
INSERT into Students(ID,Password ....
To this:
INSERT into Students(ID,[Password] ....
Password is a reserved keyword. Wrap your password like [Password]
Microsoft SQL Server uses reserved keywords for defining,
manipulating, and accessing databases. Reserved keywords are part of
the grammar of the Transact-SQL language that is used by SQL Server to
parse and understand Transact-SQL statements and batches. Although it
is syntactically possible to use SQL Server reserved keywords as
identifiers and object names in Transact-SQL scripts, you can do this
only by using delimited identifiers.

using reserved word as entity name

I'm using NHibernate mapping by code with naming conventions to map my entities. Now I have following error
SQL error - Incorrect syntax near the keyword 'User'.:
I know this is reserved word and I'm wonder how can I use this name (User) as entity name in mapping by conventions.
You can use it by wrapping it around square brackets as it is a reserved keyword in SQL SERVER:
[User]
The word user is a reserved word in SQL Server. If you need to use it as a column name, put brackets around it. This goes for all table names and other user-defined names that happen to collide with keywords,
Example:
Select * from tbl where [User] = 'xyz'
The correct way to deal with this in NHibernate is using SQL Quoted Identifiers.
Just wrap the table or column name in backticks and the Dialect will take care of using the right symbol for your database.
To make things easier, NHibernate provides a configuration setting that does this for you: set hbm2ddl.keywords="auto-quote" in an xml config file, or call AutoQuoteKeywords() when using loquacious.
If the brackets don't work, try this:
"`User`"

Oracle Table column name having special( Danish) characters. Unable to execute sql query

I am using DbDataReader to execute query. Please find the code below
Query is:
select BRANCH_NAME, AMOUNT, ACCOUØNT_ID from ACCOUNT
Error is:
ORA-00904: "ACCOU?NT_ID": invalid identifier .
I am trying to connect oracle database and execute the oracle query.
Please help by how to execute the oracle query which columns have special characters.
Quite possibly
select "BRANCH_NAME", "AMOUNT", "ACCOUØNT_ID" from "ACCOUNT";
will work.
See http://docs.oracle.com/cd/E11882_01/server.112/e10592/sql_elements008.htm for more information on Database Object Naming Rules.

SQL command problems (C# Winforms)

I am successfully connecting to my sql 2008 server hosted on winhost.com. But I am following this tutorial: http://www.codeproject.com/KB/database/sql_in_csharp.aspx which was suggested in an answer from: Connecting to SQL Server Database C#-WinForms and I keep getting the exact same error when I try to:
Insert something into the table.
Retrieve something from the db.
The error is: "Incorrect syntax near the keyword 'table'.".
I don't know what's wrong. The error message is very vague, and everything seems to look fine.
I am using all the examples from the above tutorial, but they all give the same error.
Any suggestions? Does anyone have any other tutorials/articles for me I can have a look at?
Thank you
Where it says INSERT INTO table ... you have to change table to be the actual name of your table as it says in the text just beneath:
Now we will take a look at the values. table is simply the table within the database.
If you chose to call your table table then you can write [table] but it would be better to change the table name to something else.
Where table appears in that tutorial, it's meant to be a 'placeholder' for an actual table name - table by itself is an illegal table name - hence the syntax error. If you need to use this name then [table] would be fine.
TABLE is a reserved word, try surrounding it with brackets, if you have created a table called table.
[table]

How do I protect this function from SQL injection?

public static bool TruncateTable(string dbAlias, string tableName)
{
string sqlStatement = string.Format("TRUNCATE TABLE {0}", tableName);
return ExecuteNonQuery(dbAlias, sqlStatement) > 0;
}
The most common recommendation to fight SQL injection is to use an SQL query parameter (several people on this thread have suggested it).
This is the wrong answer in this case. You can't use an SQL query parameter for a table name in a DDL statement.
SQL query parameters can be used only in place of a literal value in an SQL expression. This is standard in every implementation of SQL.
My recommendation for protecting against SQL injection when you have a table name is to validate the input string against a list of known table names.
You can get a list of valid table names from the INFORMATION_SCHEMA:
SELECT table_name
FROM INFORMATION_SCHEMA.Tables
WHERE table_type = 'BASE TABLE'
AND table_name = #tableName
Now you can pass your input variable to this query as an SQL parameter. If the query returns no rows, you know that the input is not valid to use as a table. If the query returns a row, it matched, so you have more assurance you can use it safely.
You could also validate the table name against a list of specific tables you define as okay for your app to truncate, as #John Buchanan suggests.
Even after validating that tableName exists as a table name in your RDBMS, I would also suggest delimiting the table name, just in case you use table names with spaces or special characters. In Microsoft SQL Server, the default identifier delimiters are square brackets:
string sqlStatement = string.Format("TRUNCATE TABLE [{0}]", tableName);
Now you're only at risk for SQL injection if tableName matches a real table, and you actually use square brackets in the names of your tables!
As far as I know, you can't use parameterized queries to perform DDL statements/ specify table names, at least not in Oracle or Sql Server. What I would do, if I had to have a crazy TruncateTable function, that had to be safe from sql injection would be to make a stored procedure that checks that the input is a table that is safe to truncate.
-- Sql Server specific!
CREATE TABLE TruncableTables (TableName varchar(50))
Insert into TruncableTables values ('MyTable')
go
CREATE PROCEDURE MyTrunc #tableName varchar(50)
AS
BEGIN
declare #IsValidTable int
declare #SqlString nvarchar(50)
select #IsValidTable = Count(*) from TruncableTables where TableName = #tableName
if #IsValidTable > 0
begin
select #SqlString = 'truncate table ' + #tableName
EXECUTE sp_executesql #SqlString
end
END
If you're allowing user-defined input to creep into this function via the tablename variable, I don't think SQL Injection is your only problem.
A better option would be to run this command via its own secure connection and give it no SELECT rights at all. All TRUNCATE needs to run is the ALTER TABLE permission. If you're on SQL 2005 upwards, you could also try using a stored procedure with EXECUTE AS inside.
CREATE OR REPLACE PROCEDURE truncate(ptbl_name IN VARCHAR2) IS
stmt VARCHAR2(100);
BEGIN
stmt := 'TRUNCATE TABLE '||DBMS_ASSERT.SIMPLE_SQL_NAME(ptbl_name);
dbms_output.put_line('<'||stmt||'>');
EXECUTE IMMEDIATE stmt;
END;
Use a stored procedure. Any decent db library (MS Enterprise Library is what I use) will handle escaping string parameters correctly.
Also, re:parameterized queries: I prefer to NOT have to redeploy my app to fix a db issue. Storing queries as literal strings in your source increases maintenance complexity.
Have a look at this link
Does this code prevent SQL injection?
Remove the unwanted from the tableName string.
I do not think you can use param query for a table name.
There are some other posts which will help with the SQL injection, so I'll upvote those, but another thing to consider is how you will be handling permissions for this. If you're granting users db+owner or db_ddladmin roles so that they can truncate tables then simply avoiding standard SQL injection attacks isn't sufficient. A hacker can send in other table names which might be valid, but which you wouldn't want truncated.
If you're giving ALTER TABLE permissions to the users on the specific tables that you will allow to be truncated then you're in a bit better shape, but it's still more than I like to allow in a normal environment.
Usually TRUNCATE TABLE isn't used in normal day-to-day application use. It's used for ETL scenarios or during database maintenance. The only situation where I might imagine it would be used in a front-facing application would be if you allowed users to load a table which is specific for that user for loading purposes, but even then I would probably use a different solution.
Of course, without knowing the specifics around why you're using it, I can't categorically say that you should redesign, but if I got a request for this as a DBA I'd be asking the developer a lot of questions.
Use parameterized queries.
In this concrete example you need protection from SQL injection only if table name comes from external source.
Why would you ever allow this to happen?
If you are allowing some external entity (end user, other system, what?)
to name a table to be dropped, why won't you just give them admin rights.
If you are creating and removing tables to provide some functionality for end user,
don't let them provide names for database objects directly.
Apart from SQL injection, you'll have problems with name clashes etc.
Instead generate real table names yourself (e.g DYNTABLE_00001, DYNTABLE_00002, ...) and keep a table that connects them to the names provided by user.
Some notes on generating dynamic SQL for DDL operations:
In most RDBMS-s you'll have to use dynamic SQL and insert table names as text.
Be extra careful.
Use quoted identifiers ([] in MS SQL Server, "" in all ANSI compliant RDBMS).
This will make avoiding errors caused by invalid names easier.
Do it in stored procedures and check if all referenced objects are valid.
Do not do anything irreversible. E.g. don't drop tables automatically.
You can flag them to be dropped and e-mail your DBA.
She'll drop them after the backup.
Avoid it if you can. If you can't, do what you can to minimize rights to other
(non-dynamic) tables that normal users will have.
You could use SQLParameter to pass in tableName value. As far as I know and tested, SQLParameter takes care of all parameter checking and thus disables possibility of injection.
If you can't use parameterized queries (and you should) ... a simple replace of all instances of ' with '' should work.
string sqlStatement = string.Format("TRUNCATE TABLE {0}", tableName.Replace("'", "''"));

Categories