Как выполнить строку SQL, которая ссылается на переменную таблицы?

У меня есть табличная переменная в SQL Server 2008

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

Затем я позже строю строку под названием @query, которую я в конечном счете пытаюсь передать в EXECUTE, как в следующем примере:

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

Однако SQL Server дает мне сообщение об ошибке: Must declare the table variable "@specsAndModel".

После поиска, я думаю, это может быть связано с контекстом выполнения, но я не смог решить проблему.

Возможно ли вообще использовать табличную переменную в вызове функции execute?

Ответ 1

Создаваемая таблица представляет собой переменную таблицы, которая недоступна вне ее первоначальной области. Есть несколько способов исправить это:

Создайте глобальную таблицу темпа (Отказ от ответственности: это может вызвать проблемы, если больше одного пользователя пытается запустить это одновременно.):

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)

Создайте локальную таблицу темпа вместо глобальной:

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)

Выполнить таблицу создания внутри динамического SQL (уродливого):

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)

Вместо того, чтобы использовать временную таблицу, создайте фактическую таблицу и затем отпустите ее, когда закончите (Отказ от ответственности: это может вызвать проблемы, если больше одного пользователя пытается запустить это одновременно.):

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

Вот ссылка на обсуждение временных таблиц и табличных переменных:

Должен ли я использовать таблицу #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

Используя глобальные таблицы ## temp и постоянную таблицу, запускайте риски в том случае, если несколько пользователей пытаются запустить процесс, могут возникнуть конфликты.

Безопаснее использовать либо локальную таблицу #temp, либо передавать переменную таблицы с помощью sp_executesql.

Ответ 2

Вам также нужно создать переменную таблицы внутри строки.

DECLARE @query NVARCHAR(MAX);
SET @query = 'DECLARE @specsAndModel TABLE  ( specName VARCHAR(50) ,specVal VARCHAR(50))'
SET @Query = @Query + ' INSERT INTO  @specsAndModel VALUES(''modelNumber'',''abcd''); SELECT specName, specVal FROM @specsAndModel'
EXEC (@query)