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))
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.
try
{
string Query = "SELECT Registrations list FROM [Records] WHERE textBox = '" + comboBox.SelectedValue + "'";
OleDbConnection me = new OleDbConnection(connection);
OleDbCommand constr = new OleDbCommand(Query, me);
OleDbDataReader reader;
connection.Open();
reader = constr.ExecuteReader();
if (reader.Read())
{
OleDbParameter parameter = constr.Parameters.Add(new OleDbParameter("Registrations list", OleDbType.Integer));
textBox.Text = reader["Registrations list"].ToString();
}
me.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Im trying to get database values to display in textbox but keep getting the error, i've tried mostly everything possible
wrap the column name with square brackets
SELECT [Registrations list] FROM [Records] WHERE textBox
Otherwise sql server looks for a column called Registrations and then tries to alias it as [List]
Enclose the column name in square brackets.
SELECT [Registrations list]
If the column names contais space then you need to enclose the column name in square brackets else SQL Server will consider it as two column names and since comma will also be not present hence it will give you syntax error.
I suppose there is an error in the SQL
string Query = "SELECT Registrations list FROM [Records] WHERE textBox = '" + comboBox.SelectedValue + "'";
Between SELECT and FROM there should be a comma separated list of columns belinging to the table Records. If you want to label the column place the keyword as between the column name and uts label.
If you placed a white space in the column name (never saw, never did, don't even know if it's possible at all), try including the column name between single quotes. Or (much better) rename the column.
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
I found several examples of how to get the last inserted row id from an sql insert call to my SQLite database, but my script threw this error:
SQLiteException
Message = "SQLite error\r\nnear \")\": syntax error"
InnerException
NULL
Below is the SQL text I sent in and how I used it. Obviously, I misunderstood something. Could someone help me out here?
I am trying to return the ID number that was just inserted.
private static int Save(Dates date, SQLiteConnection con) {
// REF: http://www.sqlite.org/c3ref/last_insert_rowid.html
int result = 0;
string sql = "INSERT INTO Dates1 " +
"(ID, TaskID, Last1) " +
"VALUES " +
"((SELECT MAX(ID) FROM Dates1)+1, #TaskID, #Last); " +
"SELECT sqlite3_last_insert_rowid(sqlite3*);";
using (SQLiteCommand cmd = new SQLiteCommand(sql, con)) {
cmd.Parameters.AddWithValue(Dates.AT_TASK, date.TaskID);
cmd.Parameters.AddWithValue(Dates.AT_LAST, date.Last.ToShortDateString());
cmd.CommandText = Dates.SQL_INSERT;
try {
result = cmd.ExecuteNonQuery();
} catch (SQLiteException err) {
result = -1;
LogError("Save(Dates, SQLiteConnection)", err);
}
}
return result;
}
FYI: I have set up the table so that ID is supposed to be auto generated using the Create SQL below, but the table only stores -1 for the ID values unless I manually insert it.
public const string SQL_CREATE = "CREATE TABLE Dates1 " +
"(ID INTEGER PRIMARY KEY AUTOINCREMENT, TaskID INTEGER, Last1 TEXT);";
To quote from the SQLite documentation:
last_insert_rowid() The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. The last_insert_rowid() SQL function is a wrapper around the sqlite3_last_insert_rowid() C/C++ interface function.
So you need to change your statement to:
"SELECT last_insert_rowid();"
because what you did was to try and call the C API function.