SQL Server 2016 .Net 4.5.2 C#
我尊重地说,我正在使用Northwind数据库来展示我想要实现的目标。请不要评论Northwind数据库。这只是我将要做的一个例子。
我正在使用ADO.Net来执行内联sql。我的困境是我将有可能传递给sql查询的可选参数。这是C#:
var city = "";
var state = "tx";
var sqlQuery = "
if exists @City
begin
select * from Customers where city = @City and state=@State;
end
else
begin
select * from Customers where state=@State;
end
";
var conn = new SqlConnection("Server=(local);DataBase=Northwind;Integrated Security=SSPI");
conn.Open();
SqlCommand cmd = new SqlCommand(sqlQuery, conn);
if (!string.IsNullorEmpty(city))
{
SqlParameter param = new SqlParameter();
param.ParameterName = "@City";
param.Value = city;
cmd.Parameters.Add(param);
}
if (!string.IsNullorEmpty(state))
{
SqlParameter param = new SqlParameter();
param.ParameterName = "@State";
param.Value = state;
cmd.Parameters.Add(param);
}
var reader = cmd.ExecuteReader();
如您所见,变量city为空,因此参数@City不会传递给sql查询,但变量状态不为空,因此@State参数将传递给查询。请记住,@ City不会一直空白。我在sql中检查是否存在@City,但这不起作用。如果@City,@ State或可能传入的任何其他参数存在,我如何检查sql查询?如果我可以想出那个部分,我可以处理sql中需要做的事情。感谢您的帮助。
P.S。我不能使用存储过程。
答案 0 :(得分:2)
select *
from
Customers
where
state=@State
AND (city = @City
OR ISNULL(@City,'') = '')
我建议上面你可以在1选择语句中完成,而不必使用IF控制方法。它将测试城市,但它也会说@City是否为空,然后返回它,因为只有其中一个条件可以是真的,你永远不会得到你不想要的结果。要使用控制方法,您可以执行以下操作,
IF ISNULL(@City,'') <> ''
BEGIN
select * from Customers where city = @City and state=@State;
END
ELSE
BEGIN
select * from Customers where state=@State;
END
但是第一个例子再次更标准,代码更少,所以我建议这样做。
编辑: 您必须每次都传递参数。否则,您实际上将更改C#代码中的SQL语句而不是SQL代码。
接下来,您将实际传递一个空字符串而不是NULL值,查看您的var city = "";
分配,以便您可以切换到测试。
完全没有传递参数的问题是你的SQL语句将使用你没有声明的变量,如果你不添加参数值。因此标准方法是始终传递变量并使用类似上面第一个的SQL语句。如果您真的想以不同的方式完成它甚至根本不通过,那么您将需要使用c#控制流来不同地构建SQL字符串。
标准方式:
var city = "";
var state = "tx";
var sqlQuery = "
select *
from
Customers
where
state=@State
AND (city = @City
OR ISNULL(@City,'') = '')
";
var conn = new SqlConnection("Server=(local);DataBase=Northwind;Integrated Security=SSPI");
conn.Open();
SqlCommand cmd = new SqlCommand(sqlQuery, conn);
SqlParameter param = new SqlParameter();
param.ParameterName = "@City";
param.Value = city;
cmd.Parameters.Add(param);
SqlParameter param = new SqlParameter();
param.ParameterName = "@State";
param.Value = state;
cmd.Parameters.Add(param);
var reader = cmd.ExecuteReader();
不传递参数的方法是通过c#控制流动态构建SQL语句:
var city = "";
var state = "tx";
var sqlQuery = "
select *
from
Customers
where
state=@State
";
if (!string.IsNullorEmpty(city))
{
sqlQuery += "
AND city=@City";
}
var conn = new SqlConnection("Server=(local);DataBase=Northwind;Integrated Security=SSPI");
conn.Open();
SqlCommand cmd = new SqlCommand(sqlQuery, conn);
if (!string.IsNullorEmpty(city))
{
SqlParameter param = new SqlParameter();
param.ParameterName = "@City";
param.Value = city;
cmd.Parameters.Add(param);
}
SqlParameter param = new SqlParameter();
param.ParameterName = "@State";
param.Value = state;
cmd.Parameters.Add(param);
var reader = cmd.ExecuteReader();
如果你没有通过参数,那么为了更加了解must declare scalar variable @city
的原因是因为c#中的参数定义是在SQL中定义变量的内容。所以:
SqlParameter param = new SqlParameter();
param.ParameterName = "@City";
param.Value = city;
cmd.Parameters.Add(param);
基本上在SQL中这样做:
DECLARE @City VARCHAR(50)
SET @City = value of city var.
因此,如果您在城市变量上使用if控制流而忽略此步骤,则省略变量定义,SQL将失败。因此,虽然参数的值可以是可选的,但如果在SQL语句中引用它,则参数本身不是选项。
另请注意,您在参数定义中使用隐式数据类型,您应该明确定义数据类型!
答案 1 :(得分:0)
当您通过sql进行传递时,使用可选参数很有挑战性。它确实无助于使您的代码更好。选项参数在存储过程中很有用,但在传递查询中,它比它的价值要大得多。处理此问题的最佳方法是始终传递参数。但是你可以传递一个DBNull并在你的查询中处理它。
我还强烈建议您开始在USING语句中包装iDisposable对象。特别是连接和命令之类的东西。您不希望软管连接池,因为您偶然错过了Dispose通话。
这是一种可以非常干净地管理这类事物的方法。
var sqlQuery = "select *
from Customers
where
(
state = @State
OR
@state is null
)
AND
(
city = @City
OR
@City is null
)";
using (SqlConnection conn = new SqlConnection("Server=(local);DataBase=Northwind;Integrated Security=SSPI"))
{
conn.Open();
using(SqlCommand cmd = new SqlCommand(sqlQuery, conn))
{
SqlParameter param = new SqlParameter();
param.ParameterName = "@City";
if (string.IsNullorEmpty(city))
{
param.value = DBNull.Vale;
}
else
{
param.Value = city;
}
cmd.Parameters.Add(param);
SqlParameter param = new SqlParameter();
param.ParameterName = "@State";
if(string.IsNullorEmpty(state))
{
param.value = DBNull.Vale;
}
else
{
param.Value = state;
}
cmd.Parameters.Add(param);
}
}
}