i'm lost: what is wrong with this ado.net code? - c#

well, the question is clear i hope, the code is this:
string sql = "delete from #tabelnaam";
SqlCommand sc = new SqlCommand();
sc.Connection = getConnection();
sc.CommandType = CommandType.Text;
sc.CommandText = sql;
SqlParameter param = new SqlParameter();
param.Direction = ParameterDirection.Input;
param.ParameterName = "#tabelnaam";
param.Value = tableName;
sc.Parameters.Add(param);
OpenConnection(sc);
sc.ExecuteScalar();
tableName is supplied to this function.
I get the exception:
Must declare the table variable #tabelnaam

IIRC, you cant use a substitute the table name for a parameter.
Rather build the SQL string containing the correct table name.

Make to changes
rather than using paramter use this
string sql = string.format( "delete from {0}",tableName);
make use of executenonquery intead of ExecuteScalar
sc.ExecuteNonQuery();

As mentioned by others, you can't parameterise the table name.
However, as you rightly mention in comments on other answers, using simple string manipulation potentialy introduces a SQL injection risk:
If your table name input is fro an untrusted source, such as user input, then using this:
string sql = string.format( "DELETE FROM {0}",tableName);
leaves you open to the table name "myTable; DROP DATABASE MyDb" being inserted, to give you:
DELETE FROM myDb; DROP DATABASE MyDB
The way round this is to delimit the table name doing something such as this:
string sql = string.format("DELETE FROM dbo.[{0}]", tableName);
in combination with checking that the input does not contain either '[' or ']'; you should probably check it also doesn't contain any other characters that can't be used as a table name, such as period and quotes.

I dont think you can parameterize the table name. From what I have read you can do it via Dynamic sql and calling sp_ExecuteSQL.

Your SQL is incorrect, you are deleting from a table variable yet you haven't defined that variable.
Update: as someone has pointed out, you are trying to dynamically build a query string but have inadvertantly used SQL parameters (these do not act as place holders for string literals).

More here:
Parameterise table name in .NET/SQL?

You cannot parameterise the table name, you have to inject it into the command text.
What you can and should do is protect yourself against SQL injection by delimiting the name thus:
public static string Delimit(string name) {
return "[" + name.Replace("]", "]]") + "]";
}
// Construct the command...
sc.CommandType = CommandType.Text;
sc.CommandText = "delete from " + Delimit(tableName);
sc.ExecuteNonQuery();
See here and here for more background info.

Related

Insert Firebird Database C#

FbCommand fbCmm =
new FbCommand("INSERT INTO PRODUTO
(CODIGO,EAN,DESCRICAO,VAL_PRODUTO,VAL_CUSTO,CAT_PRECO)"
+ "Values (#txt_codigo.Text, #txt_ean, #txt_descricao,
#txt_valPro, #txt_valCus, #txt_catPre)", ConexaoFirebird.Conexao);
What's wrong with that sentence?
I did a open connection in other class - ConexaoFirebird.Conexao();
You're executing a parameterized query without providing values for those parameters. See the documentation:
FbCommand cmd = new FbCommand("insert into t1(id, text) values (#id, #text);");
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add("#id", 123);
cmd.Parameters.Add("#text", "my string");
cmd.ExecuteNonQuery();
Here they bind the values 123 and "my string" to the parameters named id and text respectively.
Also note that parameter names are generally rescticted to alphanumeric, so txt_codigo.Text isn't likely going to work.
You should use quote for decimal, string field types, your statement is correct but not clear, you can create clear sql text with sql command builder or you can use Command object of your connection.

How to execute a delete query that includes a varchar and datetime field in the WHERE clause

Hello i try to delete from a Table where i need to access a varchar note field and an datetimefield.
Here is the Code:
DateTime test = (DateTime)powerPlant.timestamp;
string DateUS = test.ToString("s");
string deletePowerPlant =
String.Format(
"DELETE FROM [dbo].[tblSPpowerPlants] WHERE [timestamp] = CONVERT(datetime,"+ DateUS +",111) AND [note] = {0};",
note);
SqlCommand sqlDelete = new SqlCommand(deleteComponents, sqlConnection);
sqlDeletePowerPlant.CommandType = CommandType.Text;
sqlDeletePowerPlant.CommandText = deleteComponents;
sqlDeletePowerPlant.ExecuteNonQuery();
And yes normally i would use sql parameters but i want to know how it would work without parameters just to test it out becouse somehow it must be possible. I tried to google it and with some other forum and some blogs but had no luck.
Thx for your help and sorry for my english.
EDIT
The Field timestamp is a Datetime in the table.
The note is a nvarchar in the Table. And i just want to use it once so i can say i know how to do it without parameters. I know its bad....
You'll want to make sure there is no dependency on server operating system locale. So if you use a certain format (111 in your case) in the SQL query, you should use the .NET equivalent to convert your date to a string:
string DateUS = test.ToString("yyyy/MM/dd");
For details about the formats that the CONVERT function supports, see here:
https://msdn.microsoft.com/de-de/library/ms187928(v=sql.120).aspx
As you stated yourself in the question, using a (strongly typed) SqlParameter is the preferred way to go. Failing to so so may result in sql injection vulnerabilities.
Given that note is a text column, single quotes and escaping will be required:
String.Format(
"DELETE FROM [dbo].[tblSPpowerPlants] WHERE [timestamp]=CONVERT(datetime,'{0}',111) AND [note]='{1}'",
DateUS
note.Replace("'","''").Replace(#"\",#"\\")
);
If you store time-of-day too, the comparison with = will not affect records with nonzero time component.
Put some string qualifiers in there
DateTime test = (DateTime)powerPlant.timestamp;
string DateUS = test.ToString("s");
string deletePowerPlant = String.Format("DELETE FROM [dbo].[tblSPpowerPlants] WHERE [timestamp] = CONVERT(datetime,'"+ DateUS +"',111) AND [note] = '{0}';", note);
SqlCommand sqlDelete = new SqlCommand(deleteComponents, sqlConnection);
sqlDeletePowerPlant.CommandType = CommandType.Text;
sqlDeletePowerPlant.CommandText = deleteComponents;
sqlDeletePowerPlant.ExecuteNonQuery();
But really. Use parameterized queries

Query updates all of my data instead of only the one I want

How do I make it so that my query only update the data I want?
Here's the current code
string query = string.Format("update Customer set title='{0}',[Name]='{1}'",titleComboBox2.Text,nameTextBox2.Text,"where ID="+idTextBox+"");
Apparently the last part of the query isn't working. Why it is that?
Because you didn't use any index argument as {2} for your third argument which is WHERE part.
That's why your query will be contain only update Customer set title='{0}',[Name]='{1}' part this will be update for your all rows since it doesn't have any filter.
Fun fact, you could see this as query if you would debug your code.
But more important
You should always use parameterized queries. This kind of string concatenations are open for SQL Injection attacks.
Let's assume you use ADO.NET;
using(var con = new SqlConnection(conString))
using(var cmd = con.CreateCommand())
{
cmd.CommandText = #"update Customer set title = #title, [Name] = #name
where ID = #id";
cmd.Paramter.Add("#title", SqlDbType.NVarChar).Value = titleComboBox2.Text;
cmd.Paramter.Add("#name", SqlDbType.NVarChar).Value = nameTextBox2.Text;
cmd.Paramter.Add("#id", SqlDbType.Int).Value = int.Parse(idTextBox.Text);
// I assumed your column types.
con.Open();
cmd.ExecuteNonQuery();
}
Currently your query does not use WHERE clause, because it is ignored by string.Format. You have 3 placeholder parameters, and you are using only {0} and {1}, so WHERE part is never added to the SQL query. Change your query to include WHERE clause, e.g. like this:
string query = string.Format("update Customer set title='{0}',[Name]='{1}' {2}",titleComboBox2.Text,nameTextBox2.Text,"where ID="+idTextBox.Text+"");
However, there is one very serious flaw in your code - it is vulnerable to SQL injection attack. There are hundreds of articles about it online, make sure to read about what that is and how to update your code accordingly (hint - parametrize queries)

OracleCommand Parameter with concatenation

THIS works:
OracleCommand cm = con.CreateCommand();
cmd.CommandText = String.Format("select s,e from {0}" + ".DTREE where DATAID=:pDataId", credentialsthing.dbschema");
cmd.Parameters.Add("pDataId", objectx.theid);
However... I also want to put the first one in the parametr command:
cmd.CommandText = "select s,e from :pPar1" + ".DTREE where DATAID=:pDataId");
cmd.Parameters.Add("pPar1", credentialsthing.dbschema);
cmd.Parameters.Add("pDataId", objectx.theid);
And this fails. Why, what should the syntax be?
Your can't parameterize your table name, column name or any other database objects.
You can only parameterize your values. That's why you need to use string concatenation for your table name.
But you should be very careful doing that, you need to supply strong validation for your table name or should use a whitelist of some form.

SQL inserting variables from different statements

StringBuilder sb = new StringBuilder();
sb.Append("DECLARE #ControlPaneliD int");
sb.Append(" SET #ControlPaneliD=(SELECT ControlPanelID");
sb.Append(" FROM ControlPanelID");
sb.Append(" WHERE Name=#Name)");
sb.Append("DECLARE #UserName UniqueIdentifier");
sb.Append(" SET #UserName=(SELECT Name");
sb.Append(" FROM UsersID");
sb.Append(" WHERE UsersID=#UserID)");
sb.Append("INSERT INTO dbo.CP_Comments (ControlPanelID,Comments,Commentator)");
sb.Append(" VALUES(#ControlPaneliD,#Comment,#UserName)");
MembershipUser CurrentUser = Membership.GetUser();
Guid id = (Guid)CurrentUser.ProviderUserKey;
string myConnectionString = AllQuestionsPresented.connectionString;
using (SqlConnection conn = new SqlConnection(AllQuestionsPresented.connectionString))
{
conn.Open();
SqlCommand cmd = new SqlCommand(sb.ToString(), conn);
cmd.Parameters.Add("UserID", SqlDbType.UniqueIdentifier).Value = id;
cmd.Parameters.Add("Comment", SqlDbType.NVarChar).Value = TextBox1.Text;
cmd.Parameters.Add("Name", SqlDbType.NVarChar).Value = name; //string variable from my code
cmd.ExecuteNonQuery();
}
I am trying to do two select statements, put their results in their variables and insert their variables plus another variable into another insert statement..
I am not sure if I am doing it right, I would appreciate your help if you gave me some advice and some criticism on what I composed
In insert statement you inserting 3 parameters into 2 columns.
I think you should write stored procedure and pass parameters for it. You always "generating" sql code with string builder. And to change some functionality in stored procedure is much easier than find statement in code, change it and rebuild app.
SELECT ControlPanelID FROM ControlPanelID WHERE Name=#Name and SELECT Name FROM UsersID WHERE UsersID=#UserID looks strange. Do you really have tables with names ControlPanelID and UsersID?
Your method looks OK but it is recommended that you use stored procedure instead of passing query
This is really vulnerable to SQL-injection, especially this part:
cmd.Parameters.Add("Comment", SqlDbType.NVarChar).Value = TextBox1.Text;
This is very, very dangerous. I cannot imagine you haven't heard about this, but just in case, check out this wiki article: http://en.wikipedia.org/wiki/SQL_injection
If you really want/ need to execute raw SQL, always escape the values.
Have you considered using a strongly typed DAL like LINQ2SQL, DataEntities etc?
I would rather suggest putting that code in a stored procedure. Its not a good idea to put that in a string builder and execute it.

Categories