Error Handling in T-SQL Scalar Function - sql-server-2005

This question could easily take multiple paths, so I will hit the more specific path first. While working with SQL Server 2005, I'm trying to create a scalar function that acts as a 'TryCast' from varchar to int. Where I encounter a problem is when I add a TRY block in the function;
CREATE FUNCTION u_TryCastInt
(
#Value as VARCHAR(MAX)
)
RETURNS Int
AS
BEGIN
DECLARE #Output AS Int
BEGIN TRY
SET #Output = CONVERT(Int, #Value)
END TRY
BEGIN CATCH
SET #Output = 0
END CATCH
RETURN #Output
END
Turns out theres all sorts of things wrong with this statement including "Invalid use of side-effecting or time-dependent operator in 'BEGIN TRY' within a function" and "Invalid use of side-effecting or time-dependent operator in 'END TRY' within a function". I can't seem to find any examples of using try statements within a scalar function, which got me thinking, is error handling in a function is possible?
The goal here is to make a robust version of the Convert or Cast functions to allow a SELECT statement carry through depsite conversion errors. For example, take the following;
CREATE TABLE tblTest
(
f1 VARCHAR(50)
)
GO
INSERT INTO tblTest(f1) VALUES('1')
INSERT INTO tblTest(f1) VALUES('2')
INSERT INTO tblTest(f1) VALUES('3')
INSERT INTO tblTest(f1) VALUES('f')
INSERT INTO tblTest(f1) VALUES('5')
INSERT INTO tblTest(f1) VALUES('1.1')
SELECT CONVERT(int,f1) AS f1_num FROM tblTest
DROP TABLE tblTest
It never reaches point of dropping the table because the execution gets hung on trying to convert 'f' to an integer. I want to be able to do something like this;
SELECT u_TryCastInt(f1) AS f1_num FROM tblTest
fi_num
__________
1
2
3
0
5
0
Any thoughts on this? Is there anything that exists that handles this? Also, I would like to try and expand the conversation to support SQL Server 2000 since Try blocks are not an option in that scenario.

Check if you can convert to int first, check out the IsInteger function here: IsNumeric, IsInt, IsNumber It will work on 2000 and up

And, to answer in general: No, you can't use try-catch logic in a function. I can sort of see why - or at least it's clearly preferable to avoid it, given the huge performance penalty that would come with it.
However, I think it is odd that one also cannot RAISE an error in a function... that's something built-in functions already do. I suppose one has to get by returning NULL.

The TRY…CATCH construct cannot be used in a user-defined function in SQL 2012!
See this:
http://msdn.microsoft.com/en-us/library/ms175976.aspx
When I try to use this script:
CREATE FUNCTION u_TryCastInt
(
#Value as VARCHAR(MAX)
)
RETURNS Int
AS
BEGIN
DECLARE #Output AS Int
BEGIN TRY
SET #Output = CONVERT(Int, #Value)
END TRY
BEGIN CATCH
SET #Output = 0
END CATCH
RETURN #Output
END
I got error:
Msg 443, Level 16, State 14, Procedure u_TryCastInt, Line 10
Invalid use of a side-effecting operator 'BEGIN TRY' within a function.
Msg 443, Level 16, State 14, Procedure u_TryCastInt, Line 12
Invalid use of a side-effecting operator 'END TRY' within a function.
Msg 443, Level 16, State 14, Procedure u_TryCastInt, Line 13
Invalid use of a side-effecting operator 'BEGIN CATCH' within a function.
Msg 443, Level 16, State 14, Procedure u_TryCastInt, Line 15
Invalid use of a side-effecting operator 'END CATCH' within a function.

Related

How to affect one selected Row to a local variable in T-SQL

I try to select one row from a table, and affect its value to a local declared variable I used the method below, but I got error.
Method:
DECLARE #A AS INT ;
SET #A=1;
WHILE #A<=10
BEGIN
DECLARE #R AS TABLE
SET #R = (SELECT * FROM Client c WHERE c.ID=#A)
SET #A=#A+1
END
Error I got :
Msg 156, Level 15, State 1, Line 9
Incorrect syntax near the keyword 'SET'.
So please how can I affect the subquery result to the R local variable ?
Table Variables cannot be assigned; you use DML to add data to a table variable. From docs
Assignment operation between table variables isn't supported.
table (Transact-SQL)
So something like:
DECLARE #R AS TABLE(ClientID int, Name nvarchar(200), ...)
INSERT INTO #R(ClientId, Name, ...)
SELECT ClientId, Name, ...
FROM Client c
WHERE c.ID=#A

How to start user procedure in sql?

I have a SQL Server function which I need to exec. But I tried to call it via select, exec - it throws an error. How to fix that bug and launch that function?
Procedure code
create or alter function mergetext
(#TitleOfCourtesy text,
#FirstName text,
#LastName text)
returns varchar(255)
as
begin
return concat(#TitleOfCourtesy, ' ', #FirstName, ' ', #LastName)
end
select mergetext('a','b','c')
Error message
Msg 156, Level 15, State 1, Procedure mergetext, Line 12 [Batch Start Line 0]
Incorrect syntax near the keyword 'select'.
Msg 195, Level 15, State 10, Procedure mergetext, Line 12 [Batch Start Line 0]
'mergetext' is not a recognized built-in function name.
When calling a SQL Server function, you need to include the schema. If you did not specify a schema when creating the function, then the function is created using your default schema (probably dbo). So try calling the function so:
SELECT dbo.mergetext('a','b','c')
First of all, this is not procedure. It's a function.
Second, the text type is deprecated and should not be used.
Then, you need to separate the creation of the object either using GO, executing it in a separate query window or selecting only the function and pressing F5.
Try this:
create or alter function mergetext(
#TitleOfCourtesy text,
#FirstName text,
#LastName text
)
returns varchar(255)
as
begin
return concat(#TitleOfCourtesy,' ',#FirstName,' ',#LastName)
end
GO
select dbo.mergetext('a','b','c')
and finally, why you are creating a wrapper of the CONCAT function. Just use the CONCAT wherever you need.

How to store select statement result to table variable in sql server

Declare #T_variable table(name varchar(200))
SET #T_variable =(SELECT au_lname FROM Testing)
Error Message. Msg 137, Level 16, State 1, Line 2 Must declare the
scalar variable "#T_variable".
Note :- select statement result will give multiple rows.
I try to capture the select result in table variable.But i failed.
Is there any way to capture the select result to Table variable Dynamically.
Thanks in advance.
Please try below query instead since you have declared a table variable instead of a datatype variable.
Declare #T_variable table(name varchar(200))
insert into #T_variable
SELECT au_lname FROM Testing
Try this:
SET #T_variable :=(SELECT au_lname FROM Testing)
Adding a colon may help here.

"Cannot specify decimal(5,2) data type (parameter 4) as a substitution parameter" error on SQL Server 2008

In SQL Server 2008 I get the following error:
Cannot specify decimal(5,2) data type (parameter 4) as a substitution
parameter.
Just had a look at the trigger on the table and it looks like the issue has to do with this if
if #SumField7 <> 100
begin
rollback tran
raiserror ('...%d...', 16, 1, #SumField7)
end
The issue is easy to reproduce
declare #SumField7 decimal(5,2) = 123.45
raiserror ('...%d...', 16, 1, #SumField7)
You are specifying %d as the Type specification which represents signed integer but passing it a decimal. Maybe this was never type checked in SQL Server 2000.
It looks like there is no syntax for decimal place holders and you would need to pass a string instead as below.
declare #SumField7 decimal(5,2) = 123.45
declare #SumField7String varchar(7) = #SumField7
raiserror ('...%s...', 16, 1, #SumField7String)
The error is usually caused by a RAISERROR and mismatch of parameters vs placeholder.
Do you have a trigger with RAISERROR? It isn't the INSERT...

Calling Scalar-valued Functions in SQL

I have migrated a database from oracle, and now have a few Scalar-valued Functions.
However, when I call them, I get an error saying:
Cannot find either column "dbo" or the user-defined function or aggregate "dbo.chk_mgr", or the name is ambiguous.
I'm calling it like this:
SELECT dbo.chk_mgr('asdf')
What am I doing wrong?
Are you sure it's not a Table-Valued Function?
The reason I ask:
CREATE FUNCTION dbo.chk_mgr(#mgr VARCHAR(50))
RETURNS #mgr_table TABLE (mgr_name VARCHAR(50))
AS
BEGIN
INSERT #mgr_table (mgr_name) VALUES ('pointy haired boss')
RETURN
END
GO
SELECT dbo.chk_mgr('asdf')
GO
Result:
Msg 4121, Level 16, State 1, Line 1
Cannot find either column "dbo" or the user-defined function
or aggregate "dbo.chk_mgr", or the name is ambiguous.
However...
SELECT * FROM dbo.chk_mgr('asdf')
mgr_name
------------------
pointy haired boss
Can do the following
PRINT dbo.[FunctionName] ( [Parameter/Argument] )
E.g.:
PRINT dbo.StringSplit('77,54')
That syntax works fine for me:
CREATE FUNCTION dbo.test_func
(#in varchar(20))
RETURNS INT
AS
BEGIN
RETURN 1
END
GO
SELECT dbo.test_func('blah')
Are you sure that the function exists as a function and under the dbo schema?
You are using an inline table value function. Therefore you must use Select * From function.
If you want to use select function() you must use a scalar function.
https://msdn.microsoft.com/fr-fr/library/ms186755%28v=sql.120%29.aspx
Make sure you have the correct database selected. You may have the master database selected if you are trying to run it in a new query window.