在sql存储过程中传递表名
Posted
技术标签:
【中文标题】在sql存储过程中传递表名【英文标题】:Passing table name in sql stored procedure 【发布时间】:2012-05-24 09:13:28 【问题描述】:是否可以将表名作为输入参数传递给存储过程?
例如:
create procedure test
@tablename char(10)
as
begin
select * from @tablename
end
go
我知道这行不通。那么如果我想将表名传递到存储过程中,最好的方法是什么?
非常感谢
【问题讨论】:
这能回答你的问题吗? How should I pass a table name into a stored proc? 【参考方案1】:最安全的方法是通过视图。
创建一个视图,它将您可能希望访问的所有表联合起来(并且这些表必须具有相同的列结构),并在行前加上表名。
CREATE VIEW MultiTable
AS
SELECT 'table1' AS TableName, * FROM table1
UNION ALL
SELECT 'table2' AS TableName, * FROM table2
UNION ALL
SELECT 'table3' AS TableName, * FROM table3
您的存储过程现在可以过滤表名:
CREATE PROCEDURE test
@TableName varchar(100)
AS
SELECT * FROM MultiTable WHERE TableName = @TableName
这比使用动态 SQL 创建和执行更安全。
【讨论】:
需要注意的是,使用“*”的例子是假设三个表的列数相同。我相信否则你会得到一个错误。即使是这种情况,作为最佳实践,您也应该在每个 SELECT 中枚举它们。 @Buggieboy 可能会收到该错误,如果列仅在其中一个表中发生更改是值得的........【参考方案2】:您需要使用动态 SQL,但您需要注意潜在的 sql 注入风险,就像 @tablename 包含一些狡猾的东西一样,您可能会陷入痛苦的世界。
例如
-- basic check to see if a table with this name exists
IF NOT EXISTS(SELECT * FROM sys.tables WHERE name = @tablename)
RETURN
DECLARE @sql NVARCHAR(100)
SET @sql = 'SELECT * FROM ' + QUOTENAME(@tablename)
EXECUTE(@sql)
你需要非常小心这种方法,确保你没有打开一罐安全蠕虫。
我的另一个顾虑是您可能正在尝试创建通用数据访问存储过程,这通常是个坏主意。显然我不知道你的用例。
【讨论】:
Yours is case number one! 非常感谢。 sql注入的可能性几乎可以忽略不计,因为表名没有用户条目。它仅由应用程序内部使用 - 我想避免创建多个具有相同逻辑的存储 prc,但表名不同 @Bridge - 是的,我完全同意。在我真正需要使用动态表名的情况下,我个人在应用程序代码中生成了 SQL。但我发现真正的用例并不常见 @user1414575 - 我强烈推荐阅读 Erland Sommerskog 的文章(@Bridge 的链接)。这听起来确实像您正在寻找的一种节省时间/通用数据访问方法,根据我的经验,这是不好的【参考方案3】:DECLARE @Name VARCHAR(50)
SET @Name='Company'
EXEC('SELECT * from ' + @Name )
使用这种方式从数据库中获取记录。
【讨论】:
以上是关于在sql存储过程中传递表名的主要内容,如果未能解决你的问题,请参考以下文章