Почему моя хранимая процедура выполняет все операции выбора независимо от логики условия? - PullRequest
0 голосов
/ 28 марта 2012

Я использую SQL Server 2008.

У меня есть интересный сценарий, когда хранимая процедура (написанная «опытным пользователем») имеет нормальное время выполнения (около 4 секунд), если есть данные восновной стол.Если значение поиска не существует, время выполнения в среднем составляет около 3 минут.Из-за того, как работает процесс и веб-приложение, которое использует процедуру, ему требуется пустой набор результатов в случае отсутствия данных.

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

DECLARE @spId int

SELECT @spId = td.mainId
FROM dbo.PRIMARYTABLE
WHERE td.longId = @searchVal

IF @spId < 1 OR @spId IS NULL
BEGIN
     select 'RETURN EMPTY RESULT SET' as test
END
ELSE 
BEGIN
    SELECT 'DO ACTUAL QUERY' as test
END

Когда я проверяю это с фиктивным значениемнапример, 1111, выберите «RETURN EMPTY RESULT SET» в качестве теста.Когда я использую значение, которое, как я знаю, существует, в качестве теста возвращается SELECT 'DO ACTUAL QUERY'.Когда я заменяю «ВЫБРАТЬ« СДЕЛАТЬ АКТУАЛЬНЫЙ ЗАПРОС »как тест» фактическим усиленным запросом и использую то же несуществующее фиктивное значение, все равно выглядит, что предложение ELSE достигнуто.

Что мне здесь не хватает

Ответы [ 2 ]

1 голос
/ 28 марта 2012

Возможно, вы не все показываете. При выборе присваивания есть нелогичная вещь, когда строки не возвращаются - значение переменной не будет очищено. Вставьте это в SSMS:

declare @searchVal as int
set @searchVal=111

DECLARE @spId int
set @spId = 2134
SELECT @spId = td.mainId
FROM (select 839 as mainId, 0 as longid) td
where td.longId = @searchVal
print @spid

@ spid будет 2134. Вот почему вы всегда должны тестировать, используя @@ rowcount, в вашем случае

IF @@rowcount = 0 or @spId < 1 or @spId is null
BEGIN
    select 'RETURN EMPTY RESULT SET' as test
END
ELSE 
BEGIN
    SELECT 'DO ACTUAL QUERY' as test
END

Существует также возможность дублирования данных с помощью longId, возвращая случайный mainid из строк, которые удовлетворяют условию @searchval.

Кроме этого, я бы не знал.

0 голосов
/ 29 марта 2012

Спасибо всем за ваши предложения. Я прошу прощения за отсутствие публикации всей хранимой процедуры, но я не могу поделиться этим точным кодом. Фрагмент, с которого я начал, был psuedo-кодом (ну, реальный код с переименованными таблицами и полями).

Я думаю, что Никола Марковинович может быть что-то со своим ответом и ссылкой на статью. Все это испытание было своего рода сводящим с ума. Я гуглил, отлаживал и снова делал все это, затем искал переполнение стека. После нескольких изменений от ваших предложений, процедура волшебным образом начала отвечать временем выполнения, которое я думал, что должно. Я не думаю, что некоторые из первоначальных изменений потребовали или, возможно, они не были кэшированы на сервере sql правильно; У меня нет ничего, кроме догадок.

Это очень странно, потому что в течение часа и более он работал так, как будто его никогда не изменяли (с точки зрения производительности) ... затем он просто включался. Интересно, не моя ли это вина, и, может быть, я не изменил постановку, как на испытании ... это кажется наиболее подходящим объяснением.

Во всяком случае, спасибо за ваши предложения. Я научился нескольким вещам, так что это всегда хорошо.

...