How to declare sql variable in C# - c#

My requirement is to remove all record but one from a table. For this I am executing a series of two different sql commands. Seems like on ssms it works fine but with C# is not
--This is what I run on ssms without any issue
DECLARE #int INT;
SELECT #int = COUNT(*)
FROM [Table]
WHERE STATE = 'CO';
--Delete statement
DELETE TOP (#int - 1 )
FROM [Table] ;
public static void ClearData(string state)
{
const string queryToExec = #"DECLARE #int INT;" +
"SELECT #int = COUNT(*) " +
"FROM [Table] " +
"WHERE STATE = #State;" +
"DELETE TOP (#int - 1 ) " + //NOTICE THIS LINE
"FROM [Table] ";
List<SqlParameter> param = new List<SqlParameter>()
{
new SqlParameter {ParameterName = "#State", SqlDbType = SqlDbType.VarChar, Value = state},
};
ExecQuery(queryToExec, param);
}
public static void ExecQuery(string query, List<SqlParameter> paramCollection = null)
{
using (SqlConnection conn = new SqlConnection(ConnString))
{
using (SqlCommand mySqlCom = new SqlCommand())
{
mySqlCom.CommandText = query;
if (paramCollection != null) mySqlCom.Parameters.AddRange(paramCollection.ToArray());
mySqlCom.Connection = conn;
conn.Open();
mySqlCom.ExecuteNonQuery();
}
}
}
My qsns
How can I declare a sql variable correctly in C# (see ClearData method)
And, how to execute multiple queries in a single query string?(if I am doing this right)
EDIT
I came up with this to accomplish this. But still now luck. Please advise me to what to do:
IF OBJECT_ID ( 'uspWageDataByState', 'P' ) IS NOT NULL
DROP PROCEDURE uspWageDataByState;
GO
CREATE PROCEDURE uspWageDataByState
#State NVARCHAR(2)
AS
DECLARE #int INT
SET #int = (SELECT COUNT(*)
FROM [Test]
WHERE [STATE] = #State)
DELETE TOP (#int - 1 )
FROM [Test]
WHERE [STATE] = #State;
GO
exec uspWageDataByState 'CO'

I have run exactly this code in my environment and it is working as expected.
My framework version is 4.5.51641 and my SQL Version is SQL Server 11.0.2100
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlClient;
using System.Data;
namespace PruebasSQL
{
class Program
{
const string ConnString = #"";
static void Main(string[] args)
{
ClearData("A");
}
public static void ClearData(string state)
{
const string queryToExec = #"DECLARE #int INT;" +
"SELECT #int = COUNT(*) " +
"FROM [Table] " +
"WHERE STATE = #State;" +
"DELETE TOP (#int - 1 ) " + //NOTICE THIS LINE
"FROM [Table] ";
List<SqlParameter> param = new List<SqlParameter>()
{
new SqlParameter {ParameterName = "#State", SqlDbType = SqlDbType.VarChar, Value = state},
};
ExecQuery(queryToExec, param);
}
public static void ExecQuery(string query, List<SqlParameter> paramCollection = null)
{
using (SqlConnection conn = new SqlConnection(ConnString))
{
using (SqlCommand mySqlCom = new SqlCommand())
{
mySqlCom.CommandText = query;
if (paramCollection != null) mySqlCom.Parameters.AddRange(paramCollection.ToArray());
mySqlCom.Connection = conn;
conn.Open();
mySqlCom.ExecuteNonQuery();
}
}
}
}
}

Try changing your query (queryToExec) to:
ALTER PROCEDURE uspWageDataByState
#State NVARCHAR(2)
AS
DELETE TOP
(CASE
(SELECT COUNT(*) FROM [Test] WHERE [STATE] = #State)
WHEN 0 THEN 1
ELSE (SELECT COUNT(*) FROM [Test] WHERE [STATE] = #State) END -1)
FROM [Test]
WHERE [STATE] = #State;
If the declared variable is the problem you can troubleshoot with this. It's not the best query, but your form wasn't either :P
I'm adding a 0 rows validation. In the previous implementation the stored procedure crashed when no data was found.

execute multiple queries in a single string statement :
string querystring = "select [yourcolumns] from [yourtable];select [yourvalues] from [yourtables]";
sqlcommand cmd = new sqlcommand(querystring,yourconnection);
sqlDataReader reader = cmd.executeReader();
do
{
while(reader.Read())
{
//get your values here
}
}while(reader.NextResult());

DECLARE #PageSize INT = 5, #PageNum INT = 1
SELECT tickets.ID, tickets.userID FROM tickets WHERE tickets.isActive = 1
OFFSET (#PageNum-1)*#PageSize ROWS FETCH NEXT #PageSize ROWS ONLY
in that way works in aspnet sqlcommand and datareader

Related

Pass a list as a parameter to an oracle query

This code works for a query parameter that is a single value:
public void GetById(long id)
{
var sql = "SELECT * FROM table1 WHERE id = :id";
using(var cmd = new OracleCommand(sql, oracleConnection)) {
cmd.Parameters.Add(new OracleParameter("id", id));
...
}
}
What's the equivalent for an array or list of values?
public void GetByIds(long[] ids)
{
var sql = "SELECT * FROM table1 WHERE id IN (:ids)";
using(var cmd = new OracleCommand(sql, oracleConnection)) {
cmd.Parameters.Add(new OracleParameter("ids", /* ??? */));
...
}
}
In case it's not clear, I'm looking for something that will work like this:
sql = "SELECT * FROM table1 WHERE id IN (" + string.Join(',', ids) + ")";
but as a clean parameterized query.
You coud send the list of parameters as string and use a regular expresion to separate the id's. Example:
select regexp_substr('SMITH,ALLEN,WARD,JONES','[^,]+', 1, level) from dual
So
sql = "SELECT * FROM table1 WHERE id IN (
select regexp_substr(:ids,'[^,]+', 1, level) from dual
)";
How to split comma separated string and pass to IN clause of select statement

How to properly return count(*) values from scalar valued function

Every time I execute my code I get "false" from method
public bool exists(int vpisna, string geslo)
{
bool a = false;
Uspeh = true;
cmd = new SqlCommand("SELECT dbo.fnExists(#Vpisna,#Geslo)", povezava);
cmd.Parameters.AddWithValue("#Vpisna", vpisna);
cmd.Parameters.AddWithValue("#Geslo", geslo);
try
{
povezava.Open();
int result =(int)cmd.ExecuteScalar();
if (result==1)
{
a = true;
}
}
catch (Exception e)
{
ex = e;
}
finally
{
povezava.Close();
}
return a;
}
My scalar valued function:
[dbo].[fnExists](
#Vpisna int,
#Geslo nvarchar(40)
)
RETURNS INT AS BEGIN
DECLARE #a int
SET #a = (
SELECT
COUNT(*)
FROM
Student
WHERE
ID = #Vpisna
AND
Geslo = CONVERT( nvarchar(40), HashBytes('SHA1', #Geslo ), 2 )
)
RETURN #a
END
Everytime I get a false result, even when I try to manipulate data inside of the scalar valued function. When I try the SELECT statement on real data without a the function it works inside the SQL Management Studio.
I think your code series is wrong. Before create sql command must open sql connection or must open from sqlcommand.
Use this;
SqlConnection cnn = new SqlConnection("sql-connection-string");
cnn.Open();
SqlCommand cmd = new SqlCommand("select 1", cnn);
or
SqlConnection cnn = new SqlConnection("sql-connection-string");
SqlCommand cmd = new SqlCommand("select 1", cnn);
cmd.Connection.Open();
[dbo].[fnExists](
#Vpisna int,
#Geslo nvarchar(40)
)
RETURNS INT AS BEGIN
DECLARE #a int
SELECT
#a = COUNT(*)
FROM
Student
WHERE
ID = #Vpisna
AND
Geslo = CONVERT( nvarchar(40), HashBytes('SHA1', #Geslo ), 2 )
RETURN #a
END

How to get the value of selected row from PostgreSQL in C#?

I am using PostgreSQL database with C# and the Npgsql library.
Right now I can select the last row in my table, but I can not figure out how to assign a C# variable to it. I know that my selection works, because I have successfully edited my last entry before.
You can find my code below. Note that I have not pasted the rest of the methods as I think they are irrelevant.
public void myMethod()
{
this.OpenConn(); //opens the connection
string sql = "SELECT id FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'customers' ORDER BY id DESC, LIMIT 1";
using (NpgsqlCommand command = new NpgsqlCommand(sql, conn))
{
int id = 0; //instead of '0' I want it to be equal to the ID value from the row
//something like "int id = sqlSelection.id;" -- this obviously doesn't work
this.CloseConn(); //close the current connection
}
}
You could achieve this goal by using the specific DataReader:
public void myMethod()
{
this.OpenConn(); //opens the connection
string sql = "SELECT id FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'customers' ORDER BY id DESC, LIMIT 1";
using (NpgsqlCommand command = new NpgsqlCommand(sql, conn))
{
int val;
NpgsqlDataReader reader = command.ExecuteReader();
while(reader.Read()){
val = Int32.Parse(reader[0].ToString());
//do whatever you like
}
this.CloseConn(); //close the current connection
}
}
Useful notes
In some contexts ExecuteScalar is a good alternative
Npgsql documentation
Use can use following code variation too;
using (var command = new NpgsqlCommand(sql, conn))
{
int id = 0;
var reader = command.ExecuteReader();
while(reader.Read())
{
var id = Int32.Parse(reader["id"].ToString());
}
this.CloseConn();
}
You can use ExecuteScalarSync method.
public void myMethod()
{
this.OpenConn(); //opens the connection
string sql = "SELECT id FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'customers' ORDER BY id DESC, LIMIT 1";
using (NpgsqlCommand command = new NpgsqlCommand(sql, conn))
{
int id= (int)DBHelperRepository.ExecuteScalarSync(sqlString, CommandType.Text);
this.CloseConn(); //close the current connection
}
}

how to check if stored procedure exists or not in sql server using c# code

I tried below code for cheking SP is alredy exist or not. if not exist i am creating..
But every time it is showing sp is not created.....But my database already have this sp.
Let me know where i am doing mistake.
string checkSP = String.Format(
"IF OBJECT_ID('{0}', 'U') IS NOT NULL SELECT 'true' ELSE SELECT 'false'",
"GP_SOP_AdjustTax");
SqlCommand command = new SqlCommand(checkSP, myConnection);
command.CommandType = CommandType.Text;
if (myConnection == null || myConnection.State == ConnectionState.Closed)
{
try
{
myConnection.Open();
}
catch (Exception a)
{
MessageBox.Show("Error " + a.Message);
}
}
bool Exist = false;
Exist = Convert.ToBoolean(command.ExecuteScalar());
if (Exist == false) //false : SP does not exist
{
// here i am writing code for creating SP
}
Try:
if exists(select * from sys.objects where type = 'p' and name = '<procedure name>' )
Also you can check that with c#:
string connString = "";
string query = "select * from sysobjects where type='P' and name='MyStoredProcedureName'";
bool spExists = false;
using (SqlConnection conn = new SqlConnection(connString))
{
conn.Open();
using (SqlCommand command = new SqlCommand(query, conn))
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
spExists = true;
break;
}
}
}
}
For those who use Entity Framework and a DbContext:
create an extension class for DbContext:
internal static class DbContextExtensions
{
public static bool StoredProcedureExists(this DbContext context,
string procedureName)
{
string query = String.Format(
#"select top 1 from sys.procedures " +
"where [type_desc] = '{0}'", procedureName);
return dbContext.Database.SqlQuery<string>(query).Any();
}
}
As robIII remarked, this code should not be published to the outside world as it makes the database vulnerable for hackers (thank you RobIII!). To prevent this use a parameterized statement. The problem with the above mentioned method is described here
The solution is to put procedureName as a parameter in an SQL statement. SQL will check if the string parameter has the desired format, thus inhibiting malicious calls:
public static bool ImprovedExists(this DbContext dbContext, string procedureName)
{
object[] functionParameters = new object[]
{
new SqlParameter(#"procedurename", procedureName),
};
const string query = #"select [name] from sys.procedures where name= #procedurename";
return dbContext.Database.SqlQuery<string>(query, functionParameters).Any();
}
I found this on MSDN
select * from sys.objects where type_desc = 'SQL_STORED_PROCEDURE' AND name = 'Sql_PersonInsert'
Try:
SELECT *
FROM sys.objects
WHERE object_id = OBJECT_ID(N'GP_SOP_AdjustTax') AND type in (N'P', N'PC')
My stab at it:
Reusable extension method
Minimal Sql / Minimal C#
Called from .Net as the OP implicitly requested
Could be faster because of the object_id function
public static bool StoredProcedureExists(this string source)
{
using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
{
conn.Open();
using (var cmd = new SqlCommand($"select object_id('{source}')", conn))
return !cmd.ExecuteScalar().ToString().IsNullOrWhiteSpace();
}
}
You can check with following tsql query (suitable for SQL Server):
select * from sysobjects where ytype='P' and name='MyStoredProcedureName'
If query returns row then stored procedure named 'MyStoredProcedureName' exists.
And here is how you can use it in code:
//TODO: set connection string
string connString = "";
string query = "select * from sysobjects where ytype='P' and name='MyStoredProcedureName'";
bool spExists = false;
using (SqlConnection conn = new SqlConnection(connString))
{
conn.Open();
using (SqlCommand command = new SqlCommand(query,conn))
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
spExists = true;
break;
}
}
}
}
string checkSP = String.Format(
"IF OBJECT_ID('{0}', 'U') IS NOT NULL SELECT 'true' ELSE SELECT 'false'",
"GP_SOP_AdjustTax");
is fine if you change the 'U' to 'P'.
With 'U' you query for user-tables, where 'P' gives you stored-procedures.
private static bool StoredProcedureExists(string sp)
{
var connString = #"<your string here>";
var query = string.Format("SELECT COUNT(0) FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME = '{0}'", sp);
using (var conn = new SqlConnection(connString))
{
conn.Open();
using (var cmd = new SqlCommand(query, conn))
{
return Convert.ToInt32(cmd.ExecuteScalar()) > 0;
}
}
}
Handles procedure names with different schemas
Names with and without brackets ([])
Uses parameter to avoid SQL injection
Note: Caller owns SQL Connection
public static class SqlConnectionExtensions
{
public static Task<bool> StoredProcedureExistsAsync(this SqlConnection sqlConnection, string storedProcedureName)
{
string query = "SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(#storedProcedureName) AND type in (N'P', N'PC')";
using (SqlCommand command = new SqlCommand(query, sqlConnection))
{
command.Parameters.AddWithValue("#storedProcedureName", storedProcedureName);
using (SqlDataReader reader = command.ExecuteReader())
{
return reader.ReadAsync();
}
}
}
}
The following works with MySQL, SQL Server, and Oracle I think:
SELECT * FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_TYPE='PROCEDURE'
AND (ROUTINE_SCHEMA='questionnaire' OR ROUTINE_CATALOG = 'questionnaire')
AND SPECIFIC_NAME='create_question';
Usage:
string procedureName = "create_question";
using (DbConnection conn = new SqlConnection("Server=localhost;Database=questionnaire;Trusted_Connection=True;")) // Connection is interchangeable
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = $"SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_TYPE='PROCEDURE' AND (ROUTINE_SCHEMA='{conn.Database}' OR ROUTINE_CATALOG = '{conn.Database}') AND SPECIFIC_NAME='{procedureName}';";
return cmd.ExecuteScalar() != null;
}
}
If you use Microsoft.SqlServer.Management.Smo, try
private static bool CheckIfStoredProcedureExists(Database db, string spName, string schema)
{
db.StoredProcedures.Refresh();
return (db.StoredProcedures[spName, schema] != null);
}
Try this;
if object_id('YourStoredProcedureName') is null
exec ('create procedure dbo.YourSp as select 1')
go
alter procedure dbo.YourStoredProcedure
as

Making a Webservice (asp.NET) which accepts several Paramters seperated by comma

I have the following Webservice and SQL-Query:
public class DIENSTLEISTUNG
{
public string DienstleistungName { get; set; }
public string DienstleistungArtBezeichnung { get; set; }
}
internal static List<DIENSTLEISTUNG> Dienstleistung(string RAUM_ID)
{
List<DIENSTLEISTUNG> BestuhlungObject = new List<DIENSTLEISTUNG>();
using (SqlConnection con = new SqlConnection(#"Data Source=Localhost\SQLEXPRESS;Initial Catalog=BOOK-IT-V2;Integrated Security=true;"))
using (SqlCommand cmd = new SqlCommand(#"
SELECT
DISTINCT dl.NAME AS NAME, da.BEZEICHNUNG AS BEZEICHNUNG
FROM RAUM r
RIGHT JOIN DIENSTLEISTUNG_Raum bs ON bs.RAUM_ID = (" + Room_ID + ")
RIGHT JOIN DIENSTLEISTUNG ba ON bs.DIENSTLEISTUNG_ID = ba.ID
RIGHT JOIN DIENSTLEISTUNGSART da ON ba.DIENSTLEISTUNGSART_ID = da.ID
RIGHT JOIN DIENSTLEISTER dl ON da.DIENSTLEISTER_ID = dl.ID", con))
{
con.Open();
using (SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
if (rdr["NAME"] != DBNull.Value && rdr["BEZEICHNUNG"] != DBNull.Value)
{
BestuhlungObject.Add(new DIENSTLEISTUNG()
{
DienstleistungName = rdr["NAME"].ToString(),
DienstleistungArtBezeichnung = rdr["BEZEICHNUNG"].ToString()
});
}
}
}
}
return BestuhlungObject;
}
}
}
This Webservice is working like charm. I can send one Room_ID = 219 and get the expected output. My Question is, how can i send more then one Room_ID seperated by comma. For Example: Room_ID = 219, 220, 221
Can someone please help me with that?
Thanks in advance
See T-SQL stored procedure that accepts multiple Id values
One of many ways (MS SQL 2005+), if you can pass parameters as xml:
var sql =
#"SET ARITHABORT ON;
SELECT ...
RIGHT JOIN DIENSTLEISTUNG_Raum bs ON bs.RAUM_ID IN
(
SELECT tbl.col.value('.', 'varchar(20)')
FROM #xml.nodes('id') as tbl(col)
) ...";
SqlCommand cmd = new SqlCommand(sql, connection);
cmd.Parameters.Add("#xml", SqlDbType.Xml).Value = "<id>111</id><id>222</id><id>333</id>";
Or using LIKE if you can pass parameters as ,aaa,bbb,ccc, (note the order of LIKE arguments to avoid an injection)
var sql =
#"SELECT ...
RIGHT JOIN DIENSTLEISTUNG_Raum bs ON #ids LIKE '%,' + bs.RAUM_ID + ',%'
...";
SqlCommand cmd = new SqlCommand(sql, connection);
cmd.Parameters.Add("#ids", SqlDbType.VarChar).Value = ",111,222,333,";

Categories

Resources