Где условие имеет объявленную переменную в неправильном месте, не знаю, действительно ли она
У меня есть такое утверждение ниже в одном из моих больших хранимых процессов, и мне интересно, если это действительно так, чтобы написать таким образом.
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);
Таким образом, мне не нужно повторять сложный код запроса дважды.