如果您有以下函数(例如):
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())
{
}
}
}
}
接下来,如果像Jack建议的那样param2 = null,由代码生成的脚本将与选项2相同,并导致相同的错误。所以在这种情况下,你不能使用NULL。你也不能将DEFAULT设置为SQLParameter的值。
你可以做的是创建一个存储过程来包装对你的函数的调用,并将默认值从函数移动到SP。例如:
CREATE PROCEDURE dbo.USP_SAMPLE_PROCEDURE
(
@Param1 nvarchar(10),
@Param2 int = NULL,
@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,
Value = "SELECT * FROM dbo.UFN_SAMPLE_FUNCTION (@P1, @P2)"
};
cmd.Parameters.Add(param);
cmd.Connection.Open();
using (IDataReader dataReader = cmd.ExecuteReader())
{
}
}
}
}
在这种情况下,
param2 的值为
null 将被翻译为正确的
DEFAULT,并将生成以下脚本:
exec USP_SAMPLE_PROCEDURE @Param1=N'ABC',@Param2=default,@Statement=N'SELECT * FROM dbo.UFN_SAMPLE_FUNCTION (@P1, @P2)'
这将会给你以下结果:
Col1 Col2
ABC NULL
我不确定这是否是最佳实践,这只是一种解决方法。
INSERT
(或UPDATE
)语句中像使用NULL
一样使用DEFAULT
:INSERT INTO foo(col1, col2) VALUES(1234, DEFAULT)
。这是标准的SQL语法,但鲜为人知。 - Bill KarwinCoalesce(@Foo, DEFAULT)
)。 - Thomas