Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 在select子句中使用变量名,需要它们的行为类似于列名-SQLServer_Sql Server - Fatal编程技术网

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'