SQL Server SELECT INTO @variable?

250

Ich habe den folgenden Code in einem meiner gespeicherten SQL (2008) -Prozesse, der einwandfrei ausgeführt wird:

    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

Die Frage für euch ist also, ob es eine Möglichkeit gibt, etwas in der Art von:

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

Damit ich diese Daten aus dem Speicher in anderen folgenden Anweisungen wiederverwenden kann? SQL Server löst eine Anpassung mit der obigen Anweisung aus, ich möchte jedoch keine separaten Variablen erstellen und jede einzelne über eine separate SELECT-Anweisung für dieselbe Tabelle initialisieren müssen .... UGH !!!

Irgendwelche Vorschläge, wie Sie etwas in dieser Richtung erreichen können, ohne mehrere Abfragen für dieselbe Tabelle durchzuführen?

bleepzter
quelle
1
"um separate Variablen zu erstellen und jede einzelne über eine separate SELECT-Anweisung zu initialisieren" - warum sollten Sie das tun müssen? declare @t tableeinmal, und wenn Sie es wiederverwenden müssen, feuern Sie ein, DELETE @TempCustomerbevor Sie es wieder einsetzen
RichardTheKiwi

Antworten:

204

Sie können nicht .. IN .. eine TABELLE VARIABLE AUSWÄHLEN. Das Beste, was Sie tun können, ist, es zuerst zu erstellen und dann einzufügen. Dein 2. Snippet muss sein

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
quelle
5
Sollte beachten, dass dies auch in einem CTE-Kontext gut funktioniert. Bazinga!
Michael Krauklis
4
Hat jemand eine Antwort darauf, warum man nicht wie bei einer tatsächlichen temporären Tabelle eine Tabellenvariable auswählen kann?
KSwift87
504

Wenn Sie einfach einige Variablen für die spätere Verwendung zuweisen möchten, können Sie sie auf einmal mit etwas in dieser Richtung ausführen:

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

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

Wenn das die Art von Dingen ist, nach denen Sie suchen

Dougajmcdonald
quelle
1
Beste Antwort imho, aber was passiert, wenn die Ergebnisse mehr als eins sind?
capitano666
Wenn die Ergebnisse mehr als eins sind, erhalten Sie einen der verfügbaren Werte. Das könnte zu einem interessanten Rätsel führen! Siehe mssqltips.com/sqlservertip/1888/…
Smandoli
8
Um die Abfrage zu zwingen, eine einzelne Zeile zurückzugeben, verwenden Sie SELECT TOP 1
Adrian
1
@Adrian Ja, bei der obigen Abfrage wird davon ausgegangen, dass Sie eine einzelne Zeile ausgewählt haben. Sie können auch Ordnungs- und Aggregatfunktionen verwenden, wenn Sie eine ausgefallenere Logik wünschen.
Dougajmcdonald
1
Falls Sie nicht den Datenbanktyp verwenden, den das OP verwendet, unterstützen nicht alle TOP 1, wie Adrian erwähnt hat. SQL Server / MS Access verwenden TOP, MySQL verwendet LIMIT und Oracle verwendet ROWNUM. Weitere Informationen finden Sie unter w3schools.com/sql/sql_top.asp .
Tyler
33

du kannst das:

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

dann später

SELECT CustomerId FROM #tempCustomer

Sie müssen die Struktur von #tempCustomer nicht deklarieren

Victor Ribeiro da Silva Eloy
quelle
3
@webturner Keiner dieser Punkte ist wahr. Temp-Tabellen sind nicht außerhalb des Prozesses gültig und Tabellenvariablen sind nicht mehr "nur Speicher" als temporäre Tabellen.
Martin Smith
7
Vergessen Sie nicht, ein DROP TABLE #tempCustomerWann hinzuzufügen, #tempCustomerdas nicht mehr benötigt wird, da sonst die nächste Auswahl einen #tempCustomer already existsFehler verursacht
ViRuSTriNiTy
15

Es sieht so aus, als ob Ihre Syntax etwas falsch ist. Dies hat einige gute Beispiele

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

Dann später

SELECT CustomerId FROM @TempCustomer
Pat L.
quelle
2

Klingt so, als ob Sie temporäre Tabellen möchten. http://www.sqlteam.com/article/temporary-tables

Beachten Sie, dass #TempTable in Ihrem SP verfügbar ist.

Beachten Sie, dass die ## TempTable für alle verfügbar ist.

Valamas
quelle
2
## verlockend - bis der Besitzer (Schöpfer) es löscht oder getrennt wird
RichardTheKiwi
4
Ich möchte keine temporären Tabellen. Temp-Tische sind teuer und langsam. Ich möchte nur ein wenig Daten für einen bestimmten Datensatz für eine kurze Zeit aufbewahren und sie mehreren SQL-Anweisungen ohne nachfolgende Suchvorgänge zur Verfügung stellen. Da Tabellenvariablen innerhalb des gespeicherten Prozesses, in dem sie definiert wurden, einen Gültigkeitsbereich haben, sind sie die perfekte Lösung zum Speichern von Daten für diesen einen gespeicherten
Prozessaufruf
3
Ich habe auch vergessen zu erwähnen, dass sich die Datenbank in Azure befindet. Ich möchte kein Durcheinander bei der Verwaltung von temporären Tabellen verursachen.
Bleepzter
Variable Tabelle ist der richtige Weg. deklarieren Sie @varTable Table (....)
ARLibertarian
1

Ich fand Ihre Frage auf der Suche nach einer Lösung für das gleiche Problem. und was andere Antworten nicht zeigen, ist eine Möglichkeit, eine Variable zu verwenden, um den Namen der Tabelle für jede Ausführung Ihrer Prozedur in einer permanenten Form zu ändern, nicht in einer temporären.

Bisher verkette ich den gesamten SQL-Code mit den zu verwendenden Variablen. So was:

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

Ich hoffe, es hilft, aber es könnte umständlich sein, wenn der Code zu groß ist. Wenn Sie also einen besseren Weg gefunden haben, teilen Sie ihn bitte mit!

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

@tempCustomerDies bedeutet, dass eine neue Tabellenvariable erstellt und Daten vom Kunden eingefügt werden. Sie hatten es bereits oben deklariert, sodass Sie es nicht erneut deklarieren müssen. Besser mit zu gehen

INSERT INTO @tempCustomer SELECT * FROM Customer
Koushik Veldanda
quelle
4
Es funktioniert nicht. Sie müssen die Tabellenvariable noch vorher deklarieren.
Johan Boulé