3

SELECT1行を出力するステートメントを含むストアドプロシージャがあります。これは次のようなものです。

CREATE PROCEDURE [dbo].[CreateCustomer]
...

INSERT INTO Customers values(, , , ,)
SELECT CustomerID, FirstName, LastNam.....
INSERT Roles values(, , , .....

これにより、新しく保存された値がCustomersテーブルから選択されます。2番目の挿入では、new CustomerIDを使用して新しい行をRolesテーブルに挿入します。

customerIDCustomerIDを再度クエリせずに、上記のselectステートメントからを取得する方法はありますか?

私は変数を宣言して、次のようにしようとしました:

SELECT takenCustomerID = CustomerID, FirstName, LastNam....(rest of query statement)

しかし、私はすべての変数を宣言し、次のようにする必要があります。

SELECT takenCustomerID, takenFirstName, takenLastNa... = CustomerID, FirstName, LastNam... (rest of query statement)

しかし、これはサーバー側で多くのメモリを浪費するので悪いことだと思います。

それで、TEMP( "customerID")を呼び出してその値を取得できる組み込みのTEMPのような変数など、selectステートメントですべての変数を宣言せずに個々の値をすぐに取得する簡単な方法はありますか?

また、ストアドプロシージャに複数のSELECTステートメントを含めることはできますか?必要なselectステートメントからselect値を取得するにはどうすればよいですか?

私はすでに価値を得る方法を知っているので、好奇心からもっと多くを求めています。もっとエレガントな方法があるかどうか知りたいだけです。

4

2 に答える 2

2

手動でテーブルにリダイレクトしない限りSELECT、出力ストリームにのみ送信されるため、前の選択から自動的に値にアクセスすることはできません。

あなたはただ探しているかもしれませんSCOPE_IDENTITY()

declare @id int

insert ....
values (...)

set @id = SCOPE_IDENTITY()

DML の一般的なケースでは、もう 1 つの候補はOUTPUTclauseです。

既存の選択に基づくより一般的な複合選択については、テーブル変数が役立つ場合があります。

declare @foo table (id int not null, name nvarchar(100) not null) // etc

insert @foo (id, name)
select id, name from Foo where ...

select * from @foo // for output

// but we still have the @foo data available for subsequent query

... // more TSQL here

複数の select ステートメントを使用する場合、使用している API に完全に依存します。ただし、ここでの未加工の ADO.NET API はIDataReaderであり、NextResult()メソッドがあります。マルチグリッドの一般的な使用法は次のとおりです。

using(var reader = cmd.ExecuteReader()) {
    do {
        while(reader.Read()) {
          // i.e. for each row in this grid
          ...
        }
    } while (reader.NextResult()); // <== for each grid
}

while(...) {...}とここの違いは、最初のグリッドから自動的にdo {...} while(...)開始するためですが、そのグリッドの最初のに手動で進む必要があることに注意してください。

于 2012-07-30T06:38:58.240 に答える
2

挿入された値へのアクセス

簡単です。OUTPUT句を使用して、作成したばかりの値を返します。

DECLARE @Customers TABLE (
   CustomerID uniqueidentifier,
   FirstName varchar(100),
   LastName varchar(100)
);

INSERT dbo.Customers 
OUTPUT Inserted.*
INTO @Customers
SELECT newsequentialid(), @FirstName, @LastName, ...;
-- now you have all the values of the new row in the `@Customers` table variable.

次に、これを行うことができます:

INSERT dbo.Roles
SELECT
   CustomerID,
   @OtherValue,
   @AnotherValue,
   AnyotherColumnFrom@Customers
FROM @Customers;

挿入された Customer 行の値をそれ以上使用しない場合は、テーブル変数を廃止して、Roles テーブルに直接 OUTPUT することもできます。これは、そこに入るすべての値が変数からのものであると仮定した場合です。

このOUTPUT句は、特別な meta-table を使用して、挿入された値へのアクセスを提供しますInserted。ただし、変数と式を定数と共に使用することもできます。

この方法を使用する利点は、挿入された多数の行を一度に処理できることです。挿入する行が 1 行だけで、必要なのはCustomerIDその後だけで、それを複数回使用する必要がある場合は、代わりに次のようにします。

DECLARE @CustomerID uniqueidentifier = newsequentialid();
INSERT @Customer VALUES (@CustomerID, ...);
INSERT @Roles VALUES (..., @CustomerID ...);

事前に GUID を作成することで、テーブルから戻す必要がなくなります。ちなみに、クラスター化されたインデックスの場合newsequentialid()よりもおそらく優れてnewid()います(おそらくそうです)newid。原因となるページ分割を回避できるからです。

複数の結果セットを返す

これは常に可能です。クエリに使用する手段には、データ アクセス オブジェクトを次のレコードセットに進めるメソッドがあります。を使用している場合は、メソッドDataReaderを調べてください。NextResult従来の ADO では、レコードセットにNextRecordsetメソッドがあります。

于 2012-07-30T06:48:40.943 に答える