I have a sql table that saves a word and I need to check if that word already exists and I so, I should get a message saying that word already exists.
Is it possible? If so how should I do it?
I will leave it down below myccode to add the word for the sql, but if you need something else I will provide you without any problem.
string conn = ConfigurationManager.ConnectionStrings["test"].ConnectionString;
using (SqlConnection sqlConn = new SqlConnection(conn))
{
sqlConn.Open();
string sqlQuery = #"INSERT INTO testetiposdestados(CDU_ESTADOS) VALUES(#estados)";
SqlCommand SQLcm = new SqlCommand();
SQLcm.Connection = sqlConn;
SQLcm.CommandText = sqlQuery;
SQLcm.CommandType = CommandType.Text;
SQLcm.Parameters.AddWithValue("#estados", textBox1.Text);
SQLcm.ExecuteNonQuery();
sqlConn.Close();
}
I'm using c#
You can use IF NOT EXIST statment like so
IF NOT EXISTS (SELECT * FROM testetiposdestados
WHERE CDU_ESTADOS = #estados)
BEGIN
INSERT INTO testetiposdestados(CDU_ESTADOS) VALUES(#estados)
END
Your query will become:
string sqlQuery =
#"IF NOT EXISTS(SELECT *
FROM testetiposdestados
WHERE CDU_ESTADOS = #estados)
BEGIN
INSERT INTO testetiposdestados(CDU_ESTADOS)
VALUES (#estados)
END";
If it inserted successfully it means it was not present in the table already.
I would recommend using a unique constraint:
CREATE UNIQUE CONSTRAINT unq_testetiposdestados_estados
UNIQUE (CDU_ESTADOS);
INSERT INTO testetiposdestados(CDU_ESTADOS)
VALUES(#estados);
This has the advantage that the database ensures that the value is unique, not the application. Hence, this will prevent another INSERT or UPDATE statement from producing a unique value.
Furthermore, this is much safer than the IF approach. That approach is subject to race conditions -- two threads attempting to insert the same value may both succeed.
Related
This question already has answers here:
Sanitize table/column name in Dynamic SQL in .NET? (Prevent SQL injection attacks)
(3 answers)
Closed 5 months ago.
Edit: I marked that the linked question was useful, but I didn't intend to mean that it completely answered my question here, which after reviewing others' comments and answers here, I realize I need two different escaped versions of table, one as a safe single-quoted identifier, and one as a safe single-bracketed identifier.
I need to drop a SQL server table from C# with the table name as a parameter.
This is my code:
private static void DropSqlTableIfExists(string connectionString, string table)
{
string query = "if object_id (#table, 'U') is not null begin drop table #table; end";
using SqlConnection conn = new(connectionString);
using SqlCommand command = new(query, conn);
command.Parameters.AddWithValue("#table", table);
conn.Open();
command.ExecuteNonQuery();
}
The above code gives me an error, Incorrect syntax near '#table'.
I could of course put the table name directly into the query string, but that would allow code injection, which I need to avoid.
What is the best way to go about this?
EDIT 2:
Based on feedback, I updated the code to look like this:
private static void DropSqlTableIfExists(string connectionString, string table)
{
string tableSafeQuoted = $"'{table.Replace("'", "''")}'";
string tableSafeBracketed = $"[{table.Replace("]", "]]").Replace(".", "].[")}]";
string query = $"if object_id ({tableSafeQuoted}, 'U') is not null begin drop table {tableSafeBracketed}; end";
using SqlConnection conn = new(connectionString);
using SqlCommand command = new(query, conn);
conn.Open();
command.ExecuteNonQuery();
}
tbh, I'm not sure if it's 100% safe, due to the oddity of the . replacement.. but I think unless someone gives me a good reason not to, I will leave it like this..
You'll need to escape/encode the table name as an identifier. In SQL Server, this is typically done by replacing any closing brackets (]) in the name with two consecutive brackets (]]), and then surrounding the result with brackets ([...]).
You can either write a simple method to do this yourself, or take on a dependency like ScriptDom, which allows you to do this:
var escapedTableName = Identifier.EncodeIdentifier(tableName);
If your SQL Server database is set to use double-quoted identifiers, do something similar, but with double-quotes instead of brackets. Or, with ScriptDom:
var escapedTableName = Identifier.EncodeIdentifier(tableName, QuoteType.DoubleQuote);
Note that encoding the table name makes any .s act as if they're part of the table name itself. If your table name is supposed to have qualifiers (database, schema), each of those must be escaped individually, so you'll probably want to have them passed in as a separate argument, or create a separate type to represent the combination of these names.
There is probably a more elegant way to do this, but here's one possible way:
declare #dynamicsql nvarchar(max)
set #dynamicsql = 'DROP TABLE dbo.' + QUOTENAME(#table) + '';
if object_id (#table, 'U') is not null
begin
EXEC sp_executesql #dynamicsql;
end
so in your specific case it will be:
private static void DropSqlTableIfExists(string connectionString, string table)
{
string query = #"
declare #dynamicsql nvarchar(max)
set #dynamicsql = 'DROP TABLE dbo.' + QUOTENAME(#table) + '';
if object_id (#table, 'U') is not null
begin
EXEC sp_executesql #dynamicsql;
end
";
using SqlConnection conn = new(connectionString);
using SqlCommand command = new(query, conn);
command.Parameters.AddWithValue("#table", table);
conn.Open();
command.ExecuteNonQuery();
}
I hope it helps!
With MySqlCommand I'm tryting to execute a .sql that updates my database.
The large file contains updates, deletes, stored procedures and all. It also uses some variables like:
SET #_count := (
SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'easycertlistfwk_audit'
AND TABLE_NAME = 'AUDIT_TITLE'
AND COLUMN_NAME = 'TI_ORDER');
IF #_count = 0 THEN
ALTER TABLE `AUDIT_TITLE`
ADD COLUMN `TI_ORDER` int(11) NULL AFTER `TI_DESCR`;
The code that I use to execute it withing c# is:
using (MySqlConnection conn = new MySqlConnection(constring))
{
using (MySqlCommand cmd = new MySqlCommand())
{
conn.Open();
cmd.CommandText = File.ReadAllText(dbUpdatesFile);
cmd.ExecuteNonQuery();
conn.Close();
}
}
the cmd.ExecuteNonQuery() method rises an Exception telling me that #_count must be defined. I guess it takes it for one of the parameters that I'm supposed to pass to the command, but in this case, all the code (and hence temporary variable declarations) is within the sql file that I'd like just to execute.
How to do this? Is there a way to ignore params checking and binding?
So I am trying to fetch a value from the database, selecting the row using WHERE INT.
conn = new MySqlConnection(DBdetails.connStr);
conn.Open();
query = "SELECT * FROM tables WHERE table=#tafel";
MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("#tafel", tafel);
cmd.ExecuteNonQuery();
However it wont pass 'cmd.ExecuteNonQuery()', it throws a error saying the syntax isnt right like: "near table=1", "near table=2"
I tried fetching a other one in the same table that is a var char and it worked perfectly.
Don't really see what I am doing wrong. The 'table' column is a int and 'tafel' is a int to.
Thanks!
Put your field name table in backticks (table is a reserved word in MySQL) :
query = "SELECT * FROM `tables` WHERE `table` = #tafel";
As others said, table is a reserved word in MySQL. You need to use quote with it like
query = "SELECT * FROM tables WHERE `table` = #tafel";
However, the best solution is to change the name to a nonreserved word.
Also use using statement to dispose your MySqlConnection and MySqlCommand like;
using(MySqlConnection conn = new MySqlConnection(DBdetails.connStr))
using(MySqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = "SELECT * FROM tables WHERE `table` = #tafel";
cmd.Parameters.AddWithValue("#tafel", tafel);
conn.Open();
cmd.ExecuteNonQuery();
}
By the way, I don't understand why you use ExecuteNonQuery with SELECT statement. It just executes your query. It doesn't even return any value.
If you want to get the result of your query, you can use ExecuteReader method which returns SqlDataReader as your result rows.
Using C# in Visual Studio, I'm inserting a row into a table like this:
INSERT INTO foo (column_name)
VALUES ('bar')
I want to do something like this, but I don't know the correct syntax:
INSERT INTO foo (column_name)
VALUES ('bar')
RETURNING foo_id
This would return the foo_id column from the newly inserted row.
Furthermore, even if I find the correct syntax for this, I have another problem: I have SqlDataReader and SqlDataAdapter at my disposal. As far as I know, the former is for reading data, the second is for manipulating data. When inserting a row with a return statement, I am both manipulating and reading data, so I'm not sure what to use. Maybe there's something entirely different I should use for this?
SCOPE_IDENTITY returns the last identity value inserted into an identity column in the same scope. A scope is a module: a stored procedure, trigger, function, or batch. Therefore, two statements are in the same scope if they are in the same stored procedure, function, or batch.
You can use SqlCommand.ExecuteScalar to execute the insert command and retrieve the new ID in one query.
using (var con = new SqlConnection(ConnectionString)) {
int newID;
var cmd = "INSERT INTO foo (column_name)VALUES (#Value);SELECT CAST(scope_identity() AS int)";
using (var insertCommand = new SqlCommand(cmd, con)) {
insertCommand.Parameters.AddWithValue("#Value", "bar");
con.Open();
newID = (int)insertCommand.ExecuteScalar();
}
}
try this:
INSERT INTO foo (column_name)
OUTPUT INSERTED.column_name,column_name,...
VALUES ('bar')
OUTPUT can return a result set (among other things), see: OUTPUT Clause (Transact-SQL). Also, if you insert multiple values (INSERT SELECT) this method will return one row per inserted row, where other methods will only return info on the last row.
working example:
declare #YourTable table (YourID int identity(1,1), YourCol1 varchar(5))
INSERT INTO #YourTable (YourCol1)
OUTPUT INSERTED.YourID
VALUES ('Bar')
OUTPUT:
YourID
-----------
1
(1 row(s) affected)
I think you can use ##IDENTITY for this, but I think there's some special rules/restrictions around it?
using (var con = new SqlConnection("connection string"))
{
con.Open();
string query = "INSERT INTO table (column) VALUES (#value)";
var command = new SqlCommand(query, con);
command.Parameters.Add("#value", value);
command.ExecuteNonQuery();
command.Parameters.Clear();
command.CommandText = "SELECT ##IDENTITY";
int identity = Convert.ToInt32(command.ExecuteScalar());
}
Using C# in Visual Studio, I'm inserting a row into a table like this:
INSERT INTO foo (column_name)
VALUES ('bar')
I want to do something like this, but I don't know the correct syntax:
INSERT INTO foo (column_name)
VALUES ('bar')
RETURNING foo_id
This would return the foo_id column from the newly inserted row.
Furthermore, even if I find the correct syntax for this, I have another problem: I have SqlDataReader and SqlDataAdapter at my disposal. As far as I know, the former is for reading data, the second is for manipulating data. When inserting a row with a return statement, I am both manipulating and reading data, so I'm not sure what to use. Maybe there's something entirely different I should use for this?
SCOPE_IDENTITY returns the last identity value inserted into an identity column in the same scope. A scope is a module: a stored procedure, trigger, function, or batch. Therefore, two statements are in the same scope if they are in the same stored procedure, function, or batch.
You can use SqlCommand.ExecuteScalar to execute the insert command and retrieve the new ID in one query.
using (var con = new SqlConnection(ConnectionString)) {
int newID;
var cmd = "INSERT INTO foo (column_name)VALUES (#Value);SELECT CAST(scope_identity() AS int)";
using (var insertCommand = new SqlCommand(cmd, con)) {
insertCommand.Parameters.AddWithValue("#Value", "bar");
con.Open();
newID = (int)insertCommand.ExecuteScalar();
}
}
try this:
INSERT INTO foo (column_name)
OUTPUT INSERTED.column_name,column_name,...
VALUES ('bar')
OUTPUT can return a result set (among other things), see: OUTPUT Clause (Transact-SQL). Also, if you insert multiple values (INSERT SELECT) this method will return one row per inserted row, where other methods will only return info on the last row.
working example:
declare #YourTable table (YourID int identity(1,1), YourCol1 varchar(5))
INSERT INTO #YourTable (YourCol1)
OUTPUT INSERTED.YourID
VALUES ('Bar')
OUTPUT:
YourID
-----------
1
(1 row(s) affected)
I think you can use ##IDENTITY for this, but I think there's some special rules/restrictions around it?
using (var con = new SqlConnection("connection string"))
{
con.Open();
string query = "INSERT INTO table (column) VALUES (#value)";
var command = new SqlCommand(query, con);
command.Parameters.Add("#value", value);
command.ExecuteNonQuery();
command.Parameters.Clear();
command.CommandText = "SELECT ##IDENTITY";
int identity = Convert.ToInt32(command.ExecuteScalar());
}