views:

1196

answers:

6

I have a UDF that queries data out of a table. The table, however, needs to be definable as a parameter. For example I can't have:

Select * From [dbo].[TableA]

I need something like:

Select * From [dbo].[@TableName]

The above line doesn't work, and also the UDF prohibits me from setting the query as a string and calling exec(). I can do this in a procedure, but I can't call the procedure from the UDF either.

Does anyone know how I can accomplish this within the UDF without having some kind of massive switch statement?

+2  A: 

This can't be done, dynamic SQL is not supported in functions.

See this SO question: http://stackoverflow.com/questions/150552/executing-dynamic-sql-in-a-sqlserver-2005-function

Andomar
Thanks for the link!
DaveK
This answer is correct when using normal UDFs (which is what I asked about). I was able to solve my problem with a CLR UDF written in C#.
DaveK
+2  A: 

You can write a udf clr that can do dynamic sql. I've had to implement this before. It's pretty slick.

Justin Balvanz
Right, but that would be an extended CLR function, not a UDF?
Andomar
Can it be used in a query the way a UDF can?
DaveK
Yeah, but your DBA has to agree to enable CLR support, and you have to deploy them as a compiled .NET assmebly http://msdn.microsoft.com/en-us/library/ms254498(VS.80).aspx
Andomar
This solution worked great. I was able to write a table-value CLR UDF in C#, with the sql query being generated dynamically. My regular UDF now calls the CLR UDF and assigns the returned values to parameters. I still have to do some scalability testing, but so far so good.
DaveK
+3  A: 

You can UNION ALL your tables and include the table name as a column, then specify the table name as a predicate over this. If you check the query plan for this example you see that t2 is not touched

create table t1 (i int)
create table t2 (i int)

insert t1 values(1)
insert t1 values(2)
insert t1 values(3)
insert t2 values(4)
insert t2 values(5)
insert t2 values(6)


;with tableSet as (
    select i, 't1' as tableName from t1
    union all select i, 't2' as tableName from t2
)
select i from tableSet where tableName = 't1'
+1 the question excludes a "massive switch statement" approach tho
Andomar
@Andomar, I thought this was a little less "switchy" than a bunch of if/else blocks. E.g. this set of tables to UNION ALL could be wrapped into a view if you had many functions that needed the functionality, which you couldn't do with if/else. Point taken though ;)
A: 

You cannot do it. What problem are you solving, there might be other solutions.

AlexKuznetsov
A: 
SET @SQL = 'SELECT * FROM ' + @table
EXEC (@SQL)  -- parentheses are required
johnnycrash
Be nice to know why this got a negative vote....
johnnycrash
A: 

If you would give more details about what underlying problem you are trying to solve, we might have better answers. One solution is to code generate the UDFs on a per-table basis. Another is to use dynamic SQL from an SP. What's right for your situation is hard to say.

Cade Roux