我想知道为什么我不能像这样使用变量作为列名:
declare @a as varchar;
set @a='TEST'
select @a from x;
谢谢
declare @a as varchar;
set @a='TEST'
select @a from x;
谢谢
你不能这样做是因为在SQL编译时并不知道 @a 的值(假设在实际情况中,@a 是某个参数而不是像你示例中那样硬编码的)。
相反,你可以这样做:
declare @a as varchar;
set @a='TEST'
declare @sql nvarchar(max)
set @sql = 'select [' + replace(@a, '''', '''''') + '] from x'
exec sp_executesql @sql
但要小心,这是一个安全漏洞(SQL注入攻击),如果你不能信任或无法清理@a,则不应该这样做。
因为不允许这样做。
你可以使用动态SQL查询代替:
declare @a as varchar;
set @a='TEST'
exec ('select ' + @a + ' from x')
exec
- 它比 exec sp_executesql
更容易记忆。我总是记得使用这个存储过程时会出现错误,例如“不允许执行此过程”。 - Tomasz Gandor由于列名在SQL语句的编译时而非运行时被解析,因此需要注意。
如果可选择的列不太多,可以考虑使用CASE WHEN语句?
DECLARE @ColName VARCHAR(50) = 'Test1'
SELECT [Foo], [Bar],
CASE
WHEN @ColName = 'Test1' THEN [Test1]
WHEN @ColName = 'Test2' THEN [Test2]
WHEN @ColName = 'Test3' THEN [Test3]
WHEN @ColName = 'Test4' THEN [Test4]
ELSE [TestDefault]
END [TestResult]
FROM [TableName];
这样可以避免使用任何 EXEC 命令。
使用sp_executesql
来实现此功能。
Example
SET @SQLString = N'SELECT *
FROM table1
WHERE timet = @time and items in (@item)';
DECLARE @SQLString nvarchar(500);
DECLARE @ParmDefinition nvarchar(500);
SET @ParmDefinition = N'@time timestamp,
@item varchar(max) ';
EXECUTE sp_executesql
@SQLString
,@ParmDefinition
,@time = '2010-04-26 17:15:05.667'
,@item = '''Item1'',''Item2'',''Item3'',''Item4'''
;