回答:
- SETは変数代入のANSI標準ですが、SELECTはそうではありません。
- SETは一度に1つの変数のみを割り当てることができ、SELECTは一度に複数の割り当てを行うことができます。
- クエリから割り当てる場合、SETはスカラー値のみを割り当てることができます。クエリが複数の値/行を返す場合、SETはエラーを発生させます。SELECTは値の1つを変数に割り当て、複数の値が返されたという事実を隠します(そのため、他の場所で問題が発生した理由がわからない可能性があります。そのトラブルシューティングを楽しんでください)。
- クエリから代入するときに値が返されない場合、SETはNULLを代入します。SELECTは代入をまったく行いません(そのため、変数は以前の値から変更されません)。
- 速度の違いに関する限り-SETとSELECTの間に直接的な違いはありません。ただし、1つのショットで複数の割り当てを行うSELECTの機能は、SETよりも速度がわずかに優れています。
SELECT @Int = @Int + 1, @Int = @Int + 1
、@Int
0から開始すると、2で終了します。これは、連続する文字列操作を行うときに非常に役立ちます。
私SET
はANSI標準だと思いますが、そうでSELECT
はありません。また、値が見つからない場合の以下の例のSET
vs. の異なる動作にも注意してくださいSELECT
。
declare @var varchar(20)
set @var = 'Joe'
set @var = (select name from master.sys.tables where name = 'qwerty')
select @var /* @var is now NULL */
set @var = 'Joe'
select @var = name from master.sys.tables where name = 'qwerty'
select @var /* @var is still equal to 'Joe' */
select @var = (select name from master.sys.tables where name = 'qwerty')
場合、@ varはnullになります。あなたが与えている例は同じクエリではありません。
(select name from master.sys.tables where name = 'qwerty')
一つのために、そしてもう一つのname from master.sys.tables where name = 'qwerty'
ために...あなたはそれを見ませんか?
(select name from master.sys.tables where name = 'qwerty')
スカラーサブクエリでありname from master.sys.tables where name = 'qwerty'
、単純なクエリです。2つの異なる式が同じ結果を生成することは想定されていませんが、そうする必要があることを示唆しているようです。あなたが言おうとしている場合SET
とSELECT
、キーワードが異なる実装を持って、次の2つの異なる使用すべきでない表現を、あなたの例で。msdn.microsoft.com/en-us/library/ms187330.aspx
クエリを作成するときは、この違いに注意する必要があります。
DECLARE @A INT = 2
SELECT @A = TBL.A
FROM ( SELECT 1 A ) TBL
WHERE 1 = 2
SELECT @A
/* @A is 2*/
---------------------------------------------------------------
DECLARE @A INT = 2
SET @A = (
SELECT TBL.A
FROM ( SELECT 1 A) TBL
WHERE 1 = 2
)
SELECT @A
/* @A is null*/
ANSIや速度などは別として、私にとって常に重要な非常に重要な違いがあります。ANSIおよび速度以上。この重要な見落としのために修正したバグの数は多いです。私は常にコードレビュー中にこれを探します。
-- Arrange
create table Employee (EmployeeId int);
insert into dbo.Employee values (1);
insert into dbo.Employee values (2);
insert into dbo.Employee values (3);
-- Act
declare @employeeId int;
select @employeeId = e.EmployeeId from dbo.Employee e;
-- Assert
-- This will print 3, the last EmployeeId from the query (an arbitrary value)
-- Almost always, this is not what the developer was intending.
print @employeeId;
ほとんどの場合、それは開発者が意図していることではありません。上記では、クエリは単純明快ですが、クエリが非常に複雑で、単一の値を返すかどうかを判断するのは簡単ではありません。多くの場合、クエリはこれよりも複雑で、たまたま単一の値を返していました。開発者のテスト中は問題ありません。しかし、これはカチカチ音をたてる爆弾のようなもので、クエリが複数の結果を返すときに問題を引き起こします。どうして?変数に最後の値を代入するだけだからです。
今度は同じことを試してみましょうSET
:
-- Act
set @employeeId = (select e.EmployeeId from dbo.Employee e);
エラーが表示されます。
サブクエリが複数の値を返しました。これは、サブクエリが=、!=、<、<=、>、> =の後に続く場合、またはサブクエリが式として使用される場合は許可されません。
これは驚くべきことであり、非常に重要です。なぜなら、些細な「結果の最後の項目」をに割り当てたいのはなぜですか@employeeId
。とselect
、あなたはすべてのエラーを得ることはありません、あなたは時間がデバッグ、数分を過ごすことになります。
おそらく、単一のIDを探しているため、SET
クエリを修正する必要があります。したがって、次のようなことができます。
-- Act
-- Notice the where clause
set @employeeId = (select e.EmployeeId from dbo.Employee e where e.EmployeeId = 1);
print @employeeId;
掃除
drop table Employee;
結論として、以下を使用します。
SET
:単一の値を変数に割り当てたい場合、その変数は単一の値用です。SELECT
:複数の値を変数に割り当てたい場合。変数は、テーブル、一時テーブル、テーブル変数などです。