【发布时间】:2012-05-24 09:13:28
【问题描述】:
是否可以将表名作为输入参数传递给存储过程?
例如:
create procedure test
@tablename char(10)
as
begin
select * from @tablename
end
go
我知道这行不通。那么如果我想将表名传递到存储过程中,最好的方法是什么?
非常感谢
【问题讨论】:
是否可以将表名作为输入参数传递给存储过程?
例如:
create procedure test
@tablename char(10)
as
begin
select * from @tablename
end
go
我知道这行不通。那么如果我想将表名传递到存储过程中,最好的方法是什么?
非常感谢
【问题讨论】:
最安全的方法是通过视图。
创建一个视图,它将您可能希望访问的所有表联合起来(并且这些表必须具有相同的列结构),并在行前加上表名。
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 创建和执行更安全。
【讨论】:
您需要使用动态 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)
你需要非常小心这种方法,确保你没有打开一罐安全蠕虫。
我的另一个顾虑是您可能正在尝试创建通用数据访问存储过程,这通常是个坏主意。显然我不知道你的用例。
【讨论】:
DECLARE @Name VARCHAR(50)
SET @Name='Company'
EXEC('SELECT * from ' + @Name )
使用这种方式从数据库中获取记录。
【讨论】: