I am trying to create a database and table in mySQL using C#. So far I can create a Schema in mysql through c#, but having trouble with creating table in that created schema.
User will enter the name of the schema to be created and then will enter the table name which will be created under the schema name entered before. Schema name and table names are taken in textbox values.
I am getting an error in table query the error is about syntax.
myQuery1.AppendFormat("CREATE SCHEMA {0}", databasenametxt.Text);
myQuery2.AppendFormat("CREATE TABLE {0} (name VARCHAR(20)) WHERE
database={0}",tblenametxt.Text,databasenametxt.Text);
string s1 = myQuery1.ToString();
string s2 = myQuery2.ToString();
MySqlCommand cmd = new MySqlCommand(s1, coat);
MySqlCommand cmd1 = new MySqlCommand(s2, coat);
cmd.ExecuteNonQuery();
cmd1.ExecuteNonQuery();
myQuery1 is executed successfully and a schema is created with the name entered in databasenametxt.Text but in myquery2 I am getting error.
The way I understand it is that you want to dynamically create a schema and tables in it. I am not sure of the error you get, but try using the following query:
CREATE TABLE schema_name.table_name ( column_name1 data_type, column_name2 data_type, column_name3 data_type, .... )
For replacing the schema_name and table_name, it should work like following:
myQuery2.AppendFormat("CREATE TABLE {schema_name}.{table_name} ( {column_name1} {data_type}, .... ), your_schema_name, your_table_name, column_name1, data_type1);
You can also just add strings:
myQuery2.AppendFormat("CREATE TABLE " + your_schema_name + "." + your_table_name + " ( " + column_name1 + " " + data_type1 + ")");
It is just that you are creating a query string, which would run on sql server.
Also, you can get all the msql syntax for creating a table at https://dev.mysql.com/doc/refman/8.0/en/create-table.html
Let me know if it helps!
As pointed out in comment the error "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE database=databasename' at line 1'"
is because "where database = .." is not valid syntax.
As schema is just a synonym for database in mysql you want
create database {0}
use {0}
create table {0} (`name` VARCHAR(20))
in each of your strings. Why the change to name? its a reserved word.
Related
My Question is how can i create a table with a table name what the user typed in? So i have already that:
string createtable = "CREATE TABLE '" + email.Text + "' (benutzung VARCHAR (20), passwort VARCHAR (30), id INTEGER);"; but everytime i start the program and try it again this error pops up:
MySql.Data.MySqlClient.MySqlException: "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''test' (benutzung VARCHAR (20), passwort VARCHAR (30), id INTEGER)' at line 1"
I found the Solution from myself, what you must do is easily make it like that:
string createtable = "CREATE TABLE " + email.Text + " (benutzung VARCHAR (20),
passwort VARCHAR (30), id INTEGER);";
Now all works :D
I am facing a problem , I have a query in SQL Server 2014, The query result should be based on a WHERE clause that takes a string from a C# CheckedListBox.
I have the string in this form (the following values are for example only) :-
cat,dog,bird,duck
And inside the database the records look like this:-
dog cat-dog cat-dog-duck bird-dog-duck etc...
I have tried this :-
DECLARE #animals nvarchar(max) = 'dog,bird,cat'
select x,y,z WHERE CHARINDEX(animals, replace(#animals,',',' ')) > 0
The result would show rows with only ONE SINGLE VALUE like dog cat bird But it wouldn't show rows with values like dog-cat dog-cat-bird etc! it just shows rows with one single word from #animals string.
How can I select all rows where column animals contains either a word or more from #animals string.
Thanks in advance...
You should create a temp table for store all searching value or you should create a temp table from the comma separated variable for the example visit Query for convert CSV values into temp table. Then use inner join for filter records from your table like below.
declare #temp table (animal varchar(50))
insert into #temp values ('cat')
insert into #temp values ('dog')
insert into #temp values ('bird')
select * from SomeTable a
inner join #temp t on a.Column like '%' + t.animal + '%'
Make stored procedure for that query and call it from C#.
And inside the database the records look like this:-
dog cat-dog cat-dog-duck bird-dog-duck etc...
There is the source of your problems. Before reading anything else I wrote in my answer, you should read Is storing a delimited list in a database column really that bad?, where you will see a lot of reasons why the answer to this question is Absolutely yes!.
Once you're done with that, the solution to the problem should be as obvious to you as it is to me - Fix the database structure - meaning remove that column storing delimited data and replace it with a table referenced by a many-to-many relationship to your existing table, that will hold the animals data for you.
The first part of the solution is using a table valued parameter instead of sending a delimited string to the database.
There are plenty of examples on how to do this on stackoverflow - like here and there.
Once you've done that, you can use a hack with like as a workaround, in case you can't change the database structure:
SELECT <ColumnsList>
FROM <TableName> As T
JOIN #TVP As TVP
ON '-' + T.Animals +'-' LIKE '%-' + TPV.Animal +'-%'
Note I've added the delimiter to both ends of both columns.
If you can change the structure you will have a query like this:
SELECT <ColumnsList>
FROM <TableName> As T
JOIN TableToAnimals AS TTA
ON T.Id = TTA.TableId
JOIN Aniamls AS A
ON TTA.AnimalId = A.Id
JOIN #TVP As TVP
ON A.Name = TVP.Animal
You should take a look at Table valued parameters, it will let you send in a table of values as a parameter from C# to SQL. You make a table with "animals" and then make a sub-select in your Stored Proc.
See example code from link below, shows how to pass the parameter:
// Assumes connection is an open SqlConnection object.
using (connection)
{
// Create a DataTable with the modified rows.
DataTable addedCategories = CategoriesDataTable.GetChanges(DataRowState.Added);
// Configure the SqlCommand and SqlParameter.
SqlCommand insertCommand = new SqlCommand("usp_InsertCategories", connection);
insertCommand.CommandType = CommandType.StoredProcedure;
SqlParameter tvpParam = insertCommand.Parameters.AddWithValue("#tvpNewCategories", addedCategories);
tvpParam.SqlDbType = SqlDbType.Structured;
// Execute the command.
insertCommand.ExecuteNonQuery();
}
https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/sql/table-valued-parameters
For anyone who has the same problem. I have found the solution for this on SQL Server. Use the Full Text Search and your problem is easily solved. It's awesome.
Check the following link :-
https://learn.microsoft.com/en-us/sql/relational-databases/search/get-started-with-full-text-search?view=sql-server-2017
use like this:
var query = string.Empty;
var index=0;
foreach(var animal in animals) {
if (query.Length>0) {
query +=" and ";
}
var paramName = "#animalName" + index++;
query +="(animals like " + paramName + " or animals like '%' + " + paramName + " or animals like " + paramName + " + '%' or animals like '%' + " + paramName + " + '%')";
SqlParameter thisParam = new SqlParameter(paramName, animal);
command.Parameters.Add(thisParam);
}
command.CommandText = "select * from tableName WHERE " + query;
I want to create a table name in SQLite based on the user inputted textbox value or a declared string value. For example:
cmd.CommandText = #"CREATE TABLE '"+Machine_Name.Text+"' AS (Date, Cal_Date) VALUES (#Date, #CalDate)";
I'm receiving a newline in constant error right before the AS. I know this may be bad database design but it would be helpful for me to do it this way.
Your query syntax seems to be mixed up.
If you want to create table, you have to provide the column spec (names and datatypes), or if you use create table as, a valid select query has to be used to define the column names/types.
The last part of your statement with the values clause is a valid form for an INSERT, but not for a create table.
See the Documentation here for details.
The syntax to create a table is the following
cmd.CommandText = #"CREATE TABLE '" + newTable + "'" +
"(DATE DATETIME, CAL_DATE VARCHAR(256))";
This of course assumes that your fields are a DateTime and a VarChar.
In other words, after the tablename you put, between parenthesys, the name of the columns and their datatype.
I suggest also to pay particular attention to the value your user types for the name of the new table. This liberty to type anything could be very dangerous and it is the basic building block when a malicious user tries to create an Sql Injection attack.
string ct = "Create table '" + Textbox1.Text +"'(Column1, Column2)";
SQLiteCommand createCommand1 = new SQLiteCommand(ct, sqliteCon);
createCommand1.ExecuteNonQuery();
sqliteCon.Close();
MessageBox.Show("Data Saved");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
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')"
I'm trying to use C# & MySql in order to copy an empty table (recreate the Schema really). The structure looks like this:
> TableTemplate (schema)
+ Tables
> FirstTable (table)
> second table (table)
> ...
> SomeOtherTable
+ Tables
> ...
What I would like is to copy the TableTemplate into a new Schema with the user name.
The first obvious path to oblivion was trying CREATE TABLE #UserName LIKE TableTemplate, swiftly learning that sql parameters are supposed to be used for values and not table names (all hail jon skeet, again: How to pass a table as parameter to MySqlCommand?).
So that leaves us with manual validation of the user names in order to build the table names (robert's a prime example).
Next, it seems that even CREATE TABLE UserID LIKE TableTemplate; won't work (even from MySQL Workbench), since TableTemplate isn't a table.
So It's down to writing a loop that will create a table LIKE each table in TableTemplate, after creating a UserID Schema (after manual validation of that string), or trying other options like dumping the database and creating a new one, as seen in these questions:
C# and mysqldump
Slow performance using mysqldump from C#
But I would prefer avoid running a process, dumping the database, and creating it from there every time I add a user.
Any suggestions would be highly appreciated.
I think mysqldump would be better. but if you want to do in one process. try this.
SELECT
CONCAT ("CREATE TABLE SomeOtherTable.",
TABLE_NAME ," AS SELECT * FROM TableTemplate.", TABLE_NAME
) as creation_sql
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'TableTemplate';
the output will be like
CREATE TABLE SomeOtherTable.tbl_name AS SELECT * FROM TableTemplate.tbl_name;
then iterate result and execute CREATE TABLE ....
Ended up using something like this, in a method where aName is passed for the table name:
using (MySqlCommand cmd = new MySqlCommand(string.Format("CREATE DATABASE {0} ;", aName), connection))
{
cmd.ExecuteNonQuery(); // Create the database with the given user name
// Building the sql query that will return a "create table" per table in some_db template DB.
cmd.CommandText = (string.Format("SELECT CONCAT (\"CREATE TABLE {0}.\", TABLE_NAME ,\" "
+ "LIKE some_other_db.\", TABLE_NAME ) as creation_sql "
+ "FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'some_db';"
, aName));
try // Building the inner tables "create table" sql strings
{
using (MySqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
createInnerTablesList.Add(reader.GetString(0));
}
}
catch (MySqlException mysql_ex) { ... } // handle errors
foreach (var sql_insert_query in createInnerTablesList)
{
try // Insert the tables into the user database
{
cmd.CommandText = sql_insert_query;
cmd.ExecuteNonQuery();
}
catch (Exception e) { ... } // handle errors
}
}
The reasons for using LIKE vs AS like Jungsu suggested is that even though the AS will create the tables, it will not keep any of the constraints and keys defined (primary key, etc).
Using the LIKE will replicate them with the constraints.
I'm still not too happy about this, since I feel I'm missing something though ...