SQL Сервер Нулевые или отсутствующие значения в параметрах хранимой процедуры - PullRequest
0 голосов
/ 19 июня 2020

У меня есть следующая хранимая процедура:

CREATE PROCEDURE oc.add_discount (@course_id INT = '',
                                @level VARCHAR(100) = '',
                                @language VARCHAR(100) = '',
                                @series_name VARCHAR(100) = '',
                                @discount DECIMAL(5,4) = 0.0)
AS
BEGIN
    SET @level = ISNULL(@level,'')
    SET @language = ISNULL(@language,'')
    SET @series_name = ISNULL(@series_name,'')
    UPDATE oc.price
    SET discount = @discount,
    --discount based always on the original price
        price = price/(1-discount)*(1-@discount)
    WHERE 
        (@course_id NOT IN (SELECT course_id FROM oc.courses)
            OR course_id IN (@course_id)) AND
        (@level NOT IN (SELECT level FROM oc.level)
            OR course_id IN (SELECT c.course_id 
                    FROM oc.courses c
                    JOIN oc.level l ON c.level_id = l.level_id 
                    WHERE l.level = LOWER(@level))) AND
        (@language NOT IN (SELECT language FROM oc.language)
            OR course_id IN (SELECT c.course_id
                    FROM oc.courses c
                    JOIN oc.language l ON c.language_id = l.language_id
                    WHERE l.language = UPPER(LEFT(@language,1))+LOWER(SUBSTRING(@language,2,LEN(@language))))) AND
        (@series_name NOT IN (SELECT series_name FROM oc.series)
            OR course_id IN (SELECT c.course_id
                    FROM oc.courses c
                    JOIN oc.series s ON c.series_id = s.series_id
                    WHERE s.series_name = @series_name))
    IF @@ROWCOUNT<1
        RAISERROR('Ooops something went wrong. No discount has been added. Avoid NULL or missing values, use '' instead!', 16, 0);
END;

Моя проблема в том, что в большинстве случаев процедура работает правильно, однако, если параметр равен нулю, он ничего не обновляет, и если параметр в отсутствует середина, я получаю сообщение об ошибке. Мне удалось решить проблему с сообщением об ошибке, но я хотел бы найти более элегантное решение. Кто-нибудь может мне помочь, пожалуйста?

EXEC oc.add_discount 0.1, 1                       ---- this query gives 10% discount for course ID 1
EXEC oc.add_discount 0.1, '', 'beginner', '', ''  ---- this query 10% discount for every beginner course
EXEC oc.add_discount 0.1, NULL, 'beginner', '','' ---- "0 rows affected"
EXEC od.add_discount 0.1, ,'beginner', ,          ---- "Incorrect syntax near ','."

Ответы [ 2 ]

2 голосов
/ 19 июня 2020
  • Обычно предпочтительнее вызывать параметры по имени: Таким образом, вы можете вызывать параметры в любом порядке.

    EXEC oc.add_discount @course_id = 1, @level=''...
    
  • Если хотите для вызова процедуры с использованием упорядоченных параметров:

    • вы должны передать параметры по порядку, и вы можете пропустить последующие параметры (при условии, что они имеют значения по умолчанию).

    • вы не можете пропустить параметры в середине.

Переходя к вашему вопросу, если вы хотите пропустить средние параметры и вызвать их со значениями по умолчанию, вместо их жесткого кодирования.

EXEC oc.add_discount 0.1, DEFAULT, 'beginner', DEFAULT, DEFAULT

Или, если вы хотите передать нулевые значения, передайте нулевые значения и обработайте их внутри процедуры

EXEC oc.add_discount 0.1, NULL, 'beginner', NULL, NULL

В вашем случае вы обрабатываете это дважды. Я бы посоветовал вам поступить следующим образом.

CREATE PROCEDURE oc.add_discount (@course_id INT = NULL,
                                @level VARCHAR(100) = NULL,
                                @language VARCHAR(100) = NULL,
                                @series_name VARCHAR(100) = NULL,
                                @discount DECIMAL(5,4) = NULL)
as

    SET @level = ISNULL(@level,'')
    SET @language = ISNULL(@language,'')
    SET @series_name = ISNULL(@series_name,'')
    SET @discount = ISNULL(@discount ,0.0)
  • Если вы не передаете значение, оно заполняется значением по умолчанию NULL и устанавливается соответствующим образом.
EXEC oc.add_discount 0.1
  • Если вы хотите передать значение по умолчанию в середине, вызовите с параметром DEFAULT
EXEC oc.add_discount 0.1,DEFAULT,1,DEFAULT,DEFAULT,1
1 голос
/ 19 июня 2020

Насколько я понял, вы хотите пропустить некоторые параметры для какого-то сценария ios. Я рекомендую вам использовать следующий подход, чтобы пропустить параметры при выполнении хранимой процедуры.

EXEC od.add_discount @level='',@language='beginner'

Однако, согласно вашему примеру, я не рекомендую использовать кавычки для параметра INT. Вместо этого вам следует рассмотреть возможность использования NULL.

...