您如何将“默认值”指定为ado.net中的SQL参数值?
-
24-10-2019 - |
题
我有一个针对SQL2005的参数化SQL查询,该查询是在代码中动态创建的,因此我使用了ado.net SqlParameter
添加SQL参数的类 SqlCommand
.
在上述SQL中,我从具有默认值的表值函数中选择。我希望我的动态SQL有时为这些默认参数指定一个值,而其他时间我想指定SQL DEFAULT
- 如表值函数所定义 - 应使用。
保留代码 干净的 我不想动态添加SQL DEFAULT
关键字并在要使用非默认的情况下参数化,我只是想设置 DEFAULT
作为我的价值 SQLParameter
.
我可以吗?在这种情况下,最好的做法是什么?
解决方案
SQL查询参数代替字面价值 只要.
您不能将SQL关键字作为参数的值发送,就像您无法发送表标识符,列标识符,值列表一样(例如 IN
谓词)或表达式。参数的值为 总是 被解释为字面价值,好像您在查询中包括了引用的字符串字面或数字字面的字面。
抱歉,但是您必须包含一个SQL关键字作为SQL查询的一部分 前 您准备该查询。
其他提示
AFAIK,告诉SQL Server使用默认值的唯一方法是通过 DEFAULT
关键字或将其从参数列表中排除。这意味着使用 DEFAULT
关键字必须在您的参数化SQL语句中。所以,类似:
Select ...
From dbo.udf_Foo( DEFAULT, @Param2, @Param3, DEFAULT, .... )
我想另一种方法是查询系统目录的实际值 DEFAULT
值并确定是否将SQLPARAMETER设置为默认值,但这需要复杂的第二查询才能获取默认值。
如果您具有以下功能(例如):
CREATE FUNCTION dbo.UFN_SAMPLE_FUNCTION
(
@Param1 nvarchar(10),
@Param2 int = NULL
)
RETURNS TABLE
AS
RETURN
SELECT @Param1 AS Col1, @Param2 AS Col2;
GO
然后,您可以以以下方式使用它(选项1):
SELECT * FROM dbo.UFN_SAMPLE_FUNCTION ('ABC', DEFAULT);
这是正确的方法,您将获得以下结果:
Col1 Col2
---------- -----------
ABC NULL
但是,如果您尝试使用参数化查询(选项2):
exec sp_executesql N'SELECT * FROM dbo.UFN_SAMPLE_FUNCTION (@P1, @P2)',N'@P1 nvarchar(10),@P2 int',@P1=N'abc',@P2=default;
您会遇到一个错误:
Msg 8178, Level 16, State 1, Line 0
The parameterized query '(@P1 nvarchar(10),@P2 int)SELECT * FROM dbo.UFN_SAMPLE_FUNCTION' expects the parameter '@P2', which was not supplied.
如果您有以下.NET代码:
public void RunTVF(string param1, int? param2)
{
using (SqlConnection con = GetProdConection())
{
using (var cmd = new SqlCommand("SELECT * FROM dbo.UFN_SAMPLE_FUNCTION (@P1, @P2)", con))
{
cmd.CommandType = CommandType.Text;
var param = new SqlParameter
{
ParameterName = "@P1",
SqlDbType = SqlDbType.NVarChar,
Size = 10 ,
Value = param1
};
cmd.Parameters.Add(param);
param = new SqlParameter
{
ParameterName = "@P2",
SqlDbType = SqlDbType.Int,
Value = param2
};
cmd.Parameters.Add(param);
cmd.Connection.Open();
using (IDataReader dataReader = cmd.ExecuteReader())
{
//...
}
}
}
}
然后,如果param2 = null如上所述,代码产生的脚本将与选项2相同,并且会导致相同的错误。所以你不能使用 无效的 在这种情况下。您无法设置 默认 作为SQLParameter的值。
您可以做的是创建一个存储过程,以将调用呼叫包裹到您的功能,并将默认值从函数移至SP。例子:
CREATE PROCEDURE dbo.USP_SAMPLE_PROCEDURE
(
@Param1 nvarchar(10),
@Param2 int = NULL, --DEFAULT value now is here (remove it from the function)
@Statement nvarchar(max)
)
AS
BEGIN
SET NOCOUNT ON;
EXEC sp_executesql @Statement,N'@P1 nvarchar(10),@P2 int',@P1=@Param1,@P2=@Param2;
END
.NET代码将以以下方式查看:
public void RunWrapper(string param1, int? param2)
{
using (SqlConnection con = GetProdConection())
{
using (var cmd = new SqlCommand("USP_SAMPLE_PROCEDURE", con))
{
cmd.CommandType = CommandType.StoredProcedure;
var param = new SqlParameter
{
ParameterName = "@Param1",
SqlDbType = SqlDbType.NVarChar,
Size = 10,
Value = param1
};
cmd.Parameters.Add(param);
param = new SqlParameter
{
ParameterName = "@Param2",
SqlDbType = SqlDbType.Int,
Value = param2
};
cmd.Parameters.Add(param);
param = new SqlParameter
{
ParameterName = "@Statement",
SqlDbType = SqlDbType.NVarChar,
Size = -1, //-1 used in case you need to specify nvarchar(MAX)
Value = "SELECT * FROM dbo.UFN_SAMPLE_FUNCTION (@P1, @P2)"
};
cmd.Parameters.Add(param);
cmd.Connection.Open();
using (IDataReader dataReader = cmd.ExecuteReader())
{
//...
}
}
}
}
在这种情况下 无效的 作为 参数2 将翻译成正确的 默认 并将生成以下脚本:
exec USP_SAMPLE_PROCEDURE @Param1=N'ABC',@Param2=default,@Statement=N'SELECT * FROM dbo.UFN_SAMPLE_FUNCTION (@P1, @P2)'
这将为您带来以下结果:
Col1 Col2
---------- -----------
ABC NULL
我不确定这是最好的做法。这只是解决方案。
尽管您无法将SQL关键字设置为参数的值,但在这种情况下,您可以获取默认值。
SELECT COLUMN_DEFAULT FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'table_name' AND COLUMN_NAME = 'column_name'"
如果将点NET NULL值作为参数值传递,如果您通过DOT NET DBNULL.VALUE将使用SQL NULL,则将使用SQL默认值