SQL Server - 条件分岐

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動

概要

SQL ServerのTransact-SQLで条件分岐(IF ~ ELSE)を実装する方法を記載する。

また、IF文を記述すれば、WHERE句の内容を変えて検索できるが、
条件ごとに同じようなSQL文を複数記述するのは面倒なので、1行で分岐できるIIF文を記載する。


IF文

以下に、IF文のシンタックスを示す。

<処理>が複数行ある場合は、BEGINENDが必要となる。
<条件>が合致する場合、配下の処理が実行されて、IF文の処理は終了する。
<条件>が合致しない場合、配下の処理は実行されず、ELSE IF文またはELSE文に進む。

 IF <条件> 
    BEGIN
       <処理>
    END
 ELSE IF <条件>
    BEGIN
     <処理>
    END
 ELSE
    BEGIN
     <処理>
    END


以下の例では、6行目で値を代入した変数により、条件分岐している。
また、IF文の条件式に丸括弧()を付けることができる。

 CREATE PROCEDURE dbo.TEST1
 AS
 BEGIN
    DECLARE @num1 INT
    DECLARE @msg1 VARCHAR(20)
    SET @num1 = 11
 
    IF (@num1 = 0)
       BEGIN
          SET @msg1 = '0です'
       END
    ELSE IF  @num1 = 1
       BEGIN
          SET @msg1 = '1です'
       END
    ELSE
       BEGIN
          SET @msg1 = 'その他'
       END
 
    PRINT @msg1 --1です
 END


また、IF文をネストすることもできる。

 CREATE PROCEDURE dbo.TEST1
 AS
 BEGIN
    DECLARE @num1 INT
    DECLARE @num2 INT
    DECLARE @msg1 VARCHAR(20)
    SET @num1 = 1
    SET @num2 = 1
 
    IF (@num1 = 1)
       BEGIN
          IF (@num2 = 1)
             BEGIN
                SET @msg1 = '1'
             END
       END
 
    PRINT @msg1 --1
 END



論理演算子の論理積 (AND)

論理積(AND)の左の式と右の式の両方が条件に合致する場合、真(true)となる。

 IF <左の条件式> AND <右の条件式>


 CREATE PROCEDURE dbo.T_TEST
 AS
 BEGIN
    DECLARE @num1 INT
    DECLARE @num2 INT
    DECLARE @msg1 VARCHAR(20)
    SET @num1 = 1
    SET @num2 = 0
 
    IF (@num1 = 1) AND (@num2 = 0)
       BEGIN
          SET @msg1 = 'OK'
       END
    ELSE
       BEGIN
          SET @msg1 = 'NG'
       END
 
    PRINT @msg1 --OKが出力される
 END



論理演算子の論理和 (OR)

論理和(OR)の左の条件式または右の条件式のどちらかが条件に合致する場合、真(true)となる。

 IF <左の条件式> OR <右の条件式>


 CREATE PROCEDURE dbo.T_TEST
 AS
 BEGIN
    DECLARE @num1 INT
    DECLARE @num2 INT
    DECLARE @msg1 VARCHAR(20)
    SET @num1 = 2
    SET @num2 = 0
 
    IF (@num1 = 1) OR (@num2 = 0)
       BEGIN
          SET @msg1 = 'OK'
       END
    ELSE
       BEGIN
          SET @msg1 = 'NG'
       END
 
    PRINT @msg1 --OKが出力される
 END



論理演算子の否定 (NOT)

<条件式>がfalseの場合、真(true)となる。
また、<条件式>がtrueの場合、偽(false)となる。

 IF NOT<条件式>
 -- または
 IF !<条件式>


以下の例では、8行目の条件式によりtrueとなり、それを否定するため、falseとなる。

 CREATE PROCEDURE dbo.T_TEST
 AS
 BEGIN
    DECLARE @num1 INT
    DECLARE @msg1 VARCHAR(20)
    SET @num1 = 9
 
    IF NOT(@num1 = 9)
       BEGIN
          SET @msg1 = 'OK'
       END
    ELSE
       BEGIN
          SET @msg1 = 'NG'
       END
 
    PRINT @msg1 --NGが出力される
 END


以下の例のように、!=演算子を使用しても否定となる。

 IF (@num1 != 9)
    BEGIN
       SET @msg1 = 'OK'
    END
 ELSE
    BEGIN
       SET @msg1 = 'NG'
    END



条件分岐を用いてテーブルを削除する

  • SQLServer 2016以降
テーブル名はスキーマ.テーブル名と指定することもできる。
 DROP TABLE IF EXISTS [テーブル名]


  • SQL Server 2016以前
DROP TABLE IF EXISTS テーブル名が使用できないので、OBJECT_ID()関数を使用してテーブルの存在の有無を確認する。
また、テーブル名は[スキーマ名].[テーブル名]と指定することもできる。
 IF OBJECT_ID(N'テーブル名', N'U') IS NOT NULL
    BEGIN
    DROP TABLE [テーブル名]
    END


一時テーブルも通常のテーブルと同様で、上記の手順で削除することが出来る。
ストアドプロシージャとして実行している場合、実行後に一時テーブルが自動で削除されるが(存在の確認は不要)、コメントアウトしても構わない。
また、コメントアウトしなくても特に問題は無いので、SSMSで操作する可能性がある場合は残しておいても構わない。
 IF OBJECT_ID(N'[#テーブル名]', N'U') IS NOT NULL
    BEGIN
    DROP TABLE [#テーブル名]
    CREATE TABLE [#テーブル名](
                               hoge INT,
                               piyo NVARCHAR(20),
                               huga VARBINARY(max))
    END



IIF文

SQL Server 2012からIF文を1つにまとめたIIF文が使用できる。
評価の結果に基づいて、他の2つの引数のいずれかを返す。(ACCESSやVisual Basicでは馴染みの関数である)

IIF文の構文

IIF文の第1パラメータの式がtrueであれば、第2パラメータを返して、falseであれば第3パラメータを返す。

 --IIF文でscoreカラムが70以上であれば合格、70未満は不合格とする
 SELECT score,IIF(score >= 70, '合格', '不合格') res FROM table1;



CASE文

CASE文を使用して、条件の判定ができる。

8行目は変数に値を代入して、14行目で変数の値を出力している。

 CREATE PROCEDURE dbo.T_TEST
 AS
 BEGIN
    DECLARE @num1 INT
    DECLARE @msg1 VARCHAR(20)
    SET @num1 = 1
 
    SET @msg1 = CASE @num1
       WHEN 0 THEN '0です'
       WHEN 1 THEN '1です'
       ELSE 'その他'
       END
 
    PRINT @msg1 --"1です"が出力される
 END



NULLとの比較

以下の例では、NULL値と比較している。

10行目は、IS NULL句を使用して、変数の値がNULLかどうかを確認している。
17行目は、IS NOT NULL句を使用して、変数の値がNULLかどうかを確認している。

 CREATE PROCEDURE dbo.T_TEST
 AS
 BEGIN
    DECLARE @str1 VARCHAR(20)
    DECLARE @str2 VARCHAR(20)
    DECLARE @msg1 VARCHAR(20)
    SET @str1 = NULL
    SET @str2 = 'TEST'
 
    IF (@str1 IS NULL)
       BEGIN
          SET @msg1 = 'NULLである'
       END
 
    PRINT @msg1  -- NULLである
 
    IF (@str2 IS NOT NULL)
       BEGIN
          SET @msg1 = 'NULLでない'
       END
 
    PRINT @msg1  -- NULLでない
 END



CASE WHEN文で条件分岐

WHERE句の条件にCASE WHENを使用して、条件分岐を行う。

テーブルとデータの準備

まず、テーブルとその検索用データを作成する。

 CREATE TABLE 社員マスタ
 (
    社員番号  INT,
    氏名      VARCHAR(20),
    部署      VARCHAR(20)
 )


 INSERT INTO 社員マスタ VALUES (1, '太郎さん', '営業部' )
 INSERT INTO 社員マスタ VALUES (2, '次郎さん', '経理部' )
 INSERT INTO 社員マスタ VALUES (3, '三郎さん', '人事部' )
 INSERT INTO 社員マスタ VALUES (4, '四郎さん', '営業部' )
 INSERT INTO 社員マスタ VALUES (5, '五郎さん', '経理部' )
 INSERT INTO 社員マスタ VALUES (6, '六郎さん', '人事部' )
 INSERT INTO 社員マスタ VALUES (7, '七郎さん', '営業部' )
 INSERT INTO 社員マスタ VALUES (8, '八郎さん', '経理部' )
 INSERT INTO 社員マスタ VALUES (9, '九郎さん', '人事部' )


条件を分岐させて検索

社員番号を指定せずに全件取得する場合と、社員番号を指定して1件のみに絞り込んだものを実行する。

 -- 全件検索
 
 DECLARE @検索社員番号 int = NULL
 SELECT
    *
 FROM
    社員マスタ
 WHERE
    社員番号 = CASE WHEN @検索社員番号 IS NULL THEN 社員番号 ELSE @検索社員番号 END


実行結果

社員番号	氏名	部署
1	太郎さん	営業部
2	次郎さん	経理部
3	三郎さん	人事部
4	四郎さん	営業部
5	五郎さん	経理部
6	六郎さん	人事部
7	七郎さん	営業部
8	八郎さん	経理部
9	九郎さん	人事部


 -- 社員番号を指定して取得
 
 DECLARE @検索社員番号 int = 5
 SELECT
    *
 FROM
    社員マスタ
 WHERE
    社員番号 = CASE WHEN @検索社員番号 IS NULL THEN  社員番号 ELSE @検索社員番号 END


実行結果

社員番号	氏名	部署
5	五郎さん	経理部


解説

WHERE 社員番号 = CASE WHEN @検索社員番号 IS NULL THEN 社員番号 ELSE @検索社員番号 ENDにおいて、
CASE WHEN文を使用することで、条件が指定されてない(@検索社員番号がNULL)場合は、テーブルの値をそのまま使用し、
条件が指定された(@検索社員番号がNULL以外)の場合は、その指定された値で検索する。

SQL文を記述する量を少なくすることができる。