【发布时间】:2015-04-28 15:06:52
【问题描述】:
我想使用一些动态的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
这很好用。现在我得到了越来越多的具有类似代码 sn-ps 的存储过程。关于维护,我想重用 sn-ps 或使用动态功能。
一个例子:我有另一个存储过程应该“过滤”这个例子的结果集(一个额外的要求是不要添加一个参数来直接过滤这个结果集)
如果这个 SQL 是静态的,我会使用一个函数。在我的情况下,我需要那种动态。 UDF 不允许“EXEC”-stuff 和存储过程的结果集不可重用。
我希望很多人都像我一样遇到这个问题。我用谷歌搜索了很多东西并尝试了几件事,但没有任何效果......
我需要一种方法来重用存储过程代码 sn-ps 或重用存储过程的结果集或像存储过程一样动态的函数。
那么谁能帮助我并给我另一个想法?
感谢您的帮助或解决方案的想法:)
V
编辑/解决方案:
首先每个人都应该阅读“Joel Coehoorn”和“Panagiotis Kanavos”的评论。他们是绝对正确的,并且不建议在 Web 应用程序或类似的东西中使用此代码 sn-ps。在我的特殊情况下,它是一个本地应用程序,注入和其他安全方面不相关。
在那之后,我要感谢“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] ')
这只是一个例子,但我认为原理会很清楚。
感谢您的帮助和 cmets。
【问题讨论】:
-
这看起来像是 sql 注入攻击的噩梦。
-
你需要这个过程的结果在一个临时表中吗??
-
SQL(语言)不是这样工作的。您不会在多个表上“重用”语句。表相当于一种类型,您不能拥有适用于任意类型的方法。这个存储过程不是“动态的”,它只是一个使用连接创建的字符串。事实上,客户端生成的 SQL 语句(例如来自 ORM)会执行得更好并且更安全。事实上,它打开了安全漏洞(需要访问不同的数据库),打开数据库以进行注入攻击,否定执行计划缓存的任何好处,并且可以升级为分布式事务
-
这是一个本地应用程序。这就是为什么安全方面不那么重要的原因。但是您在普通的 Web 应用程序中是对的,这太糟糕了! @Abdul我可能使用临时表来获取存储过程的结果集。我会尝试一个可能的解决方案,谢谢你的提示。
标签: sql-server stored-procedures