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」は
にあるように「SQL Server 6.5までの書式で、SQL Server 7.0 以降は “SET @hoge=” の書き方を推奨」されているようです。
でもどちらも使える状態にあるということです。
「SELECT」と「SET」の違い
で、まったく「SELECT」と「SET」が同じかというとそうではなく、「SELECT」と「SET」では少しだけ違いがあります。
- SETは一度に1つの変数しか代入できないが、SELECTは一度に複数の代入を行うことができる
- 値を返さないクエリから代入すると、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 Serverで変数を代入する場合には「SELECT」「SET」のどちらでもできますが、それぞれに少しだけ違いがあります。
その違いを理解したうえで使用しないと、思わぬ不具合を発生させることにも成り兼ねないので注意しましょう。
以上、SQL ServerのSELECTとSETで変数代入時の違いでした。