SQL Server:动态函数或存储过程的重用

时间:2015-04-28 15:06:52

标签: sql-server stored-procedures

我想使用一些动态SELECT语句。表或列的名称可能不同,这就是我使用这样的动态存储过程的原因:

CREATE PROCEDURE [dbo].[test_sp](
     @database nvarchar(70)= ''
    , @table_name nvarchar(70)= ''
    , @column nvarchar(70)= ''
) 
AS
    DECLARE @sql nvarchar(max)= 'SELECT ' + @column + 
                                'FROM [' + @database + 
                                '].[dbo].[' + @table_name + ']  ' 

    EXEC(@sql);
GO

这非常有效。现在我有越来越多的存储过程与类似的代码片段。关于维护我想重用片段或使用动态函数。

一个例子:我有另一个存储过程应该"过滤"此示例的结果集(另一个要求是不添加参数来直接过滤此结果集)

如果这个SQL是静态的,我会使用一个函数。在我的情况下,我需要动态。 UDF不允许" EXEC" -stuff和存储过程的结果集不可重复使用。

我希望很多人能像我这样得到问题。我google了很多东西,尝试了几件事,但没有任何作用......

我需要一种方法来重用存储过程代码片段或重用存储过程的结果集或像存储过程一样动态的函数。

那么有人可以帮助我并给我另一个想法吗?

感谢您的帮助或解决方案的想法:)

V

修改/解决方案:
首先,每个人都应该阅读" Joel Coehoorn"的评论。和" Panagiotis Kanavos"。它们是绝对正确的,并且在Web应用程序或类似的东西中不建议使用此代码段。在我的特殊情况下,它是一个本地应用程序,注射和其他安全方面是不相关的。

之后我要感谢你和#34; Abdul Rehman Sayed"。以下解决方案基于他的想法。

要在SQL中实现该要求,您必须创建两个存储过程。第一个是创建一个结果集并将其写入临时表。

第二个执行第一个存储过程,过滤结果并删除临时表。

第一个:

ALTER PROCEDURE [dbo].[test_SP_FXN](
 @database nvarchar(70)= ''
) AS

DECLARE @create nvarchar(max)= '
    CREATE TABLE ['+@database+'].[dbo].[temp_result](
    [name] [nvarchar](150) NULL
  ,[id] [nvarchar](150) NULL
  ,[desc] [nvarchar](450) NULL )  ';

DECLARE @sql nvarchar(max)= '
INSERT INTO ['+@database+'].[dbo].[temp_result]
    SELECT TOP 1000 name, id, desc
    FROM ['+@database+'].[dbo].[important_table] ';

EXEC(@create);
EXEC(@sql);

第二个:

ALTER PROCEDURE [dbo].[test_SP_2](
 @database nvarchar(70)= ''
) AS
-- create the temp table with the result of the store procedure
EXEC ('['+@database+'].[dbo].[test_SP_FXN] '+@database )

-- Execute the real sql
DECLARE @sql nvarchar(max)= 'select * FROM ['+@database+'].[dbo].[temp_result] WHERE ID > 5' 
EXEC(@sql);

-- drop the temp table because there is no use any more
EXEC ('DROP TABLE ['+@database+'].[dbo].[temp_result] ')

这只是一个例子,但我认为原则很清楚。

感谢您的帮助和评论。

2 个答案:

答案 0 :(得分:0)

另一方面,您可以将存储过程更改为以下内容:

CREATE PROCEDURE [dbo].[test_sp](
    , @Select nvarchar(70)= ''
    , @From nvarchar(70)= ''
    , @Where nvarchar(max) = ''
    , @GroupByColumn nvarchar(max) = ''
    , @Having nvarchar(max) = ''
    , @OrderBy nvarchar(max) = ''
) 
AS
    DECLARE @sql nvarchar(max)= 'SELECT ' + @Select + 
                                'FROM ' + @From + 
                                CASE WHEN @Where = '' THEN '' ELSE ' WHERE ' + @Where END +
                                CASE WHEN @GroupByColumn = '' THEN '' ELSE ' GROUP BY ' + @GroupByColumn END +
                                CASE WHEN @Having = '' THEN '' ELSE ' HAVING ' + @Having END +
                                CASE WHEN @OrderBy = '' THEN '' ELSE ' ORDER BY ' + @OrderBy END

    EXEC(@sql);
GO

现在你可以像这样测试它:

EXEC test_sp @Select = 'Column1, Column2', @From = 'Table1'

EXEC test_sp @Select = 'DISTINCT Table1.Column1, Table2.Column1', @FROM = 'Table1 INNER JOIN TABLE2 ON Table1.PK = Table2.FK'

EXEC test_sp  @Select = 't1.[datetime]', @From = '[TestDB].[dbo].[Table1] t1', @Where = 't1.NullableColumn IS NOT NULL'

EXEC test_sp @Select = 'Column1, Column2', @From = 'Table1', @OrderBy = 'Column2'

等等......

答案 1 :(得分:-1)

我认为你正在寻找这样的东西:

Declare @table Table(/* list of columns */)

insert into @table
EXEC test_sp 'aDbName','aTable','somecolumns'

select *
from @table
where /* some filters */