I am trying to change the datatype of one of the columns in a table using SqlCommand with parameters, but it doesn't work.
Here is my code:
Dictionary<string,string> dict = new Dictionary<string,string>();
dict.Add("#TableName",TableColumnArray[0].ToString( ));
dict.Add("#ColumnName",TableColumnArray[1].ToString( ));
DBSql.ExecSQLStatement( "ALTER TABLE #TableName ALTER COLUMN #ColumnName varchar(MAX)",dict,connectionStringName);
public static void ExecSQLStatement (string strsql,Dictionary<string,string> dict,string connectionStringName)
{
SqlConnection con = CreateSqlConnectionStr(connectionStringName);
SqlCommand cmd = new SqlCommand(strsql,con);
foreach(string dictKey in dict.Keys)
{
cmd.Parameters.Add(new SqlParameter(dictKey,dict[dictKey]));
}
con.Open( );
cmd.ExecuteNonQuery( );
con.Close( );
}
But the code keeps throwing an error:"Incorrect syntax near #TableName". I cannot find the solution to this problem. I could try to use stored procedures, but I really want to know why the code is not working. I usually use SqlCommand with parameters for select,insert statements, but it seems it doesnt work with alter statements?
because by default, tableName and column names CANNOT BE PARAMETERIZED. One way you can do to avoid sql injection is to create a User Define Function that check if the tableName is valid or not. Then concatenate the name on the string. eg,
Here's the UDF
private bool IsValidColumnNameOrTableName(string tablecolumnName)
{
// other codes
return returnValue;
}
You cannot use parameters in DDL statements. You should create the statement string dynamically:
DBSql.ExecSQLStatement(
"ALTER TABLE " + TableColumnArray[0] + " ALTER COLUMN " + TableColumnArray[1] + " varchar(MAX)",
dict,connectionStringName);
you need specify table name and column name exactly:
"ALTER TABLE " + TableColumnArray[0].ToString( ) + " ALTER COLUMN " + TableColumnArray[1].ToString( ) + "varchar(MAX)"
sql server does not allow syntax where table names and column names are variable values
Related
Here's my code.
public void setUpdate(List<string> code, string tableName)
{
SQLiteConnection con = new SQLiteConnection(connection);
SQLiteCommand UPDATE = new SQLiteCommand("UPDATE #TableName SET #ColumnName = #Value WHERE Key = #PK", con);
UPDATE.Parameters.AddWithValue("#TableName", "TEST");
UPDATE.Parameters.AddWithValue("#ColumnName", code[1]);
UPDATE.Parameters.AddWithValue("#Value", code[2]);
UPDATE.Parameters.AddWithValue("#PK", code[0]);
using (con)
{
con.Open();
UPDATE.ExecuteNonQuery();
}
}
And I'm getting this exception
System.Data.SQLite.SQLiteException: 'SQL logic error
near "#TableName": syntax error'
I already tried using
UPDATE.Parameters.Add(new SQLiteParameter("#TableName", DbType.String) .Value = tableName);
Still getting the same exception.
I don't know anymore how to solve this.
I don't wanna use the concatenation because it screws up the query when you pass a value like the one below.
Smith's
EDIT:
I placed a breakpoint on
using (con)
Then checked the commandText. The result is:
"UPDATE #TableName SET #ColumnName = #Value WHERE Key = #PK"
I think there is the problem with table name as a parameter.
So firstly try to left all parameters except of table name (hardcode 'TEST' into query temporarily) and if it works take a look on this:
C# query with dynamic tablename
Again, trying to build a query with from and column names you can't do as PARAMETER. They need to be fixed in the string. BUT CAUTION. DO NOT Allow the table/column/etc parts that you build come from an untrusted source, especially the web for damage of SQL-Injection.
If your system is controlling the origin AND QUALIFIED, or otherwise internally control the table name being passed in, AND you control / qualify the column name being passed in, I would adjust your function as follows:
public void setUpdate(List<string> code, string tableName)
{
SQLiteConnection con = new SQLiteConnection(connection);
SQLiteCommand UPDATE = new SQLiteCommand(
"UPDATE " + tableName + " set " + code[1] + " = #Value WHERE Key = #PK", con);
UPDATE.Parameters.AddWithValue("#Value", code[2]);
UPDATE.Parameters.AddWithValue("#PK", code[0]);
using (con)
{
con.Open();
UPDATE.ExecuteNonQuery();
con.Close();
}
}
Again, this is on the premise that YOU are controlling and sanitizing the origins of the tableName parameter, and your code array, second element via [1] representing the column name. The setting value EQUAL TO and where key EQUALS are ok for parameters.
And if that does not work, I would start with a query that you know is legit/clear just to TEST the functionality with parameters.
"UPDATE YourTable set YourColumn = #Value WHERE Key = #PK"
The Error i get is
An unhandled exception of type 'System.Data.OleDb.OleDbException' occurred in System.Data.dll
Additional information: No value given for one or more required parameters.
but this is when all parameters a present code bellow:
private OleDbDataReader dbReader;// Data Reader object
string sConnection = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=ICTSchool.accdb";
string sql;
OleDbConnection dbConn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0; Data Source=ICTSchool.accdb");
OleDbCommand dbCommand;
public class ComboboxItem
{
public string Text { get; set; }
public object Value { get; set; }
public override string ToString()
{
return Text;
}
}
private void bAdd_Click(object sender, EventArgs e)
{
{
dbConn = new OleDbConnection(sConnection);
dbConn.ConnectionString = sConnection;
dbConn.Open();
string code = (cBQualification.SelectedItem as ComboboxItem).Value.ToString();
string sqlinsert = "INSERT INTO Student VALUES (" + tBStudentNum.Text + "," + tBStudentName.Text+","+ tBCellNo.Text+","+ code + ")";
Console.WriteLine("Test 'sqlinsert' "+ sqlinsert);
dbCommand = new OleDbCommand(sqlinsert, dbConn);
dbCommand.ExecuteNonQuery();
}
}
Here is part of the article about how to insert values in MS Access.
To add one record to a table, you must use the field list to define which fields to put the data in, and then you must supply the data itself in a value list. To define the value list, use the VALUES clause.
For example, the following statement will insert the values "1", "Kelly", and "Jill" into the CustomerID, Last Name, and First Name fields, respectively.
INSERT INTO tblCustomers (CustomerID, [Last Name], [First Name])
VALUES (1, 'Kelly', 'Jill')
You can omit the field list, but only if you supply all the values that record can contain.
INSERT INTO tblCustomers VALUES (1, Kelly, 'Jill', '555-1040',
'someone#microsoft.com')
Source MSDN How to: Insert, Update, and Delete Records From a Table Using Access SQL
The problem I see may be because of malformed SQL Statement. The string values( NVARCHAR, VARCHAR) should be enclosed within single quotes which I believe is not how you're doing now with following statement
string sqlinsert = "INSERT INTO Student VALUES (" + tBStudentNum.Text + "," + tBStudentName.Text+","+ tBCellNo.Text+","+ code + ")";
Try changing the SQL Statement to
string sqlinsert = $"INSERT INTO Student VALUES ({tBStudentNum.Text}, '{tBStudentName.Text}', {tBCellNo.Text}, '{code}')";
I've made an assumption in above case that tBStudentNum.Text and tBCellNo.Text are numeric values. If not, you can make appropriate changes to put the values inside single quote.
If you're using lower version of .net/C#, replace the $ expression with string.format function.
A number of observations:
You haven't specified the parameters in the SQL so we can only assume that there are four fields in the Student table.
You are not using named parameters - this is generally poor practice.
You are using concatenated values and SQL - this will leave you vulnerable to a SQL Injection attack
Any one of the text boxes might include a comma or other SQL formatting characters leading to SQL errors.
I'm trying to use a while loop to insert into a table from a List. I want to loop through and write each item from the list by it's index. I'm getting an error with the values I'm trying to insert.
"SQL logic error or missing database near "[y]": syntax error"
while (y < Name.Count)
{
cmd.CommandText = "INSERT INTO Mytable(Column1,Column2) values(Column1[y], Column2[y])";
cmd.ExecuteNonQuery();
y++;
}
Your query is not correct. You need to pass parameters to the query:
"INSERT INTO Mytable(Column1,Column2) values(Column1[#Column1], Column2[#Column1])"
command.Parameters.Add( new SqlParameter( "#Column1", y ) );
Having said that, if I were you, I would use Bulk Insert (or something similar) for this and transfer all the data to the database in one trip.
Your parameters, Column1[y] and Column2[y], are not handled as a index to a data structure but rather as plain text.
cmd.CommandText = "INSERT INTO Mytable(Column1,Column2) values(" + Column1[y] + ", " + Column2[y] + ")";
I'm attempting to programmatically create a SQL table. I can create a table with a query, this is no issue at all. But I'd like the table name to have some relevance to the data inserted into it, as it's being used for quotations and invoices. Data entered from a DataGridView will be inserted into it (probably via bulkcopy, or something similar).
using (SqlCeCommand command = new SqlCeCommand(
"CREATE TABLE table1' (Weight INT, Name NVARCHAR, Breed NVARCHAR)", con))
works perfectly. However I'd like this code to work:
using (SqlCeConnection con = new SqlCeConnection(#"Data Source=|DataDirectory|\LWADataBase.sdf"))
{
con.Open();
try
{
string tableName = "" + quotenameTxt.Text + "-" +firstTxt.Text+ "-" + surenameTxt.Text;
using (SqlCeCommand command = new SqlCeCommand(
"CREATE TABLE '"+tableName.ToString()+"' (Weight INT, Name NVARCHAR, Breed NVARCHAR)", con))
{
command.ExecuteNonQuery();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Any suggestions? I get an error (as expected) but are unsure what I need to do.
I'm using SqlCe (and before anyone says "BulkCopy isn't supported", I know, I've got a reference that allows it)
The error I get is :
There was an error parsing the query. [ Token line number = 1,Token line offset = 16,Token in error = 1-2-3 ]
// "1-2-3" being the textbox values.
Change the dashes to underscores or surround the entire table name with [square brackets]
As was mentioned in comments above, make the following changes:
using (SqlCeCommand command = new SqlCeCommand(
"CREATE TABLE '"+tableName+"' (Weight INT, Name NVARCHAR, Breed NVARCHAR)", con))
tableName is already a string. No need to use .ToString() on it.
Also, you have a leading white space in your declaration of tableName:
string tableName = "" + quotenameTxt.Text + "-" + firstTxt.Text + "-"
+ surenameTxt.Text;
This makes the string " 1-2-3", not the "1-2-3" you are expecting.
Lastly, surround your tableName with [] to get it to work correctly:
using (SqlCeCommand command = new SqlCeCommand(
"CREATE TABLE '[" + tableName + "]' (Weight INT, Name NVARCHAR, Breed NVARCHAR)", con))
I have inserted a row into my table, and I want to get it's ID and plus it with an int and inserted in that row.
But I don't know how to get it's ID.
Here is the insert code:
objCommand.Connection = objConnection;
objCommand.CommandText = "INSERT INTO Moin " +
" (Title, TotalID, Code ) " +
"VALUES (#Title , #TotalID, #Code )";
objCommand.Connection = objConnection;
objCommand.CommandText = "INSERT INTO Moin " +
" (Title, TotalID, Code ) " +
"VALUES (#Title , #TotalID, #Code ) SELECT SCOPE_IDENTITY()";
object id = objCommand.ExecuteScalar();
Try using the OUTPUT clause of SQL Server in your query - it can return any of the just inserted value (here I'm assuming your column is called ID - adapt as needed):
objCommand.Connection = objConnection;
objCommand.CommandText = "INSERT INTO Moin(Title, TotalID, Code ) " +
"OUTPUT Inserted.ID " +
"VALUES (#Title , #TotalID, #Code ); "
and then execute it like this:
int result = (int)objCommand.ExecuteScalar();
Since you're returning just one row and one column (just the INT), you can use .ExecuteScalar() to retrieve that value back from the INSERT statement.
With the OUTPUT clause, you can return any values just inserted - not just the identity column. So you could also return values that are filled by the database with default values, or whatever you need. If you return multiple values, you need to use a data reader to read them all - ExecuteScalar() only works for a single value.
But, as Anders correctly mentioned - using an ORM like Entity Framework would do all of this automatically for you and you wouldn't have to deal with those raw SQL commands anymore....
Building SQL commands in strings should be considered a legacy technique. If you use Entity Framework or linq-to-sql the retrieval of the id is handled automatically for you.
With pure SQL, use the SCOPE_IDENTITY() function to retrieve the id of the inserted element.