SQL ServerのSELECTとSETで変数代入時の違い

SQL ServerのT-SQLでは変数に値を設定する場合に「SELECT」と「SET」で行うことができます。

この2つは同じようで、少しだけ違いがあります。

その違いを間違えると、見つけにくい不具合が発生することもあるので注意が必要です。

スポンサーリンク

SELECT、SETで変数に代入する時の違いと注意事項

SQL ServerのT-SQLにある「SELECT」と「SET」はどちらも宣言した変数に値をセットするという機能を持っています。

DECLARE    @val int = 10
SELECT @val = 100
PRINT @val

SET @val = 200
PRINT @val

このSQLを実行すると

100
200

と表示されます。

思った通りに変数に値がセットされます。

なぜ「SELECT」と「SET」2つあるのか?

ではなぜ「SELECT」と「SET」のように同じような機能が2つ存在しているのでしょう。

その答えは「SELECT」は

SETとSELECTの違い(Transact-SQL)
お世話になります。初歩的な質問で申し訳ありません。T-SQLで、変数 @Str に値を代入する場合、DECLARE @Str VARCHAR(100)SET @Str = 'TEST' -- (1)SELECT @Str 'TEST' -- (2)(1)と(2)の二通り書けるみたいで... - SQL Serv...

にあるように「SQL Server 6.5までの書式で、SQL Server 7.0 以降は “SET @hoge=” の書き方を推奨」されているようです。

でもどちらも使える状態にあるということです。

「SELECT」と「SET」の違い

で、まったく「SELECT」と「SET」が同じかというとそうではなく、「SELECT」と「SET」では少しだけ違いがあります。

「SELECT」と「SET」の注意すべき違い

  1. SETは一度に1つの変数しか代入できないが、SELECTは一度に複数の代入を行うことができる
  2. 値を返さないクエリから代入すると、SETはNULLを代入するがSELECTは代入をまったく行わない

一度に複数の代入を行う

「SELECT」は1回の発行で複数の値を設定することができます。

DECLARE    @val1 int = 10
DECLARE    @val2 int = 20

--これはOK!!
SELECT @val1 = 200 , @val2 = 300

--これはError!!
SET @val1 = 200 , @val2 = 300

上記を実行するとSETの箇所でエラーが発生します。

値を返さないクエリからの代入

値を返さないクエリから代入を実行すると、SELECTとSETではまったく異なる動作をします。

まずはSELECT。

--SELECTで値を返さないクエリからの結果代入
DECLARE @val1 INT = 100

SELECT  @val1 = TBL.val
FROM    ( SELECT 1 AS val ) TBL
WHERE   1 = 2

SELECT  @val1

TBLは条件(WHERE句)に合致するレコードにならないので、結果は値を返しません。

それをSELECTで値を代入すると

(列名なし)
100

になり、もとの「100」のままです

次に「SET」で同様のSQLを実行します。

--SETで値を返さないクエリからの結果代入
DECLARE @val2 INT = 200

SET @val2 = ( 
            SELECT  TBL.val
            FROM    ( SELECT 1 AS  val) TBL
            WHERE   1 = 2
         )

SELECT  @val2

結果は

(列名なし)
NULL

になり、なんとNULLが代入されました

sql — 変数割り当て時のSETとSELECTの違い
T-SQLで変数を代入するときのSETステートメントとSELECTステートメントの違いは何ですか?...
この動作は「SELECT」と「SET」で値を代入する時の大きな違いです。

まとめ

SQL Serverで変数を代入する場合には「SELECT」「SET」のどちらでもできますが、それぞれに少しだけ違いがあります。

その違いを理解したうえで使用しないと、思わぬ不具合を発生させることにも成り兼ねないので注意しましょう。

以上、SQL ServerのSELECTとSETで変数代入時の違いでした。

タイトルとURLをコピーしました