I have been trying to add a column programmatically in ASP.NET to modify the tables in SQL Server.
Please see the following code:
string suppliernotxt = supplieridlist[1].ToString();
//SqlCommand cmd2 = new SqlCommand("ALTER TABLE [ProductNormalDB] ADD suppliernotxt nvarchar(20) NULL", con);
SqlCommand cmd2 = new SqlCommand("ALTER TABLE ProductNormalDB ADD #supplierlist nvarchar(20) NULL", con);
cmd2.Parameters.AddWithValue("#supplierlist", suppliernotxt);
//cmd2.Parameters.AddWithValue("#supplierlist", suppliernotxt.ToString());
//cmd2.Parameters["#supplierlist"].Value = supplieridlist[x];
cmd2.ExecuteNonQuery();
supplieridlist is an array that acquires all the column names to add into the SQL Server database. For some reason the parametrized method is not working and shows the following error:
Incorrect syntax near '#supplierlist'.
The basic idea is to have a user select from a check box the name of the suppliers, based on the selected number of suppliers the array will create the supplier names for ex. if we selected 3 suppliers, the array will save "Supplier1", "Supplier2", "Supplier3" and then the SqlCommand is supposed to alter the table and add the new columns.
You cannot use parameters to express the name of columns.
Parameters could only be used to express values for WHERE clause or for INSERT or UPDATE statements.
You could use string concatenation for your query text, passing the string value to a stored procedure or use some form of dynamic sql.
Please be very carefull with these kind of approaches because if you don't keep absolute control on the values passed to your code you will be exposed to Sql Injection.
Adding as an example of Dynamic SQL execution, but still vulnerable to SQL Injection
string suppliernotxt = supplieridlist[1].ToString();
string execSQL = "DECLARE #sup nvarchar(15); " +
"SET #sup = '" + suppliernotxt + "'; " +
"EXEC ('ALTER TABLE ProductNormalDB ADD ' + #sup + ' nvarchar(20) NULL')"
SqlCommand cmd2 = new SqlCommand(execSQL, con);
cmd2.ExecuteNonQuery();
As you can see, even with Dynamic SQL there is nothing that prevent an SQL Injection attack passing via the suppliernotxt variable
EDIT As explained in the comments below from #RBarryYoung, a good improvement on the SQL Injection problem for this case of dynamic sql could be the usage of the QUOTENAME function to obtain an Unicode string with the required delimiters around the input string
string execSQL = "DECLARE #sup nvarchar(15); " +
"SET #sup = QUOTENAME('" + suppliernotxt + "'); " +
"EXEC ('ALTER TABLE ProductNormalDB ADD ' + #sup + ' nvarchar(20) NULL')"
Related
Currently, I am working on an inventory system that will allow the client to customize their own SQL Server tables.
The user will name their column then specify the data type they would like to use. After they are satisfied with their table they click on the submit table button to create their table. C# then will create a unique table for the user by running a SQL Server stored procedure.
SqlConnection connection = new SqlConnection(Constants.conn);
connection.Open();
string query = "EXEC CreateTable #TableName='"+ UserAccountInfo.Username + "InventoryTable'";
SqlCommand command = new SqlCommand(query, connection);
command.ExecuteReader();
Then using a foreach loop, iterating through each column added (class UserTable is my custom WPF UserControl) by looking at the Stack panel "StackTable" Children, and assigning the properties of the Usertable "Name" and "DataType" to the List of String Arrays. Then I iterate throughout the list and execute the second stored procedure that alters the table previously created.
I believe all of this to work!! My question and problem lies in my stored procedure.
List<string[]> list = new List<string[]>();
foreach (UserTable ut in StackTable.Children)
{
string dataType = "";
switch (ut.DataType.Text)
{
case "Text": dataType = "Varchar(100)"; break;
case "Number": dataType = "INT"; break;
case "Boolean": dataType = "Varchar(5)"; break;
}
string[] vs = {"[" + ut.Name.Text + "]", dataType};
list.Add(vs);
}
foreach (string[] s in list)
{
string query2 = "EXEC SelectAllCustomers #Name = '" + s[0] + "', #DataType = '" + s[1] + "';";
SqlCommand command2 = new SqlCommand(query, connection);
command2.ExecuteReader();
}
My DATABASE Schema consists of the base database called InventoryDatabase, inside a table called LoginInfo where I store the user's information, and the rest of the tables are going to be the tables we are creating above. PROBLEM IS, my stored procedures are throwing syntax errors.
You'll have to use dynamic SQL. Here's an example to get you started:
create or alter procedure CreateTable #TableName varchar(100)
as
begin
declare #sql nvarchar(max) =
concat('create table ',quotename(#TableName),' AccountId int primary key identity(1,1)');
exec (#sql);
end
Note that the name is passed through the quotename function to protect against SQL Injection.
Option 1: prepare the SQL script as a string which can able to Create or alter the table in your C# code and then execute prepared string using ExecuteNonQuery method.
Option 2: by using dynamic SQL concept, prepare the create/alter table script with in a stored procedure and then execute
I am creating tables by c# code from sql server. For that i have created one dynamic table creation function in which i have passed some parameters.One of the parameter is datatable in which i am getting column detail.Everything is working fine but the one minor issue is if there is table in sql with identity(1,1)
i am getting that column's seed value as 0 in c# and hence the data is inserting with id value 0.
For getting table's defintion from database, i am using simple query like
select * from tablename
Tell me if any further details or any extra code needed then i can provide it here.
Ok i have updated my question with how i am filling my datatable.
sqlcmd = new SqlCommand("select * from item.TableName", connSource);
dt = new DataTable();
dt.Load(sqlcmd.ExecuteReader());
Please try below query in C# code and pass tablename to get Seed and Step:
SqlCommand sqlcmd = new SqlCommand("SELECT IDENT_SEED(TABLE_NAME) AS
Seed,IDENT_INCR(TABLE_NAME) AS Increment FROM INFORMATION_SCHEMA.TABLES
WHERE OBJECTPROPERTY(OBJECT_ID(TABLE_NAME), 'TableHasIdentity') = 1 AND
TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = '" + tableName + "'",
srcConStr);
SqlDataReader readercmd = sqlcmd.ExecuteReader();
while (readercmd.Read())
{
sqlsc += " IDENTITY(" + readercmd["Seed"].ToString() + "," +
readercmd["Increment"].ToString() + ") ";
}
readercmd.Close();
I was trying to create a table based on the name given in textbox1 .I am getting error in the following code :
Incorrect syntax near 'Ramesh'.
Here Ramesh was the value in textbox.
string Customername = Textbox1.text
SqlCommand cmd7 = new SqlCommand("CREATE TABLE '" + CustomerName + "' (ItemCode int,Quantity int,PricePerQuantity int,Brand char(50),Discount int , DateTime datetime)",connection
You don't need single quotes for your table name.
SqlCommand cmd7 = new SqlCommand("CREATE TABLE " + CustomerName + " (ItemCode int,Quantity int,PricePerQuantity int,Brand char(50),Discount int , DateTime datetime)",connection);
But weird part, don't use SqlCommand for MySQL. Use MySqlCommand and related class.
Also I would say that use parameterize queries but since you can't parameterize column name, and looks like you get it as an input, use strong validation or use whitelisting before you put it in your query.
You can read: The BobbyTables culture
remove ' from sides of the table name in query.
string Customername = Textbox1.text
SqlCommand cmd7 = new SqlCommand("CREATE TABLE " + CustomerName + " (ItemCode int,Quantity int,PricePerQuantity int,Brand char(50),Discount int , DateTime datetime)",connection
The immediate cause of the error is that you should not put table name into apostrophes. Something like this:
// put IDisposable into using
using (SqlCommand cmd7 = new SqlCommand(
// Keep SQL readable; "$" - C# 6.0 feature
$#"CREATE TABLE {Textbox1.text}(
ItemCode int,
Quantity int,
PricePerQuantity int,
Brand char(50),
Discount int,
DateTime datetime)",
connection)) {
cmd7.ExecuteNonQuery(); // execute and create the table
}
I'm trying to convert the following stored procedure into a query, so that I can use it in SQL Server CE
USE TestResults
GO
CREATE PROCEDURE uspInsertNewTest
(#DeviceSerialNumber nvarchar(50),
#DeviceType nvarchar(50),
#ElapsedTime int)
AS
BEGIN
INSERT INTO [TestResults].[dbo].[Tests]([Date], [Device], [DeviceType], [ExecutionTimeMs])
OUTPUT INSERTED.TestId
VALUES (GETDATE(), #DeviceSerialNumber, #DeviceType, #ElapsedTime)
END
GO
From the above script, all I can understand is that it takes three input parameters
DeviceSerialNumber
DeviceType
ElapsedTime
but it'll update 5 columns in the table Tests including Date and TestId.
Since I can't use stored procedures in SQL Server CE, I've converted the above script into a string query,
string queryString = "INSERT INTO Tests ([Date], [Device], [DeviceType], [ExecutionTimeMs]) VALUES (#Date, #DeviceSerialNumber, #DeviceType, #ElapsedTime)"
Now how to include OUTPUT INSERTED.TestId into the string( queryString ) ?
There's a similar question here, but it doesn't help my problem
Thanks!
You can use ##IDENTITY to return the last inserted identity value:
string queryString = "INSERT INTO Tests " +
"([Date], [Device], [DeviceType], [ExecutionTimeMs]) " +
"VALUES (#Date, #DeviceSerialNumber,#DeviceType, #ElapsedTime); " +
"SELECT ##IDENTITY;"
When you execute your query, you need to set it up to return a single value using the ExecuteScalar method:
var newIdentity;
// set up the queryString variable & command using the above
newIdentity = cmd.ExecuteScalar();
This assumes that the column TestId is an identity column.
Though I accepted Tanner's answer, but I ended up doing like this,
string queryString = "INSERT INTO Tests " + "([Date], [Device], [DeviceType], [ExecutionTimeMs]) " +
"VALUES (#Date, #DeviceSerialNumber,#DeviceType, #ElapsedTime)";
string queryString2 = "SELECT ##IDENTITY";
DbCommand command = factory.CreateCommand ();
command.CommandText = queryString;
// Added Parameters here
command.ExecuteNonQuery ();
command.CommandText = queryString2;
object testId = command.ExecuteScalar ();
So I had to split the query into two string & run ExecuteNonQuery with the first string and run ExecuteScalar with the second string.
I get date from DateEdit and try to Store into Access Database. But it show error like this
Syntax error in INSERT INTO statement.
my insert statement is this
OleDbCommand top = new OleDbCommand("INSERT INTO invoice(invoice_number,order_number,customername,status,subtotal,tax,total,date) VALUES (" + inno + "," + odrno + ",'" + name + "','"+ chk1 +"' ,"+ subtottal +","+ tax +","+total+",'"+date+"')", conn);
top.ExecuteNonQuery();
Except Date remaining values store successfully but how can i store date ??
I get date like this DateTime date = dateEdit1.DateTime;
Help me.
DATE is a reserved keyword for Microsoft Access. You shoud use it with square brackets like [DATE]
And you should always use parameterized queries. This kind of string concatenations are open for SQL Injection attacks.
OleDbCommand top = new OleDbCommand(#"INSERT INTO invoice(invoice_number,order_number,customername,status,subtotal,tax,total,[date])
VALUES (#invoice_number, #order_number, #customername, #status, #subtotal, #tax, #total, #date)", conn);
top.Parameters.AddWithValue("#invoice_number", inno);
top.Parameters.AddWithValue("#order_number", odrno);
top.Parameters.AddWithValue("#customername", name);
top.Parameters.AddWithValue("#status", chk1);
top.Parameters.AddWithValue("#subtotal", subtotal);
top.Parameters.AddWithValue("#tax", text);
top.Parameters.AddWithValue("#total", total);
top.Parameters.AddWithValue("#date", date);
As a general recommendation, don't use reserved keywords for your identifiers and object names in your database.