在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存储过程中传递表名的主要内容,如果未能解决你的问题,请参考以下文章

如何在存储过程中动态传递表名 - ORACLE [重复]

SQL Server 存储过程参数 - 不同类型

存储过程:将表名转换为表变量

如何从临时表名中选择,传递给存储过程?

存储过程,将表名作为参数传递

sql server存储过程如何动态生成表名