Удаление курсора, который обрабатывает неверные данные - PullRequest
0 голосов
/ 29 апреля 2020

Как мы можем удалить курсор в следующем сценарии:

DECLARE @Tablesq TABLE (numbercol INT)
INSERT INTO @Tablesq
SELECT 25 UNION all
SELECT -25 UNION all
SELECT 25 UNION all
SELECT 36

DECLARE @number INT

DECLARE sqrtcur CURSOR  FOR SELECT numbercol FROM @tablesq
OPEN sqrtcur
FETCH NEXT FROM sqrtcur INTO @number
WHILE @@FETCH_STATUS = 0
   BEGIN
         BEGIN TRY
         SELECT SQRT(@number)
         END TRY
         BEGIN CATCH
                print ERROR_MESSAGE();
         END CATCH
         FETCH NEXT FROM sqrtcur INTO @number
   END

CLOSE sqrtcur
DEALLOCATE sqrtcur

Здесь значение -25 вызывает ошибку и из-за этого я вынужден использовать курсор. Можем ли мы выполнить операцию на основе множеств для достижения того же результата?

Ответы [ 3 ]

0 голосов
/ 29 апреля 2020

SQL Сервер не обеспечивает очень хорошую обработку ошибок в операторе SELECT. Единственное исключение касается преобразования типов и функций try_, но даже это относительно недавно в истории базы данных.

SQL не одинок в этом. Стандарт просто не затрагивает этот вопрос.

Единственное, что вы можете сделать, это использовать выражение case, если вы понимаете условия, при которых вы получите ошибку:

select (case when numbercol >= 0 then sqrt(numbercol) end)
from tablesq;

SQL Сервер гарантирует, что условия when оцениваются по порядку, останавливаясь при первом совпадении, а then оценивается после when. Я должен сказать «почти при любых обстоятельствах»; В агрегационных запросах сделаны некоторые оптимизации, которые несколько ослабляют это утверждение.

Многие другие базы данных имеют аналогичные ограничения. И в большинстве из них вы можете использовать пользовательскую функцию, которая перехватывает исключение. Увы, SQL Сервер не допускает блоки try / catch в UDF, поэтому это не вариант.

0 голосов
/ 29 апреля 2020

Вы можете сделать это следующим образом:

DECLARE @tablesq TABLE (numbercol INT)
INSERT INTO @tablesq
SELECT 25 UNION all
SELECT -25 UNION all
SELECT 25 UNION all
SELECT 36;

DECLARE @number INT;

DECLARE sqrtcur CURSOR  FOR SELECT numbercol FROM @tablesq;
DECLARE @TEST FLOAT;
OPEN sqrtcur;
FETCH NEXT FROM sqrtcur INTO @number;
WHILE @@FETCH_STATUS = 0
   BEGIN
         BEGIN TRY
            SET @TEST = SQRT(@number);
            SELECT SQRT(@number);
         END TRY
         BEGIN CATCH
                print ERROR_MESSAGE();
         END CATCH;
         FETCH NEXT FROM sqrtcur INTO @number;
   END;
CLOSE sqrtcur;
DEALLOCATE sqrtcur;
0 голосов
/ 29 апреля 2020

Вы ищете это:

SELECT SQRT(numbercol)
FROM @Tablesq
WHERE numbercol > 0;
...