17

我有一个针对 SQL2005 的参数化 SQL 查询,它是在代码中动态创建的,所以我使用 ADO.NETSqlParameter类将 sql 参数添加到SqlCommand.

在上述 SQL 中,我从具有默认值的表值函数中进行选择。我希望我的动态 sql 有时为这些默认参数指定一个值,而其他时候我想指定应该使用 SQL DEFAULT- 如表值函数中定义的那样。

为了保持代码干净,我不想动态添加 SQLDEFAULT关键字并在使用非默认值时对其进行参数化,我只想将其设置DEFAULT为 my 的值SQLParameter

我可以吗?在这种情况下,最佳做法是什么?

4

5 回答 5

15

SQL 查询参数仅代替文字值。

您不能将 SQL 关键字作为参数值发送,就像您不能发送表标识符、列标识符、值列表(例如,IN谓词)或表达式一样。参数的值始终被解释为文字值,就好像您在查询中包含了带引号的字符串文字或数字文字一样。

抱歉,在准备查询之前,您必须在 SQL 查询中包含一个 SQL 关键字。

于 2010-06-03T23:46:26.577 回答
6

AFAIK,告诉 SQL Server 使用默认值的唯一方法是通过DEFAULT关键字或将其从参数列表中排除。这意味着DEFAULT关键字的使用必须在您的参数化 SQL 语句中。所以,像:

Select ...
From dbo.udf_Foo( DEFAULT, @Param2, @Param3, DEFAULT, .... )

我想另一种方法是查询系统目录以获取各种DEFAULT值的实际值,并确定是否以这种方式将 SqlParameter 设置为默认值,但这需要一个复杂的第二个查询来获取默认值。

于 2010-06-03T23:38:08.687 回答
3

如果您具有以下功能(例如):

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 如 Jack 建议的那样,代码生成的脚本将与选项 2 相同,并导致相同的错误。因此在这种情况下不能使用NULL 。也不能将DEFAULT设置为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())
            {
                //...
            }
        }
    }
}

在这种情况下,作为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

我不确定这是最佳做法。这只是解决方法。

于 2014-09-14T11:49:40.490 回答
1

虽然您不能将 SQL 关键字设置为参数的值,但在这种情况下,您可以获取默认值。

 SELECT COLUMN_DEFAULT FROM INFORMATION_SCHEMA.COLUMNS 
      WHERE TABLE_NAME = 'table_name' AND COLUMN_NAME = 'column_name'"
于 2017-11-12T15:15:30.320 回答
-1

如果你传递一个 dot net null 值作为参数值,它将使用 sql DEFAULT 如果你传递一个 dot net DBNull.Value,它将使用 sql NULL

于 2011-08-01T09:56:59.790 回答