删除正在处理坏数据的游标
Removal of cursor which is processing bad data
在以下情况下我们如何删除游标:
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 值导致错误,因此我被迫使用游标。我们可以做一个基于集合的操作来达到相同的结果吗?
你在找这个吗:
SELECT SQRT(numbercol)
FROM @Tablesq
WHERE numbercol > 0;
SQL 服务器在 SELECT
语句中没有提供很好的错误处理。一个例外是类型转换和 try_
函数——但即便如此,这在数据库的历史中也是相对较新的。
SQL 并不孤单。标准只是没有解决这一点。
您可以做的一件事是使用 case
表达式,如果您了解出现错误的条件:
select (case when numbercol >= 0 then sqrt(numbercol) end)
from tablesq;
SQL 服务器保证 when
条件按顺序求值,在第一个匹配处停止,then
在 when
之后求值。我应该说 "under almost all circumstances";在聚合查询中进行了一些优化,在某种程度上削弱了该语句。
许多其他数据库也有类似的限制。在大多数情况下,您可以使用捕获异常的用户定义函数。唉,SQL 服务器不允许在 UDF 中使用 try
/catch
块,所以这不是一个选项。
你可以这样做:
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;
在以下情况下我们如何删除游标:
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 值导致错误,因此我被迫使用游标。我们可以做一个基于集合的操作来达到相同的结果吗?
你在找这个吗:
SELECT SQRT(numbercol)
FROM @Tablesq
WHERE numbercol > 0;
SQL 服务器在 SELECT
语句中没有提供很好的错误处理。一个例外是类型转换和 try_
函数——但即便如此,这在数据库的历史中也是相对较新的。
SQL 并不孤单。标准只是没有解决这一点。
您可以做的一件事是使用 case
表达式,如果您了解出现错误的条件:
select (case when numbercol >= 0 then sqrt(numbercol) end)
from tablesq;
SQL 服务器保证 when
条件按顺序求值,在第一个匹配处停止,then
在 when
之后求值。我应该说 "under almost all circumstances";在聚合查询中进行了一些优化,在某种程度上削弱了该语句。
许多其他数据库也有类似的限制。在大多数情况下,您可以使用捕获异常的用户定义函数。唉,SQL 服务器不允许在 UDF 中使用 try
/catch
块,所以这不是一个选项。
你可以这样做:
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;