I check my SQL database to see if a column exists if not create, but I wanted to insert a string in that column, but only if the column didn´t exist.
Otherwise I handle that information in my C# code.
So far I have this code :
string query = "IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'tabela' AND COLUMN_NAME = 'coluna') ALTER TABLE tabela ADD coluna varchar(50)" ;
SqlCommand command = new SqlCommand(query, con);
command.ExecuteNonQuery();
How should I do ?
Change your query to execute a block after the IF (psuedocode):
IF NOT EXISTS(...)
BEGIN
ALTER TABLE MyTable ...;
INSERT INTO MyTable ...;
END
Be sure to put semicolons at the end of the ALTER and INSERT commands, since you are sending these in a single command from an application, so SQL Server will see them as being all on one line.
You can write a trigger for each SELECT from the database object. In that you can first check if the column exists, and then you can do the needful. This you can achieve entirely by using SQL triggres (or even stored procedures
), C# has nothing to do with it :)
For more details on triggers, you can check this out
Related
I have the following SQL query which I am sending from a C# program:
DECLARE #id as int
SELECT #id = max(fault_catagory_ident) FROM fault_catagory_list
INSERT INTO fault_catagory_list (fault_catagory_ident, fault_catagory)
VALUES (#id + 1, 'TEST')
SELECT #id + 1
The 'fault_catagory' value is coming from my program, but the ident value needs to be the next number in line (primary key) from the existing table in the database. My C# code is parameterising values for security.
I have two problems:
How can I get the #id + 1 value returned to my program (executeNonQuery doesn't return anything)?
How can I get #id as a parametarised value for the insert command?
I am wondering if my primary key could be automated in some way?
I want to carry all this out in one single query, as there will be a risk of multiple logins running this same query. If any happened to run simultainiously, the #id value may get duplicated and one would fail.
Apologies if there isn't enough info here, I'm on a learning curve!
Any advice would be greatly appreciated. Thanks in advance.
I think that you will find everything you need in this example provided in MSDN:
https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand.executescalar?view=dotnet-plat-ext-5.0
in short:
to return a single parameter from a query ull use ExecuteScalar()
parameters are added to a query through the SqlCommand class provided in System.Data.SqlClient.
cheers!
Thanks for the advice, think I have found the solution...
Firstly I need to recreate the table with the primary key column using the IDENTITY constraint (makes sense to use this now I know it exists!). Found a guide here (though it will mean some rebuilding of primary/foreign key links) https://www.datameer.com/blog/how-to-add-an-identity-to-an-existing-column-in-sql/
Then in C# program, use SqlCommand.executeScalar to return the identity value
Int identReturn = 0;
identReturn = (Int32)cmd.ExecuteScalar();
Thanks again for the responses.
While I don't agree with the logic in which you are choosing identity row values for the inserted rows, you could certainly acheive that using IDENTITY() column attribute in the SQL table definition.
In case you have multiple SELECTs in your SQL command,
everytime you have a SELECT in your sql command, a new table is added to the passed in dataset to the data adapter.
string sql = "
DECLARE #id as int
SELECT #id = max(fault_catagory_ident) FROM fault_catagory_list
INSERT INTO fault_catagory_list (fault_catagory_ident, fault_catagory)
VALUES (#id + 1, 'TEST')
SELECT #id + 1";
SqlCommand cmd = new SqlCommand(sql, conn); // assuming you already set connection
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);
Console.WriteLine( ds.Tables[0].Rows[0][0]); // this will print #id
Console.WriteLine( ds.Tables[1].Rows[0][0]); // this will print #id + 1
I have a windows forms application (C#) that reads some data from MySQL database. In a new version I needed to add a new column in one of the tables (to add some functionality). Sometimes I need to make a restore database (from dump file). If I restore the old table from the old database (without the new column) I get "unnknown column" error.
How should I alter my SQL command to select data from this table? If 'newcolumn' exists, I need to select data, if not I need to select NULL.
MySqlDataAdapter da = new MySqlDataAdapter(
"SELECT my_id AS Id,myColumn1 AS Column1,myColumn2 AS Column2,
newcolumn AS NewColumn (here IF NOT EXIST = NULL)", connection);
da.Fill(izpis_podatkov);
Thank you!
If you restore the database but leave the code as it is then there's a mismatch between code and database schema. The simplest option would be to alter the table to add the missing column after you do the restore. Something like:
ALTER TABLE yourtable ADD newcolumn VARCHAR(255)
Obviously, changing the table, column name and data type to the appropriate values for your situation.
EDIT:
You could do something closer to what you actually asked by creating a stored procedure that would check for the existence of the column and add it if it is not there:
CREATE PROCEDURE `MyStoredProc` ()
BEGIN
IF NOT EXISTS (SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = `db_name` AND TABLE_NAME = `newtable` AND COLUMN_NAME = `newcolumn`)
BEGIN
ALTER TABLE 'newtable' ADD 'newcolumn' VARCHAR(255) NULL;
END
SELECT my_id AS Id, myColumn1 AS Column1, myColumn2 AS Column2, newcolumn AS NewColumn FROM newtable;
END
You would then need to change your C# code to call this stored procedure:
command = new MySqlCommand(procName, connection);
da = new MySqlDataAdapter(command);
command.ExecuteNonQuery();
da.Fill(izpis_podatkov);
I don't know MySql that well so please check the syntax of the stored procedure first!
You can't use a SQL Data Manipulation Language query, in MySQL, that mentions a nonexistent column in a table. The query planner in the MySQL server rejects it even if it shows up in a conditional context like IFNULL().
You could use a UNION ALL operation, like so
SELECT myColumn1, myColumn2, newColumn
FROM newTable
UNION ALL
SELECT myColumn1, myColumn2, NULL as newColumn
FROM oldTable
This will give you back the rows of the newTable and the rows of the oldTable as if they were a single table. It basically hides your two tables behind the UNION, pretending they have the same layout, making an alias for the missing column in oldTable.
Then, if you restore the oldTable from backup, you can truncate (remove all rows from) the newTable, if that makes sense in your application.
You can use the query I showed in a CREATE VIEW statement, then your production software will see it as if it were table.
CREATE VIEW table AS
SELECT myColumn1, myColumn2, newColumn
FROM newTable
UNION ALL
SELECT myColumn1, myColumn2, NULL as newColumn
FROM oldTable;
I need to add column to table, for now I have this code:
public void InsertParameter(string ColumnName)
{
string sql = "ALTER TABLE table_name ADD :value1";
SQLiteCommand cmd = new SQLiteCommand(sql,conn);
cmd.Parameters.AddWithValue("value1", ColumnName);
cmd.ExecuteNonQuery();
}
But this give me syntax error:
near ":value1":syntax error
I really can't figure out what is wrong with this query?
The reason it doesn't work is that the syntax for SQLite's ALTER TABLE statement requires a column-name here instead of an arbitrary string-typed expr. This means you can't use a bind-parameter with it.
(Apparently, the implementation of prepared statements requires the table and column names to be known at “compile” time, so it can't be a variable.)
If you need a C# function that dynamically selects a column name at runtime, you need to dynamically create the SQL statement with a hard-coded column name. (Use double-quoting to prevent SQL injection attacks.)
string sql = "Alter Table table_name ADD "\"" + ColumnName.Replace("\"", "\"\"") + "\"";
I want to retrieve the table schema information using C#.
I used the sp_help <table_name> query to retrieve it, which works well when I execute it in query window but fail to retrieve it from C#. I want to retrieve all table information which is necessary for mapping between two tables such as name, datatype, size, isprimary, key, etc.
I had write down following code
SqlCommand cmd = sourceCon.CreateCommand();
cmd.CommandText = string.Format("sp_help '{0}'", cmbSourceTable.SelectedItem.ToString()); //cmd.CommandType = CommandType.StoredProcedure;
sourceDataTable = new DataTable();
SqlDataReader dr = cmd.ExecuteReader();
sourceDataTable.Load(dr);
dr.Close();
It will returns only info about table that when it is created or not
Instead of using sp_help, you could try the following options:
1) use INFORMATION_SCHEMA.COLUMNS view:
SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'YourTable'
2) query sys.columns
SELECT c.*, t.name
FROM sys.columns c
JOIN sys.types t ON c.user_type_id = t.user_type_id
WHERE c.object_id = OBJECT_ID('YourTable')
These are just 2 options that will return a single resultset. INFORMATION_SCHEMA.COLUMNS doesn't tell you (e.g.) if a column is an IDENTITY column, wherease the sys.columns route does. There's more information you can get from the catalog views, just depends what else you need. Here's the MSDN reference.
You might find it easier to play with the INFORMATION_SCHEMA views - you can build queries that will extract most of the data relating to the structure of and relationship between tables within a SQL Server database schema.
See here: http://msdn.microsoft.com/en-us/library/ms186778.aspx
I got a simple way to get schema of a table.
Just create a connection with any provider like SqlConnection object.
Create a command object for select query (select only top 1 record as you want only schema of table)
Execute that query which return a DataReader object.
Every DataReader object have a method called GetTableSchema() which returns DataTable object which have schema of a perticulat table.
This way you can easily get schema of any table with less effort.
Here I will provide a simple code for this
SqlConnection con=new SqlConnection("connString");
con.Open();
SqlCommand cmd= new SqlCommand("select top 0 * from Person.Address",con);
DataTable table = cmd.ExecuteReader().GetTableSchema();
Now this table object have schema information of Person.Address table.
I think sp_help returns multiple result sets so you'll need to use NextResult, there are more details here - http://support.microsoft.com/kb/311274 (the example is not sp_help specific but it should give you the general idea)
Also, you can use the GetSchema method from SqlConnection. http://msdn.microsoft.com/en-us/library/ms136367.aspx
like so:
var tableSchema = con.GetSchema(SqlClientMetaDataCollectionNames.Tables, new string[] { null, null, "[tableName]" });
The string array is a 'filter', here you can find the columns you can filter on: http://msdn.microsoft.com/en-us/library/ms254969.aspx
For other database servers and more info:
http://msdn.microsoft.com/en-us/library/kcax58fh.aspx
sp_help doesn't work in your code? maybe you need to include an execute statement: exec sp_help. or maybe the application is running under an account that doesn't have permission for sp_help.
Since .net 2.0 the SqlConnection class offers GetSchemaMethod you can use to retrieve the requested info.
http://msdn.microsoft.com/en-us/library/ms136364(v=vs.80).aspx
See this one ... it explains how
How To Retrieve Schema Information by Using GetOleDbSchemaTable and Visual C# .NET
I have records in table1, if the records exist, it must copy into table2. I want to delete those records in a table1 once all the records are copied into another table2. Im still a beginner in database and with some researches, i found some tutorials on d internet how to connect with database, and the codes easy to understand so i came out with this program.This codes only do the copy part and i'm still lack of the delete part. Can help me figure out how to do the delete part? i found 2 reference in msdn, but i'm not sure and not understand on the codes given.
try
{
//create connection
System.Data.SqlClient.SqlConnection sqlConnection1 =
new System.Data.SqlClient.SqlConnection("Data Source=.dbname;Integrated Security=True;User Instance=True");
//command queries
System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand();
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = "INSERT INTO tblSend (ip, msg, date) SELECT ip, msg, date FROM tblOutbox";
cmd.Connection = sqlConnection1;
sqlConnection1.Open(); //open con
cmd.ExecuteNonQuery(); //execute query
sqlConnection1.Close(); //close con
}
catch (System.Exception excep)
{
MessageBox.Show(excep.Message);
}
If i replace the query into this: //cmd.CommandText = "DELETE tblSend WHERE id = 5";
its only delete one rows. But what if many records involved? Do i need to consider the EOF things? DO i need to use DataGridView? Becoz the code i did didn't use DataGridView at all. i dont want the records to be displayed, i just want it to running behind.
No you do not need a worry about EOF or using a DataGridView. Just as you can use an ExecuteNonQuery method to insert multiple rows you can also do the same when using DELETE.
Data manipulation statements such as INSERT, UPDATE and DELETE do not generate a result set and hence you would normally use ExecuteNonQuery to run them. All the data manipulation runs in the database server engine.
If I understand correctly you need all data from table1 in table2 and then delete table1.
Options
1) It you need it once you could rename table1 to table2 and recreate table1
-- move the records to table 2, ok I assume it does not exist;)
RENAME TABLE table1 TO table2;
-- Create new table1 with same structure as table 2
CREATE TABLE table1 AS SELECT * FROM table2 WHERE 1=2;
2) Do a separate copy and delete assuming you have something like a primary key
-- copy the records
INSERT table2(field1, field2, ...) SELECT field1, field2, ... FROM table1;
-- and delete them
DELETE FROM table1;
3) Do it using C# but as this seems a database problem to me I would not go that far in pulling all the records to the client and then throwing them back.
DELETE FROM tblSend WHERE id = 5;
This will delete all rows that match the WHERE condition.
I am not sure I understand the relevance of the DataGridView. If it is databound, it will automatically remove the records as well. You only need to issue the delete query once and the rest should happen automatically, assuming you have the databinding correct.
What do you mean by "if they exist"? Compared to what?
To delete multiple records from table 1, you have to make a loop which goes through your table and compare.
Pseudo code:
forach (whatever as whut)
row = select whatever from table1.
if (whut == row)
copy row from table 1 to table 2;
Delete from table 1 where whut.id == row.id;
DELETE FROM tblSend WHERE id = 5;
This is the one solution for deletion a record.
If you want to set the identity key to 0 again, use this code
DBCC CHECKIDENT('tblSend', RESEED, 0);
Then press F5,