CHAPTER 13: WHERE句


WHERE句は、SELECTUPDATEDELETEなどの コマンドに指定します。コマンドで特定のレコードのみ処理したい場合に 、その特定する条件を指定します。

WHERE句を指定しない場合、テーブル内のすべてのレコードが処理され ます。

WHERE句は、ブール演算子で構成されます。ブール演算子は、真または偽 で評価する式です。複雑なWHERE句になると、ANDまたはOR により結合したブール演算式で構成されます。優先させたいブール式がある場合には、 括弧で囲んで優先順を制御します。

WHERE句は、演算式で比較することによって、フィールド値に基づいた レコードを限定することができます。以下に比較演算子を示します。

Table 13-1: WHERE句の比較演算子

演算子 概要
= 一致
!= or <> or ~= 不一致
! 否定
> より大きい
>= 以上
< より小さい
<= 以下
IN フィールド値の複数指定
RANGE ... 値の上限値と下限値を指定
BETWEEN ... RANGEと同一
LIKE パターンマッチ(大文字、小文字の区別有り)
MATCH パターンマッチ(大文字、小文字の区別無し)
SMATCH パターンマッチ(大文字、小文字の区別有り)

~は、!と同様に使用できます。

Syntax

WHERE |b_expr
|(b_expr)
|b_expr OR b_expr
|b_expr AND b_expr
|NOT b_expr
|
|
|
|
|

説明

b_expr ブール式です。詳細はブール式の評価を参照してください。

注意

  1. ブール式b_exprは、
    |expr [
    |
    |IS
    |[IS] NOT
    |] condition
    |
    |
    |
    |NULL expr
    |EXISTS subquery
    |
    |

    expr 式。exprの定義は Expressionsを参照してください。

    conditionは以下のいずれか1つです。
    |
    |
    |
    |
    |
    |
    |
    | =
    |!=
    |<>
    | >
    |>=
    | <
    |<=
    |
    |
    |
    |
    |
    |
    |
    |exp
    |Subquery
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    IN (expr {, expr})
    IN subquery
    LIKE like_pattern [ESCAPE atom]
    |
    |
    |
    |
    |
    |
    |
    |MATCH
    |!MATCH
    |SMATCH
    |!SMATCH
    | pattern
    |
    |
    |
    |
    |
    |
    |
    |
    |
    [ | =
    |!=
    |] NULL
    |
    |
    |
    |
    |
    |
    BETWEEN |expr
    |subquery
    | [
    |
    |EXCLUSIVE
    |INCLUSIVE
    |] AND
    |
    |expr
    |subquery
    |]
    |
    |EXCLUSIVE
    |INCLUSIVE
    |]
    |
    |
    |
    |
    |
    RANGE |expr
    |subquery
    | [
    |
    |EXCLUSIVE
    |INCLUSIVE
    |] TO
    |
    |expr
    |subquery
    |]
    |
    |EXCLUSIVE
    |INCLUSIVE
    |]
    |
    |
    |

    subquery は以下に示す形式のクエリー言語コマンドです。

    [ |ANY
    |ALL
    |] (select_command)
    |

    like_pattern文字列を表します。 like_patternには、以下に示す特別な文字を組込むことが できます。

Table 13-2: LIKEパターンマッチング文字

文字 概要
_ (underline) 指定位置には、任意の単一文字が許されます。
% 指定位置には、任意の文字列が許されます。

atomは、(_)や(%)を単一のデータとして、Empressに解釈 させるために使用します。

subqueryのselect_commandは、1つ以上のフィールドに対する集計関数であり、唯一の項目を検索しなければなりません。 この時、GROUP BY句の指定、ヘッダーのPRINT句を使用することは できません。また必ず括弧で囲む必要があります。 サブクエリーについては、SQL:ユーザーズガイドを参照してください。

BETWEEN ANDは、RENGE TOと同様に使用できます。尚、値を指定 する場合には、必ず昇順で指定しなくてはなりません。 MATCHは、大文字、小文字の区別はしませんが、SMATCHは区別 します。MATCHの前に(!)を付加すると、マッチしない 全てのレコードが選択されます。LIKEもまた、大文字、小文字の区別をします。

  • 通常WHERE句における、シンプルなブール式は以下の形式です。

       expr = VALUE
    
    

    このブール式は、真か偽、あるいはNULLのいずれかの結果を導きます。 式が何らかの原因で評価できなかった場合には、NULLとなります。

    このように、ブール演算式は3種類の結果のうち、いずれか1つを導くので、複雑な ブール演算式を評価する上では、三値論理が必要となります。この論理から、 AND結合、OR結合したブール式の規則が決定されます。 以下に、そのテーブルを示します。

    Table 13-3: AND結合

    T N F
    T T N F
    N N N F
    F F F F

    Table 13-4: OR結合

    T N F
    T T T T
    N T N N
    F T N F

    2つのブール演算式をAND結合した場合、ブール演算式全体が真になるには、 それぞれのブール演算式は、真でなくてはなりません。

    2つのブール演算式をOR結合した場合、ブール演算式全体が真になるのは、 少なくとも、どちらか一方の演算式が真でなくてはなりません。

  • NOT"!"は異なることに注意してください。"!"は 演算子に対して使用しますが、NOTは式に対して使用します。NOTを 演算子の前に使いたい場合は、式に変更して使用します。

    例えば、以下のような使い方をしたい場合、

       ... WHERE attr NOT = ANY SELECT ...
    
    

    以下のように指定します。

       ... WHERE NOT (attr = ANY SELECT ...)
    
    

    または、以下のように指定します。

       ... WHERE attr != ALL SELECT ...
    
    

  • パターンマッチは、いくつか指定した文字パターン、フィールド値を比較する処理 を行います。パターンが一致した場合、その条件を満たすことになります。

    パターンマッチでは、比較文字列に特殊文字を使用することが可能です。次に使用 できる特殊文字を示します。

    Table 13-5: パターンマッチの特殊文字

    文字 概要
    ? 指定位置には、任意の単一文字が許可されます。
    * 指定位置には、任意の文字列が許可されます。
    [...] 指定位置には、指定文字セットのいずれかを許可します。
    例、[abc]>/TT>はa、b、cが許可されます。
    {...} 指定位置には、0以上の文字列を許可します。
    例、 {[a-z]}は、小文字に英字であれば全て許可します。
    [.-.] 指定位置には、指定範囲のいずれかの文字が許可されます。
    例、[a-cf-i] は、a、b、c、f、h、iが許可されます。
    [^...] 指定位置には、指定文字セット以外のものを許可します。
    例、 [^abc]は、a、b、c以外の文字を許可します。
    ...|... "|"を境にして、どちらか一方の値で許可されます。
    例、ab|cd は、abまたはcdが許可されます。
    ...&... "&"を境にして、両方の値で許可されます。
    例、[a-z]&[^x] は"x"以外の任意の文字に許可されます。
    \ "?"、"*"、"|"、"&"、"{"、"}"、"["、"]"、"\"などの特殊文字の前に、バックスラッシュを配置した場合、その文字は 特殊文字でなく、その文字自身として許可されます。

    変数を拡張するために使用する文字の場合には、(MSQLVARCHARS変数で定義され、初期値はドル記号です)パターン マッチの用途はまったく無く、文字列におけるその変数拡張機能がそのまま維持されます。従って、この文字を文字列上、 またはパターン上の任意の位置に表現するには、2つのドル記号($$)を指定することにより、変数拡張機能を回避しなけれ ばなりません。

    パターンマッチ例

    概要
    *ho* このパターンを指定した場合、"ho"の前後に対応する文字の有無、および文字数には関係なく、 "ho"を構成している任意のフィールド値と照合することが可能です。例としてこのパターンは "ho"、"who"、"whom"、"Aho"、"hoho"、"Alphonse"などのフィールド値と一致します。 パターンの前の指定が、SMATCH(大文字、小文字を区別する)である場合には、英小文字の "ho"を使用したパターンが照合されます。パターンの前の指定が、MATCHである場合には、"ho"、 "HO"、"hO"、"Ho"というように、大文字、小文字の区別なしにパターンが照合されます。尚、MATCH、 SMATCHの前に"!"を指定した場合には、一致しないデータが検索されます。
    12|13 この場合、12または13とフィールド値が一致しなくてはなりません。
    R*&*r この場合、"Roger"などのRで始まり、rで終了する任意のフィールド値と一致しなくてなりません。 (R*rと指定することもできます。)
    *Jun*&*1990* この場合、Junと1990を含んだフィールド値に限り一致します。例えば"12 June 1990"、"Jun. 12 1990"、 "1990 12 June"、"1990 June 12"、"on the 12th day of June in 1990"、その他いろいろな表記に 一致します。(従ってDATEデータタイプではなく、CHARデータタイプに自由に日付を入力する場合に 有効になります。)
    f?r この場合、fで開始しrで終了する3文字からなる任意の文字列と一致します。例として"fur"、"for"、 "fir"、"far"などがあります。
    f[uo]r この場合、fで開始しrで終了する、中央の文字がuまたはoとなる3文字からなる文字列です。例として "fur"、"for"などです。
    f[^i]r もの場合、中央の文字がi以外の文字であれば、許可されます。例として、"fur"、"for"、"far"などです。
    E_p この場合、Eで始まり、pで終了する3文字からなる、全ての文字列と一致します。
    1. 以下のWHERE句は、personnelテーブルからname フィールドに"Jones"というデータを持つレコードを検索します。personnel テーブル中には、各nameフィールドごとに、1件のレコードが格納されている ので、単一レコードが検索されます。

         SELECT * FROM personnel
            WHERE name = 'Jones';
      
      

      以下を表示します。

         number     name     phone        credit_limit
      
          3         Jones    667-2951     $500.00
      
      
    2. 以下のWHERE句は、credit_limitが$200.00以上のレコードを 検索します。クエリーを指定する場合には、ドル記号は必ずしも指定する必要はありま せん。尚、ドル記号を指定する場合には、そのドル記号の前にもう1つのドル記号を、 指定する必要があります。これはドル記号が間違って、Empress変数であると解釈 されないようにするためです。

         SELECT * FROM personnel
            WHERE credit_limit >= 200.00;
      
      

      以下を表示します。

         number     name          phone        credit_limit
         
         10         Kilroy        426-9681     $500.00
         5          Mosca         544-2243     $750.00
         17         Wladislaw     723-6073     $200.00
         3          Jones         667-2951     $500.00
         8          Peterson      978-6060     $250.00
      
      
    3. 以下のWHERE句は、nameフィールドに"Kilroy"以外のデータが あり、なおかつ、credit_limitフィールドのデータ値が$500.00のレコードを 検索します。ANDは、その2つの条件を連結するために使用するので、 その条件は、いずれも要求するレコードに対して真でなければなりません。 "<>""!="に置き換えることができます。

         SELECT * FROM personnel
            WHERE name <> 'Kilroy'
            AND credit_limit = '$$500';
      
      

      以下を表示します。

         number     name      phone        credit_limit
      
          3         Jones     667-2951     $500.00
      
      

      credit_limitの条件には、ドル記号を2つ指定していることに注意して ください。

    4. 以下のWHERE句は、loansテーブルのレコードから、 dateフィールドのデータが"16 February 1990"であるもの、 またはnameフィールドのデータが"Wladislaw"であるものを選択します。 ORは、その2つの条件を連結するために、使用するので、少なくとどちらか 一方の条件が真でなければなりません。

         SELECT * FROM loans
            WHERE date = '16 February 1990'
            OR name = 'Wladislaw';
      
      

      以下を表示します。

         name            date                 amount
      
         Kilroy          16 February 1990     $250.00
         Wladislaw       12 May 1990           $25.00
         Wladislaw       27 February 1990      $55.00
         Wladislaw       25 June 1990          $75.00
      
      
    5. フィールドの中に、異なる値が含まれているレコードを検索する必要がある場合 には、ORを使用してWHERE句を複雑に構成することで対処できます。 例えばloansテーブルから"Jones"、"Kilroy"、"Mosca"の全てのレコード を検索するには、以下のように指定します。

         SELECT * FROM loans
            WHERE name = 'Jones' OR
            name = 'Kilroy' OR name = 'Mosca';
      
      

      この方法とは別に、定数リストを使用して同一の処理を実行することができます。 以下のようなコマンドを実行します。

         SELECT * FROM loans
            WHERE name IN
            ('Jones', 'Kilroy', 'Mosca');
      
      

      これにより、複雑な構成で記述する必要がなくなります。

      これと同様に、指定したもの以外の全てのレコードを選択することが可能です。 例えばloansテーブルの中から"Jones"、"Kilroy"、"Mosca"以外の全ての レコードを検索するには、次のように指定します。

         SELECT * FROM loans
            WHERE name NOT IN
            ('Jones', 'Kilroy', 'Mosca');
      
      
    6. 以下のWHERE句は、phoneフィールドにデータが入力されて いないレコードを、すべて検索します。 キーワードNULLは、入力されていないデータを意味します。

         SELECT FROM personnel
            WHERE phone = NULL;
      
      

      以下のように出力します。

         number     name     phone          credit_limit
      
      

      上記のように、phoneフィールドにはNULL値のレコードが検索 できないので、フィールド名だけが出力されます。 NULL値または、NULL値以外の値の検索には、 "="および"!="の代わりに、"is"および"is not" キーワードを使用することができます。

         SELECT FROM personnel
            WHERE phone IS NULL;
      
      
         SELECT FROM personnel
            WHERE phone IS NOT NULL;
      
      

      上記は、phoneフィールドがNULLでないレコードを検索します。

    7. 以下のWHERE句は、nameフィールドが"Jones"で、 dateフィールドが"1 May 1990"より前のレコード、あるいは nameフィールドが"Wlasdislaw"で、dateフィールドが "30 April 1990"より後のレコードを検索します。 この場合、括弧を指定してグループ別に分類します。nameフィールドと dateフィールドが1つのグループとして条件を指定します。

      ORは、括弧内の2つの条件を連結するために使用するので、 少なくともどちらか一方の条件が真でなくてはなりません。以下に示す例では、 それぞれの条件が同時に真になることはありません。

         SELECT FROM loans
            WHERE (name = 'Jones' AND date < '1 May 1990')
            OR (name = 'Wladislaw' AND date > '30 April 1990');
      
      

      以下を表示します。

         name               date                 amount
      
         Jones               7 February 1990     $33.95
         Jones               3 April 1990        $25.00
         Wladislaw          12 May 1990          $25.00
         Wladislaw          25 June 1990         $75.00
      
      

      括弧は、必要に応じて論理強調の目的で、WHERE句に指定することができ ます。

    8. 以下のWHERE句は、amountフィールドが credit_limitフィールドの半分を超えているレコードを検索する   コマンドです。

         SELECT name, date, amount
            FROM loans, personnel
            WHERE amount > 0.5 * credit_limit
            AND loans.name = personnel.name;
      
      

      以下を表示します。

         name               date                  amount
      
         Jones              12 August 1990        $300.00
         Scarlatti           9 September 1990     $150.00
         Scarlatti          14 October 1990       $125.00
      
      
    9. loansテーブルのnameフィールドに名前がある、 personnelテーブルのデータを表示します。

         SELECT name, phone, credit_limit
            FROM personnel WHERE exists
            (SELECT name FROM loans
             WHERE loans.name = personnel.name);
      
      

      以下を表示します。

         name          phone           credit_limit
         
         Jones         667-2951        $500.00
         Kilroy        426-9681        $500.00
         Mosca         544-2243        $750.00
         Peterson      978-6060        $250.00
         Scarlatti     961-7363        $100.00
         Wladislaw     723-6073        $200.00
      
      

      以下のWHERE句は、loansテーブルの中から平均値未満の値を 持っているamountフィールドのレコードを検索します。そのためにクエリー をネストします。

         SELECT FROM loans
            WHERE amount < (SELECT AVG amount FROM loans);
      
      

      以下を表示します。

         name            date                amount
         
         Jones            7 February 1990    $33.95
         Wladislaw       27 February 1990    $55.00
         Jones            3 April 1990       $25.00
         Wladislaw       12 May 1990         $25.00
         Peterson         6 June 1990        $50.00
         Wladislaw       25 June 1990        $75.00
      
      

      以下に示す例は、loansテーブルのamountフィールドの値が200 を超えている人の情報を、personnelテーブルから検索します。

         SELECT name, credit_limit FROM personnel
            WHERE name= ANY
            (SELECT name FROM loans WHERE amount > 200);
      
      
         name         credit_limit
      
         Kilroy       $500.00
         Jones        $500.00
      
      
    10. 以下のWHERE句は、"9"で始まるデータを持つphone フィールドの文字パターンレコードだけ検索します。 パターンマッチを利用した、検索条件の指定例を以下に示します。

         SELECT * FROM personnel
            WHERE phone MATCH '9*';
      
      

      以下を表示します。

         number    name        phone       credit_limit
      
         8        Peterson     978-6060    $250.004
                  Scarlatti    961-7363    $100.00
      
      

      以下のコマンドを指定しても、同一の処理結果となります。

         SELECT * FROM personnel
            WHERE phone LIKE '9%';
      
      

      以下のWHERE句は、任意の文字が先頭にあり(先頭になくても良い)、 その後1つのスペースが続き、"May"の後に、1つのスペースが続き、最後に任意の文字 がある(最後になくても良い)パターンと一致する、dateフィールド中の パターンレコードのみを検索します。この指定により、任意の年の5月に発生した loansテーブルのレコードを検索できます。

         SELECT * FROM loans
            WHERE date MATCH '* May *';
      
      

      以下を表示します。

         name            date           amount
      
         Mosca            4 May 1990    $200.00
         Wladislaw       12 May 1990     $25.00
      
      

      dateフィールド中のデータで、唯一英文字であるのは、月の指定です。 Mayのエントリをすべて検出するための簡潔な指定方法は、以下の方法です。

         SELECT * FROM loans
            WHERE date MATCH '*May*';
      
      

      5月以外の月に発生した、レコードを検索するには、以下のコマンドを使用します。

         SELECT * FROM loans WHERE date !MATCH '*May*';
      
      

      または

         SELECT * FROM loans WHERE date NOT LIKE '%May%';
      
      

      以下を表示します。

         name               date                 amount
         
         Mosca               2 February 1990     $150.00
         Jones               7 February 1990      $33.95
         Kilroy             16 February 1990     $250.00
         Wladislaw          27 February 1990      $55.00
         Jones               3 April 1990         $25.00
         Peterson            6 June 1990          $50.00
         Wladislaw          25 June 1990          $75.00
         Jones              12 August 1990       $300.00
         Scarlatti           9 September 1990    $150.00
         Scarlatti          14 October 1990      $125.00
      
      

      SMATCHの効果については、auto partsテーブルからの検索に より、具体的に示すことができます。

         SELECT supplier, phone, ATTR 'part name', price
            FROM 'auto parts'
            WHERE ATTR 'part name' SMATCH '*chrome*';
      
      

      以下を表示します。

         supplier           phone        part name              price
      
         AAA Automotive     922-8624     Fender--chrome          $67.95
      
      

      ここでは、1レコードのみ表示しています。次のコマンドを使用した場合には、

         SELECT supplier, phone, ATTR 'part name', price
            FROM 'auto parts'
            WHERE ATTR 'part name' MATCH '*chrome*';
      
      

      以下の2レコードを表示します。

         supplier             phone        part name              price
      
         AAA Automotive       922-8624     Fender--chrome        $67.95
         Auto Wholesalers     922-6219     Chrome paint           $1.99
      
      

      尚、複合フィールド名で、演算式でないことを明示するために、フィールド名 part nameの前には、必ず"ATTR"キーワードを指定する必要があり ます。

    11. 値が与えられた範囲内に位置しているのを見つけるために、RANGE キーワードは、次のもののような 複雑なWHERE句に優先して使用します。

         WHERE ATTRIBUTE first_constant AND ATTRIBUTE second_constant
      
      

      RANGEの値を指定する際は、任意のレコードがその条件に合致するように、 必ず昇順に指定しなければなりません。降順にRANGEの値を指定しても、 エラーにはなりませんが、レコードは検索されません。 RANGE指定の、上限値および下限値は、省略時には範囲内に含まれます。 しかし、WHERE句の中でEXCLUSIVEを指定すれば、上限値および 下限値は、検索範囲から除外されます。

      BETWEEN ... ANDは、RANGE ... TOの代わりに使用できます。

      次の例は、loansテーブルのamountフィールドが、 100以上200以下のレコードを検索します。

         SELECT name, date, amount FROM loans
            WHERE amount RANGE 100 to 200;
      
      

      以下を表示します。

         name               date                 amount
      
         Mosca               2 February 1990     $150.00
         Mosca               4 May 1990          $200.00
         Scarlatti           9 September 1990    $150.00
         Scarlatti          14 October 1990      $125.00
      
      

      この結果に対して、以下のコマンドを実行した場合。

         SELECT name, date, amount FROM loans
            WHERE amount RANGE 100 EXCLUSIVE TO 200 EXCLUSIVE;
      
      

      以下を表示します。

         name               date                amount
      
         Mosca              2 February 1990      $150.00
         Scarlatti          9 September 1990     $150.00
         Scarlatti          9 September 1990     $125.00
      
      

      以下に示すWHERE句は、loansテーブルのamount フィールドの値が、200より大きく、300以下のレコードを検索します。

         SELECT name, date, amount FROM loans
            WHERE amount RANGE 200 EXCLUSIVE TO 300;
      
      

      以下を表示します。

         name            date                 amount
      
         Kilroy          16 February 1990     $250.00
         Jones           12 August 1990       $300.00
      
      
    12. 値の範囲を指定するには、BETWEEN ... ANDを使用します。 BETWEEN ... ANDRENGE ... TOの同義語として使用できます。 またBETWEEN ... ANDは、複雑なブール演算式を指定することもできますが、 その場合の評価の際には多くの時間を費やします。

         SELECT * FROM table WHERE
            attr BETWEEN value AND value;
      
      

      上記指定は、次の指定と同一です。

         SELECT * FROM table WHERE
            attr RANGE value TO value;
      
      

      よって、前に示したloansテーブルのamountフィールドのデータ が、100より大きく、200より小さいレコードの選択は、次のように指定することも可能 です。

         SELECT name, date, amount FROM loans
            WHERE amount BETWEEN 100 EXCLUSIVE AND 200 EXCLUSIVE;
      
      

      以下に示すような、同一の結果を表示します。

         name                date                 amount
      
         Mosca               2 February 1990      $150.00
         Scarlatti           9 September 1990     $150.00
         Scarlatti           9 September 1990     $125.00
      
      

      尚、RENGE ... TOを指定した場合と同様に、任意のレコードがその条件に 合致するように、必ず昇順に値を指定しなければなりません。