SQL Server SELECT INTO @variable?


250

私のSql(2008)Stored Procsの1つに次のコードがあり、完全に正常に実行されます。

    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ステートメントを介してそれぞれを初期化する必要はありません。

同じテーブルに対して複数のクエリを実行せずに、行に沿って何かを達成する方法に関する提案はありますか?


1
「個別の変数を作成し、それぞれを個別のSELECTステートメントを介して初期化するには」-なぜそれを行う必要があるのですか?declare @t table一度、そしてそれを再利用する必要がある場合は、DELETE @TempCustomer再度挿入する前に発射してください
RichardTheKiwi

回答:


204

.. INTO .. TABLE VARIABLEは選択できません。最善の方法は、まず作成してから挿入することです。2番目のスニペットは

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
これは、CTEのコンテキストでも問題なく機能することに注意してください。バジンガ!
Michael Krauklis、2011

4
実際の一時テーブルでできるように、なぜテーブル変数に選択できないのかについての答えは誰にもありますか?
KSwift87 2016年

504

後で使用するためにいくつかの変数を割り当てるだけの場合は、これらの線に沿って何かを一度に実行できます。

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

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

それがあなたが望んでいるタイプの場合


1
ベストアンサーimhoですが、結果が複数ある場合はどうなりますか?
capitano666 2016

結果が複数の場合、使用可能な値の1つを取得します。それは面白いパズルになるかもしれません!参照 mssqltips.com/sqlservertip/1888/...を
Smandoli

8
クエリが単一行を返すように強制するには、SELECT TOP 1
Adrian

1
@Adrianはい、上記のクエリでは、1つの行を選択したと想定しています。より高度なロジックが必要な場合は、順序付け関数と集計関数を使用することもできます。
dougajmcdonald 2017年

1
OPが使用しているデータベースタイプを使用していない場合、Adrianが述べたようにすべてが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はすべてのユーザーが利用できます。


2
## temptable-所有者(作成者)が削除するか、接続が解除されるまで
RichardTheKiwi

4
一時テーブルは必要ありません。一時テーブルは高価で低速です。特定のレコードのデータを少しの間保持し、その後のルックアップなしで複数のSQLステートメントで使用できるようにしたいだけです。テーブル変数は、それらがで定義されたストアドプロシージャ内のスコープを持っているので、彼らは...その1つのストアドプロシージャ呼び出しのtuppledデータを格納するための完璧なソリューションです
bleepzter

3
また、DBがAzureに常駐していることを忘れていました。一時テーブルの管理を混乱させたくありません。
bleepzter

変数テーブルは、進むべき道です。@varTableテーブル(....)を宣言
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"

つまり、新しい@tempCustomertablevariableを作成し、FROM Customerからデータを挿入します。上ですでに宣言しているので、再度宣言する必要はありません。行く方が良い

INSERT INTO @tempCustomer SELECT * FROM Customer

4
動かない。それでも、事前にテーブル変数を宣言する必要があります。
JohanBoulé16年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.