Как указать «DEFAULT» в качестве значения параметра SQL в ADO.NET? - PullRequest
14 голосов
/ 04 июня 2010

У меня есть параметризованный запрос SQL, предназначенный для SQL2005, который динамически создается в коде, поэтому я использовал класс ADO.NET SqlParameter для добавления параметров sql в SqlCommand.

В вышеупомянутом SQL, который я выбираю из табличной функции, имеет значения по умолчанию. Я хочу, чтобы мой динамический sql иногда указывал значение для этих параметров по умолчанию, а в других случаях я хотел бы указать, что SQL DEFAULT - как определено в табличной функции - следует использовать.

Чтобы сохранить код в чистоте Я не хотел динамически добавлять ключевое слово SQL DEFAULT и параметризировать его при использовании не по умолчанию, я просто хотел установить DEFAULT как значение моего SQLParameter.

Могу ли я? Какова лучшая практика в таком случае?

Ответы [ 5 ]

14 голосов
/ 04 июня 2010

Параметры SQL-запроса заменяют буквальные значения только .

Вы не можете отправить ключевое слово SQL в качестве значения параметра, так же как вы не можете отправить идентификатор таблицы, идентификатор столбца, список значений (например, для предиката IN) или выражение. Значение параметра всегда интерпретируется как буквальное значение, как если бы вы включили строковый литерал в кавычках или числовой литерал в запрос.

Извините, но вы должны включить ключевое слово SQL как часть запроса SQL до того, как подготовите этот запрос.

6 голосов
/ 04 июня 2010

AFAIK, единственный способ указать SQL Server использовать значение по умолчанию через ключевое слово DEFAULT или исключить его из списка параметров. Это означает, что использование ключевого слова DEFAULT должно быть в параметризованном операторе SQL. Итак, что-то вроде:

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

Я полагаю, что другой подход заключается в том, чтобы запросить в системных каталогах фактическое значение различных значений DEFAULT и определить, следует ли устанавливать SqlParameter на значение по умолчанию таким образом, но для этого требуется сложный второй запрос значения.

2 голосов
/ 14 сентября 2014

Если у вас есть следующая функция (например):

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 и приведет кта же ошибка.Таким образом, вы не можете использовать 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())
            {
                //...
            }
        }
    }
}

В этом случае null в качестве значения для param2 будет переведено на правильный DEFAULT и будет создан следующий скрипт:

exec USP_SAMPLE_PROCEDURE @Param1=N'ABC',@Param2=default,@Statement=N'SELECT * FROM dbo.UFN_SAMPLE_FUNCTION (@P1, @P2)'

, который даст вам следующий результат:

Col1       Col2
---------- -----------
ABC        NULL

IЯ не уверен, что это лучшая практика.Это всего лишь обходной путь.

0 голосов
/ 12 ноября 2017

Хотя вы не можете установить ключевое слово SQL в качестве значения параметра, в этом случае вы можете пойти и получить ЗНАЧЕНИЕ ПО УМОЛЧАНИЮ.

 SELECT COLUMN_DEFAULT FROM INFORMATION_SCHEMA.COLUMNS 
      WHERE TABLE_NAME = 'table_name' AND COLUMN_NAME = 'column_name'"
0 голосов
/ 01 августа 2011

если вы передадите нулевое значение в виде точки в качестве параметра, будет использоваться sql DEFAULT если вы передадите точку DBNull.Value, он будет использовать sql NULL

...