SQL Server WYBIERAĆ @ zmienną?


250

Mam następujący kod w jednym z moich przechowywanych procesów Sql (2008), który wykonuje się doskonale:

    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

Zatem dla was pytanie brzmi, czy istnieje możliwość zrobienia czegoś w stylu:

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

Żebym mógł ponownie wykorzystać te dane z pamięci w innych poniższych instrukcjach? SQL Server rzuca dopasowanie z powyższą instrukcją, jednak nie chcę tworzyć osobnych zmiennych i inicjować każdej z nich za pomocą osobnej instrukcji SELECT dla tej samej tabeli .... UGH !!!

Jakieś sugestie, jak osiągnąć coś wzdłuż linii bez wielu zapytań do tej samej tabeli?


1
„aby utworzyć osobne zmienne i zainicjować każdą z nich za pomocą osobnej instrukcji SELECT” - dlaczego miałbyś to robić? declare @t tableraz, a jeśli chcesz go ponownie użyć, odpal DELETE @TempCustomerprzed włożeniem go ponownie
RichardTheKiwi

Odpowiedzi:


204

Nie można WYBIERAĆ… DO… ZMIENNEJ TABELI. Najlepsze, co możesz zrobić, to najpierw utworzyć, a następnie wstawić. Twój drugi fragment kodu musi być

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

5
Należy zauważyć, że działa to dobrze również w kontekście CTE. Bazinga!
Michael Krauklis,

4
Czy ktoś ma odpowiedź na pytanie, dlaczego nie można wybrać zmiennej tabeli tak jak w przypadku tabeli tymczasowej?
KSwift87

504

Jeśli chcesz po prostu przypisać niektóre zmienne do późniejszego wykorzystania, możesz to zrobić za jednym razem, używając czegoś wzdłuż tych linii:

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

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

Jeśli tego właśnie szukasz


1
Najlepsza odpowiedź imho, ale co się stanie, jeśli wyniki będą więcej niż jeden?
capitano666

Jeśli wyniki są więcej niż jeden, otrzymasz jedną z dostępnych wartości. To może być interesująca łamigłówka! Zobacz mssqltips.com/sqlservertip/1888/…
Smandoli

8
Aby zmusić zapytanie do zwrócenia jednego wiersza, użyj WYBIERZ TOP 1
Adrian

1
@Adrian Tak, powyższe zapytanie zakłada, że ​​wybrałeś pojedynczy wiersz. Możesz także użyć funkcji porządkowania i agregacji, jeśli chcesz mieć bardziej wymyślną logikę.
dougajmcdonald

1
Jeśli nie używasz typu bazy danych, z którego korzysta OP, nie wszyscy wspierają TOP 1, jak wspomniał Adrian. SQL Server / MS Access używa TOP, MySQL używa LIMIT, a Oracle używa ROWNUM. Aby uzyskać więcej informacji, zobacz w3schools.com/sql/sql_top.asp .
Tyler

33

możesz to zrobić:

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

potem

SELECT CustomerId FROM #tempCustomer

nie musisz deklarować struktury #tempCustomer


3
@webturner Żaden z tych punktów nie jest prawdziwy. Tabele temp nie są wykraczane poza proc, a zmienne tabel nie są bardziej „tylko pamięcią” niż tabele tymczasowe.
Martin Smith

7
Nie zapomnij dodać DROP TABLE #tempCustomer#tempCustomer#tempCustomer already exists
terminu,

15

Wygląda na to, że twoja składnia jest nieco wyłączona. To ma kilka dobrych przykładów

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

Potem

SELECT CustomerId FROM @TempCustomer

2

Wygląda na to, że chcesz mieć tabele tymczasowe. http://www.sqlteam.com/article/temporary-tables

Pamiętaj, że #TempTable jest dostępny w całym twoim SP.

Uwaga: ## TempTable jest dostępny dla wszystkich.


2
## kuszące - dopóki właściciel (twórca) nie usunie go lub nie rozłączy się
RichardTheKiwi

4
Nie chcę tabel tymczasowych. Tabele temperatur są drogie i wolne. Chcę po prostu zachować trochę danych dla określonego rekordu przez krótki czas i udostępnić go wielu instrukcjom SQL bez późniejszych wyszukiwań. Ponieważ zmienne tabelowe mają zakres w przechowywanym proc, w którym zostały zdefiniowane, są one idealnym rozwiązaniem do przechowywania danych krupowanych dla tego jednego zapisanego wywołania proc ...
bleepzter 28.01.11

3
Zapomniałem też wspomnieć, że baza danych znajduje się na platformie Azure .... Nie chcę wprowadzać bałaganu w zarządzaniu tabelami tymczasowymi.
bleepzter 28.01.11

Tabela zmiennych jest właściwą drogą. deklaruj @varTable Table (....)
ARLibertarian

1

Znalazłem twoje pytanie, szukając rozwiązania tego samego problemu; a inne odpowiedzi, których nie można wskazać, to sposób użycia zmiennej do zmiany nazwy tabeli dla każdego wykonania procedury w stałej formie, a nie tymczasowej.

Do tej pory łączę cały kod SQL ze zmiennymi, których należy użyć. Lubię to:

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''
    ');

Mam nadzieję, że to pomoże, ale może być kłopotliwe, jeśli kod jest zbyt duży, więc jeśli znalazłeś lepszy sposób, udostępnij!


-2
"SELECT *
  INTO 
    @TempCustomer 
FROM 
    Customer
WHERE 
    CustomerId = @CustomerId"

Co oznacza utworzenie nowej @tempCustomerzmiennej tabeli i wstawienie danych od klienta. Zadeklarowałeś to już powyżej, więc nie musisz ponownie deklarować. Lepiej iść z

INSERT INTO @tempCustomer SELECT * FROM Customer

4
To nie działa Nadal musisz wcześniej zadeklarować zmienną tabeli.
Johan Boulé,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.