How can we remove cursor in the following scenario:
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
Here -25 value is causing the error and because of which I am forced to use the cursor. Can we do a set-based operation to achieve the same result?
SQL Server does not provide very good error handling within a SELECT
statement. The one exception is for type conversion and the try_
functions -- but even that is relatively recently in the history of the database.
SQL is not alone in this. The standard just does not address this point.
The one thing you can do is use a case
expression, if you understand the conditions when you will get an error:
select (case when numbercol >= 0 then sqrt(numbercol) end)
from tablesq;
SQL Server guarantees that the when
conditions are evaluated in order, stopping at the first match, and the then
is evaluated after then when
. I should say "under almost all circumstances"; there are some optimizations made in aggregation queries that somewhat weaken that statement.
Many other databases have similar limitations. And in most of them, you can use a user-defined function that catches the exception. Alas, SQL Server does not allow try
/catch
blocks in UDFs, so this is not an option.