动态SQL(将表名作为参数传递)

13
我希望编写一个存储过程,它将使用一个参数,这个参数将是表名。
例如:
@tablename << Parameter

SELECT * FROM @tablename

这怎么可能呢?

我写了这个:

set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[GetAllInterviewQuestions]
@Alias varchar = null
AS
BEGIN
Exec('Select * FROM Table as ' @Alias) 
END

但是它说@Alias附近有错误的语法。

5个回答

21

首先,您在字符串中省略了“+”符号。这种做法远非理想,但您可以这样做。

DECLARE @SQL nvarchar(max)
SELECT @SQL = 'SELECT * FROM ' + QuoteName(@Alias)
Exec(@SQL)

我强烈建议重新考虑如何处理这个问题。动态生成SQL往往会导致SQL注入漏洞,同时使SQL Server(和其他DB)更难确定处理查询的最佳方法。如果你有一个可以返回任何表格的存储过程,则实际上从一开始就没有从中获得太多好处,因为它将无法进行太多优化,并且在很大程度上削弱了安全性。


3
您需要这样做: exec('select * from '+@tablename+' where...') 但请确保您充分了解风险,例如SQL注入攻击。通常情况下,如果数据库设计良好,您不应该使用此类方法。

2
最好将表名用方括号括起来,以保护自己免受保留字和/或表名中包含空格的影响。执行('select * from ['+@tablename+'] where...') - George Mastros

2
你是不是想说
Exec('SELECT * FROM ' + @tableName) 

此外,您收到的错误是因为在@Alias之前忘记了一个+

1
通常,需要将表名参数化意味着您应该重新考虑数据库架构。如果您从许多不同的表中提取面试问题,则最好创建一个表,并使用一列来区分以任何方式不同表中的问题。

0

大多数 SQL 的实现不允许您通过参数指定结构元素 - 表名、列名、按列排序等;您必须使用动态 SQL 来参数化查询的这些方面。

然而,查看 SQL,您会发现:

Exec('SELECT * FROM Table AS ' @Alias)

当然,这意味着代码只会从名为“Table”的表中选择,并且您需要将@Alias与其连接起来 - 在许多SQL方言中,连接由“||”表示:
Exec('SELECT * FROM Table AS ' || @Alias)

这个可能仍然不能满足你的需求 - 但是在创建过程时它可能不会生成语法错误(但在运行时可能会生成错误)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接