如何执行引用表变量的SQL String?

tle*_*man 15 sql sql-server

我在SQL Server 2008中有一个表变量

    DECLARE @specsAndModel TABLE
    (
        specName VARCHAR(50)
        ,specVal VARCHAR(50)
    )
    INSERT INTO @specsAndModel
    VALUES('[modelNumber]', 'F00-B4R')
Run Code Online (Sandbox Code Playgroud)

然后,我稍后构建一个名为的字符串@query,我最终尝试将其传入EXECUTE,如下例所示:

    DECLARE @query NVARCHAR(MAX);
    SET @query = 'SELECT specName, specVal FROM @specsAndModel'
    EXECUTE(@query)
Run Code Online (Sandbox Code Playgroud)

但是,SQL Server给我错误消息: Must declare the table variable "@specsAndModel".

搜索后,我认为这可能与执行上下文有关,但我无法解决问题.

我是否可以在对execute函数的调用中使用表变量?

Tar*_*ryn 16

您正在创建的表是一个表变量,在其初始范围之外不可用.有几种方法可以解决这个问题:

创建全局临时表(免责声明:如果有多个用户同时尝试运行此操作,则可能会导致问题.):

create table  ##specsAndModel 
(
    specName VARCHAR(50)
    ,specVal VARCHAR(50)
)
INSERT INTO ##specsAndModel
VALUES('[modelNumber]', 'F00-B4R')

DECLARE @query NVARCHAR(MAX);
SET @query = 'SELECT specName, specVal FROM ##specsAndModel'
EXECUTE(@query)
Run Code Online (Sandbox Code Playgroud)

创建本地临时表而不是全局:

create table  #specsAndModel 
(
    specName VARCHAR(50)
    ,specVal VARCHAR(50)
)
INSERT INTO #specsAndModel
VALUES('[modelNumber]', 'F00-B4R')

DECLARE @query NVARCHAR(MAX);
SET @query = 'SELECT specName, specVal FROM #specsAndModel'
EXECUTE(@query)
Run Code Online (Sandbox Code Playgroud)

在动态SQL内部执行create table(丑陋):

DECLARE @query NVARCHAR(MAX);
SET @query = 'DECLARE @specsAndModel TABLE
(
    specName VARCHAR(50)
    ,specVal VARCHAR(50)
)
INSERT INTO @specsAndModel
VALUES(''[modelNumber]'', ''F00-B4R'')
SELECT specName, specVal FROM @specsAndModel'
exec(@query)
Run Code Online (Sandbox Code Playgroud)

而不是使用临时表,创建一个实际的表,然后在完成时将其删除 (免责声明:如果多一个用户同时尝试运行它,这可能会导致问题.):

create TABLE specsAndModel 
(
    specName VARCHAR(50)
    ,specVal VARCHAR(50)
)
INSERT INTO specsAndModel
VALUES('[modelNumber]', 'F00-B4R')

DECLARE @query NVARCHAR(MAX);
SET @query = 'SELECT specName, specVal FROM specsAndModel'
EXECUTE(@query)  

drop table specsAndModel
Run Code Online (Sandbox Code Playgroud)

以下是关于临时表和表变量的讨论的链接:

我应该使用#temp表还是@table变量?

编辑:您可以使用sp_executesql以下方法传入表变量:

create type specsAndModel as table (
    specName VARCHAR(50)
    ,specVal VARCHAR(50)
 )
go
declare @t specsAndModel
insert @t VALUES('[modelNumber]', 'F00-B4R')

exec sp_executesql N'select specName, specVal from @var', N'@var specsAndModel readonly', @t
Run Code Online (Sandbox Code Playgroud)

使用全局##临时表和永久表运行风险,如果多个用户尝试运行该进程,则可能存在冲突.

使用本地#temp表或使用表变量传递更安全sp_executesql.