Sql server 在select子句中使用变量名,需要它们的行为类似于列名-SQLServer
我有一张桌子:Sql server 在select子句中使用变量名,需要它们的行为类似于列名-SQLServer,sql-server,Sql Server,我有一张桌子: T (Mon varchar(3)); INSERT INTO T VALUES ('Y'); 案例1: DECLARE @day varchar(3) = 'Mon' SELECT Mon FROM T; --result : Y (no problem) 案例2: DECLARE @day VARCHAR(3) = 'Mon' SELECT @day FROM T; --result : Mon 如果我想在第二种情况下得到结果Y,如何在不完全重新设计解决方案
T (Mon varchar(3));
INSERT INTO T VALUES ('Y');
案例1:
DECLARE @day varchar(3) = 'Mon'
SELECT Mon
FROM T; --result : Y (no problem)
案例2:
DECLARE @day VARCHAR(3) = 'Mon'
SELECT @day
FROM T; --result : Mon
如果我想在第二种情况下得到结果
Y
,如何在不完全重新设计解决方案的情况下获得结果。您可以使用此命令分配此@day变量。
exec('select '+@day+' from #T;')
不要忘记使用“TOP1”来限制只能获取一行数据。
从T中选择top 1@day=Mon
然后您可以在其他查询中使用@day。谢谢您更新您的问题,我很欣赏它的简单性
EXECUTE
/EXEC
是一种创建脚本的简单方法,允许您在变量中分割字符串,并可与VARCHAR
一起使用。请记住,EXEC
和sp_executesql
在运行时之前都不会执行,因此它将无法有效或根本无法利用缓存的查询计划
CREATE TABLE #Example (
Class_Type VARCHAR(2) NOT NULL
, Mary INT NULL
, Harry VARCHAR(100) NULL
, Larry XML NULL
, Sorry NVARCHAR(100) NULL )
INSERT INTO #Example (Class_Type, Mary, Harry, Larry, Sorry)
VALUES ('A', 250, 'Apples', CAST('<List><Class Professor="Harry">1</Class><Books>3</Books></List>' AS XML), N'Angelina')
, ('A', 300, 'Pineapples', CAST('<List><Class Professor="Larry">1</Class><Books>3</Books></List>' AS XML), N'Prince Charles')
, ('B', 15, 'Cucumbers', CAST('<List><Class Professor="Sarry">2</Class><Books>5</Books></List>' AS XML), N'Larry Cable')
GO
sp_executesql
可以说是更好的方法。因为系统过程可以参数化整个语句(不受SQL注入
),所以SQL Server
可以在第二次查询中重用缓存的计划!出于性能、安全、可靠性等原因,它是动态SQL语句的首选方法(如果可能)但是,请注意,传递的所有字符串必须采用UNICODE
格式(NVARCHAR
)
这里我们使用sp_executesql
系统过程
ALTER PROCEDURE dbo.USP_MyQuery (@Column NVARCHAR(255) )
AS
BEGIN
DECLARE @SQL NVARCHAR(100)
SET @SQL = N'SELECT ' + QUOTENAME(@Column) +
' FROM #Example WHERE Class_Type = ''' + 'A' + ''''
SET @Column = RTRIM(LTRIM(@Column))
IF @Column IN (N'Mary', N'Harry', N'Larry', N'Sorry')
BEGIN
EXEC sp_executesql @statement = @SQL
END
ELSE PRINT 'Check your spelling. Input does not match any existing columns'
END
EXEC dbo.USP_MyQuery @Column = 'Mary'
没那么难吧?您可能希望使用更多的测试,并利用诸如REPLACE()
之类的函数,使您的查询不受人为错误的影响
最后,请记住,
QUOTENAME()
会删除系统名称标识符,而将字符串替换为删除器(“[]”
是默认设置)你能使用动态SQL以外的任何替代方法吗?我不能马上想到,如果你对此有任何想法,你能告诉我吗?尽管答案很好,你能保证不使用空格或特殊字符吗?用QUOTENAME(@variable,[])封装变量,使其工作。非常感谢。假设我需要将结果返回到某个变量中,而不直接打印。我怎么做?谢谢。我是通过使用动态sql(仅限sp_executesql)实现的
ALTER PROCEDURE dbo.USP_MyQuery (@Column NVARCHAR(255) )
AS
BEGIN
DECLARE @SQL NVARCHAR(100)
SET @SQL = N'SELECT ' + QUOTENAME(@Column) +
' FROM #Example WHERE Class_Type = ''' + 'A' + ''''
SET @Column = RTRIM(LTRIM(@Column))
IF @Column IN (N'Mary', N'Harry', N'Larry', N'Sorry')
BEGIN
EXEC sp_executesql @statement = @SQL
END
ELSE PRINT 'Check your spelling. Input does not match any existing columns'
END
EXEC dbo.USP_MyQuery @Column = 'Mary'