SQL Server ВЫБРАТЬ В @ переменную?

250

У меня есть следующий код в одном из моих сохраненных Proq Sql (2008), который прекрасно работает:

    CREATE PROCEDURE [dbo].[Item_AddItem]
        @CustomerId uniqueidentifier,
        @Description nvarchar(100),
        @Type int,
        @Username nvarchar(100),
    AS
    BEGIN

        DECLARE @TopRelatedItemId uniqueidentifier;
        SET @TopRelatedItemId = 
        (
           SELECT top(1) RelatedItemId 
           FROM RelatedItems 
           WHERE CustomerId = @CustomerId
        ) 

        DECLARE @TempItem TABLE
        (
            ItemId uniqueidentifier,
            CustomerId uniqueidentifier,
            Description nvarchar(100),
            Type int,
            Username nvarchar(100),
            TimeStamp datetime
        );

        INSERT INTO Item
        OUTPUT INSERTED.* INTO @TempItem
        SELECT NEWID(), @CustomerId, @Description, @Type, @Username, GETDATE()

        SELECT
            ItemId,
            CustomerId,
            @TopRelatedItemId,
            Description,
            Type,
            Username,
            TimeStamp
        FROM
            @TempItem
END
GO

Итак, вопрос для вас, ребята, есть ли возможность сделать что-то вроде:

DECLARE @TempCustomer TABLE
(
   CustomerId uniqueidentifier,
   FirstName nvarchar(100),
   LastName nvarchar(100),
   Email nvarchar(100)
);
SELECT 
    CustomerId, 
    FirstName, 
    LastName, 
    Email 
INTO 
    @TempCustomer 
FROM 
    Customer
WHERE 
    CustomerId = @CustomerId

Чтобы я мог повторно использовать эти данные из памяти в других следующих утверждениях? SQL Server подгоняет вышеприведенный оператор, однако я не хочу создавать отдельные переменные и инициализировать каждую из них с помощью отдельного оператора SELECT для той же таблицы .... UGH !!!

Любые предложения о том, как добиться чего-то в этом направлении без нескольких запросов к одной и той же таблице?

bleepzter
источник
1
«создать отдельные переменные и инициализировать каждую из них с помощью отдельного оператора SELECT» - зачем вам это нужно? declare @t tableодин раз, и если вам нужно использовать его повторно, выстрелите DELETE @TempCustomerперед тем, как вставлять в него снова
RichardTheKiwi

Ответы:

205

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

DECLARE @TempCustomer TABLE
(
   CustomerId uniqueidentifier,
   FirstName nvarchar(100),
   LastName nvarchar(100),
   Email nvarchar(100)
);
INSERT INTO 
    @TempCustomer 
SELECT 
    CustomerId, 
    FirstName, 
    LastName, 
    Email 
FROM 
    Customer
WHERE 
    CustomerId = @CustomerId
RichardTheKiwi
источник
5
Следует отметить, что это прекрасно работает и в контексте CTE. Bazinga!
Майкл Крауклис
4
У кого-нибудь есть ответ на вопрос, почему нельзя выбрать переменную таблицы, как вы можете с реальной временной таблицей?
KSwift87
505

Если вы хотите просто назначить некоторые переменные для последующего использования, вы можете сделать их за один раз с чем-то вроде этого:

declare @var1 int,@var2 int,@var3 int;

select 
    @var1 = field1,
    @var2 = field2,
    @var3 = field3
from
    table
where
    condition

Если это то, что вы ищете

dougajmcdonald
источник
1
Лучший ответ imho, но что произойдет, если результаты будут более одного?
capitano666
Если результатов более одного, вы получите одно из доступных значений. Это может сделать интересную загадку! См. Mssqltips.com/sqlservertip/1888/…
Smandoli
8
Чтобы заставить запрос вернуть одну строку, используйте SELECT TOP 1
Adrian
1
@Adrian Да, в приведенном выше запросе предполагается, что вы выбрали одну строку. Вы также можете использовать функции упорядочения и агрегирования, если вам нужна более изощренная логика.
Дугаймкдональд
1
В случае, если вы не используете тип базы данных, который использует OP, не все поддерживают TOP 1, как упоминал Адриан. SQL Server / MS Access используют TOP, MySQL использует LIMIT, а Oracle использует ROWNUM. Смотрите w3schools.com/sql/sql_top.asp для получения дополнительной информации.
Тайлер
33

ты можешь сделать это:

SELECT 
    CustomerId, 
    FirstName, 
    LastName, 
    Email
INTO #tempCustomer 
FROM 
    Customer
WHERE 
    CustomerId = @CustomerId

тогда позже

SELECT CustomerId FROM #tempCustomer

вам не нужно объявлять структуру #tempCustomer

Виктор Рибейру да Силва Элой
источник
3
@webturner Ни один из этих пунктов не соответствует действительности. Временные таблицы не ограничиваются пределами proc, и переменные таблиц больше не являются «только памятью», чем временные таблицы.
Мартин Смит,
7
Не забудьте добавить, DROP TABLE #tempCustomerкогда #tempCustomerбольше не нужно, иначе следующий выбор вызовет #tempCustomer already existsошибку
ViRuSTriNiTy
15

Похоже, ваш синтаксис немного отсутствует. Это имеет несколько хороших примеров

DECLARE @TempCustomer TABLE
(
   CustomerId uniqueidentifier,
   FirstName nvarchar(100),
   LastName nvarchar(100),
   Email nvarchar(100)
);
INSERT @TempCustomer 
SELECT 
    CustomerId, 
    FirstName, 
    LastName, 
    Email 
FROM 
    Customer
WHERE 
    CustomerId = @CustomerId

Тогда позже

SELECT CustomerId FROM @TempCustomer
Пэт Л
источник
2

Похоже, вы хотите временные таблицы. http://www.sqlteam.com/article/temporary-tables

Обратите внимание, что #TempTable доступен для всего вашего SP.

Обратите внимание, что ## TempTable доступен для всех.

Valamas
источник
2
## temptable - пока владелец (создатель) не удалит его или не отключится
RichardTheKiwi
4
Я не хочу временных таблиц. Временные столы дороги и медленны. Я просто хочу сохранить немного данных для конкретной записи в течение небольшого промежутка времени и сделать ее доступной для нескольких операторов SQL без последующих поисков. Так как переменные таблицы имеют область действия в хранимом процессе, в котором они были определены, они являются идеальным решением для хранения потерянных данных для этого одного вызова
хранимого процесса
3
Я также забыл упомянуть, что БД находится в Azure .... Я не хочу вводить беспорядок в управление временными таблицами.
bleepzter
Переменная таблица это путь. объявить @varTable Table (....)
ARLibertarian
1

Я нашел ваш вопрос в поисках решения той же проблемы; и что другие ответы не указывают, это способ использовать переменную для изменения имени таблицы при каждом выполнении вашей процедуры в постоянной форме, а не во временной.

Пока что я объединяю весь код SQL с используемыми переменными. Как это:

declare @table_name as varchar(30)
select @table_name = CONVERT(varchar(30), getdate(), 112)
set @table_name = 'DAILY_SNAPSHOT_' + @table_name

EXEC('
        SELECT var1, var2, var3
        INTO '+@table_name+'
        FROM my_view
        WHERE string = ''Strings must use double apostrophe''
    ');

Я надеюсь, что это поможет, но это может быть громоздко, если код слишком велик, поэтому, если вы нашли лучший способ, пожалуйста, поделитесь!

Родриго
источник
-2
"SELECT *
  INTO 
    @TempCustomer 
FROM 
    Customer
WHERE 
    CustomerId = @CustomerId"

Что означает создание новой @tempCustomerпеременной таблицы и вставку данных из клиента. Вы уже заявили об этом выше, так что нет необходимости снова объявлять. Лучше пойти с

INSERT INTO @tempCustomer SELECT * FROM Customer
кошик велданда
источник
4
Это не работает Вам все еще нужно объявить переменную таблицы заранее.
Йохан Буле