Где условие имеет объявленную переменную в неправильном месте, не знаю, действительно ли она

У меня есть такое утверждение ниже в одном из моих больших хранимых процессов, и мне интересно, если это действительно так, чтобы написать таким образом.

SELECT  @PVDate = pv.Date,
        @PVdMBeginDate = dbo.fPVoidDate(pv.myID)
FROM PVMeter pv (NOLOCK)
WHERE pv.PR_ID = @PR_ID
AND @VCommen BETWEEN pv.PVDMDate AND dbo.fPVoidDate(pv.myID)

Теперь вот мой вопрос: @VCommen - объявленная переменная даты с установленным значением. Это совсем не столбец PVMeter, в то время как PVDMDate - это столбец в PVMeter, а fpVoidDate возвращает datetime

Пока я отлаживаю SP, я не вижу значения в @PVDate и @PVDMBeginDate

1 ответ

Решение

Исходный запрос эквивалентен:

SELECT  
    @PVDate = pv.Date,
    @PVdMBeginDate = dbo.fPVoidDate(pv.myID)
FROM PVMeter pv (NOLOCK)
WHERE 
    pv.PR_ID = @PR_ID
    AND pv.PVDMDate <= @VCommen
    AND @VCommen <= dbo.fPVoidDate(pv.myID)

Этот стиль должен быть более знакомым. В общем, вы можете поместить любое выражение в WHERE предложение, оно может быть сделано из переменных или констант без ссылки на столбцы таблицы вообще.

Примеры

Классический пример: WHERE 1=1 ... когда текст запроса генерируется динамически. Легко добавить столько выражений, сколько необходимо, без определенного порядка и добавить все их AND,

DECLARE @VarSQL nvarchar(max);

SET @VarSQL = 'SELECT ... FROM ... WHERE 1=1 ';

IF ... THEN SET @VarSQL = @VarSQL + ' AND expression1';
IF ... THEN SET @VarSQL = @VarSQL + ' AND expression2';
IF ... THEN SET @VarSQL = @VarSQL + ' AND expression3';

EXEC @VarSQL;

Таким образом, вам не нужно иметь сложную логику, определяющую, нужно ли вам добавить AND перед каждым выражением или нет.

Другой пример.

У вас есть хранимая процедура с параметром @ParamID int,

У вас есть сложный запрос в процедуре, который обычно возвращает много строк, и один столбец набора результатов является уникальным ID,

SELECT ID, ...
FROM ...
WHERE
expression1
AND expression2
AND expression3
...

Вы хотите вернуть все строки, если @ParamID является NULL и только один ряд с данным ID если @ParamID не является NULL, Я лично использую этот подход. Когда я впервые открываю экран с результатами запроса, я хочу показать все строки пользователю, поэтому я передаю NULL в качестве параметра. Затем пользователь вносит изменения в выбранную строку, что делается через отдельный UPDATE заявление. Затем я хочу обновить результаты, которые пользователь видит на экране. я знаю ID строки, которая была только что изменена, поэтому мне нужно запросить только эту строку, поэтому я передаю это ID обработать и извлечь только одну строку вместо всей таблицы снова.

Окончательный запрос будет выглядеть так:

SELECT ID, ...
FROM ...
WHERE
(@ParamID IS NULL OR ID = @ParamID)
AND expression1
AND expression2
AND expression3
...
OPTION (RECOMPILE);

Таким образом, мне не нужно повторять сложный код запроса дважды.

Другие вопросы по тегам