Table lookup (SELECT) in function?
-
Monday, March 18, 2013 10:46 PM
I'm attempting to create a function that takes several variables and uses them in a query to look up a value keyed on those variables and return the looked value. If more than one row would be returned (determined by doing a count(*)), '1 to Many Err' is returned, If not found, 'OTHER' is to be returned.
Issues- Error messages:
1) CREATE FUNCTION must be the only statement in the batch.
2) Invalid Object Name DP.tbl_NSW_SUB_CAT
3) Select statements included within a function cannot return data to a client
Is this the wrong methodology to get the results I'm seeking?
If not, how do I resolve these errors?
Thank you.
Jnana
-------------------------------------------------
USE [DPIMDW]
GO
/****** Object: UserDefinedFunction [DP].[fn_NSW_SUB_CAT] Script Date: 3/18/2013 1:16:50 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GOCREATE Function [DP].[fn_NSW_SUB_CAT]
(@Prod_Engn_Cd nvarchar(5), @Glbl_Cat_Sum_Cd nvarchar(5), @Reg_Long_Rng_Sesn_Mktg_Clsfcn_Desc_2 nvarchar(5))
Returns nvarchar(5)
AS
BEGINDeclare @NSW_SUB_CAT nvarchar(15)
IF @Prod_Engn_Cd = '10'
AND @Glbl_Cat_Sum_Cd = '1006'
BEGIN
IF (SELECT count(*) from DP.tbl_NSW_SUB_CAT nsc
WHERE nsc.Prod_Engn_Cd = @Prod_Engn_Cd
AND nsc.Glbl_Cat_Sum_Cd = @Glbl_Cat_Sum_Cd
AND nsc.Reg_Long_Rng_Sesn_Mktg_Clsfcn_Desc_2 = @Reg_Long_Rng_Sesn_Mktg_Clsfcn_Desc_2
) > 1
SET @NSW_SUB_CAT = '1 to Many Err'
ELSE SET @NSW_SUB_CAT= ISNULL (SELECT nsc.NSW_SUB_CAT from DP.tbl_NSW_SUB_CAT nsc
WHERE nsc.Prod_Engn_Cd = @Prod_Engn_Cd
AND nsc.Glbl_Cat_Sum_Cd = @Glbl_Cat_Sum_Cd
AND nsc.Reg_Long_Rng_Sesn_Mktg_Clsfcn_Desc_2 = @Reg_Long_Rng_Sesn_Mktg_Clsfcn_Desc_2),'OTHER')
ENDELSE @NSW_SUB_CAT = 'N/A'
END
RETURN @NSW_SUB_CAT
End
Jnana Sivananda
All Replies
-
Monday, March 18, 2013 11:23 PM
I cannot obviously not say why you get "Invalid Object Name DP.tbl_NSW_SUB_CAT", or raher I don't know you what you think is wrong with message. But a hint: If SQL Server says that a table exists, it's probably right. Computers are good at such things. Maybe you are in the wrong database.
When I try the code you posted, I get these errors:
Msg 156, Level 15, State 1, Procedure fn_NSW_SUB_CAT, Line 18
Incorrect syntax near the keyword 'SELECT'.
Msg 102, Level 15, State 1, Procedure fn_NSW_SUB_CAT, Line 21
Incorrect syntax near ')'.
Msg 102, Level 15, State 1, Procedure fn_NSW_SUB_CAT, Line 29
Incorrect syntax near 'End'.There is a left paren missing after "isnull(" - the subquery must be in parentheses. When I fix this, I get:
Msg 102, Level 15, State 1, Procedure fn_NSW_SUB_CAT, Line 24
Incorrect syntax near '@NSW_SUB_CAT'.
Msg 102, Level 15, State 1, Procedure fn_NSW_SUB_CAT, Line 29
Incorrect syntax near 'End'.Which is dues to this line:
ELSE @NSW_SUB_CAT = 'N/A'
Which is not legal SQL; you need SET or SELECT here. Fixing that I get:
Msg 156, Level 15, State 1, Procedure fn_NSW_SUB_CAT, Line 28
Incorrect syntax near the keyword 'RETURN'.
Msg 102, Level 15, State 1, Procedure fn_NSW_SUB_CAT, Line 29
Incorrect syntax near 'End'.Which makes sense, the END that follows the ELSE has no match. So let's remove that. Now I get:
Msg 2760, Level 16, State 1, Procedure fn_NSW_SUB_CAT, Line 28
The specified schema name "DP" either does not exist or you do not have permission to use it.Which is not surprising at all, since I don't have that schema at all.
So one of your problems is that you are giving up too soon. Getting compilation errors is just part of the faily chores in the programmer's trade.
But there is also another problem, and that is the idea of the function itself. You should avoid scalar functions with data access, because they can often cause performance problems, since SQL Server never lines them, but they get called for every row.
Erland Sommarskog, SQL Server MVP, esquel@sommarskog.se- Proposed As Answer by Naomi NMicrosoft Community Contributor, Moderator Monday, March 18, 2013 11:41 PM
- Marked As Answer by Jnana Tuesday, March 19, 2013 5:48 PM
-
Monday, March 18, 2013 11:35 PM
In addition to Erland's comments, your function header says the function will return varchar(5), but you declare @NSW_SUB_CAT as nvarchar(15). That is not the cause of any of your current compile errors, but it will cause you problems when you begin using the function. If you take the branch that puts "1 to Many Err" into @NSW_SUB_CAT, the return statement will truncate that to 5 characters and return "1 to".
Tom
-
Tuesday, March 19, 2013 3:12 AMWe hate UDF's. They do not optimize, they do not port, and they are bitch to maintain because of side effects. When we write them, we avoid all local variable – local variables are procedural coding. Unfortunately, T-SQL function syntax is based on 1970's hardware and assembly language. The result has to be loaded into a local variable, then returned to mimic the registers in very old IBM hardware.
Where is the DDL?
You also do not know ISO-11179 rules and are “tibbling” --that is the design flaw of putting “tbl-” on table names, or “fn_” on function names. It mixes data and meta data. We also truly hate if-then-else and while control flow logic; SQL is a set-oriented declarative language.
Without specs, my thought was a simple query that return the search value(s) and the count for multiple matches.
CREATE PROCEDURE Nsw_Sub_Cat
(@in_prod_engn_code NVARCHAR(5),
@in_glbl_cat_sum_code NVARCHAR(5),
@in_reg_long_rng_sesn_mktg_clsfcn_desc_2 NVARCHAR(5))
SELECT NSC.nsw_sub_cat,
CASE WHEN @in_prod_engn_code = '10'
AND @in_glbl_cat_sum_code = '1006'
THEN 'okay' ELSE 'other' END AS weird_flg,
COUNT(*) OVER() AS search_cnt
FROM NSW_Sub_Cat AS NSC
WHERE NSC.prod_engn_code = @in_prod_engn_code
AND NSC.glbl_cat_sum_code = @in_glbl_cat_sum_code
AND NSC.reg_long_rng_sesn_mktg_clsfcn_desc_2
= @in_reg_long_rng_sesn_mktg_clsfcn_desc_2;
Between the count(*) and the weird flag, the presentation layer should be able display the messages you embedded in the database layer.--CELKO-- Books in Celko Series for Morgan-Kaufmann Publishing: Analytics and OLAP in SQL / Data and Databases: Concepts in Practice Data / Measurements and Standards in SQL SQL for Smarties / SQL Programming Style / SQL Puzzles and Answers / Thinking in Sets / Trees and Hierarchies in SQL
-
Tuesday, March 19, 2013 8:34 AM
We hate UDF's. They do not optimize, they do not port, and they are bitch to maintain because of side effects.
"do not optimize" is true for scalar function as well as multi-statement table functions, but not inline table function. No one here but you cares whether they port. The last part is completely untrue for functions in SQL Server; Microsoft is very restrictive with what they permit in user-defined tunctions.
Erland Sommarskog, SQL Server MVP, esquel@sommarskog.se -
Tuesday, March 19, 2013 5:49 PM
Thanks, much. This resolved the issues.
-Jnana
Jnana Sivananda
-
Tuesday, March 19, 2013 5:49 PM
Thanks, Tom.
-Jnana
Jnana Sivananda
-
Tuesday, March 19, 2013 5:55 PM
Thanks Celko. This is certainly elegent and fat-free. I appreciate the updated style.
-Jnana
Jnana Sivananda

