SQLの空白判定についてまとめています。
SQLの空白判定には、TRIMを条件式に組み込む
SQLの空白判定を実際のデータを使って試してみましょう。
以下、MySQLで実行しています。サンプルデータベースとして、employeesを使用しています。
【関連記事】
▶MySQLの入門には、GUIツールで慣れ、サンプルDBを使った学習が効果的
まずは、テーブルemployeesのコピー、employees_copyを作成します。
mysql> create table employees_copy select * from employees; Query OK, 300025 rows affected (3.72 sec) Records: 300025 Duplicates: 0 Warnings: 0 mysql> select * from employees_copy limit 10; +--------+------------+------------+-----------+--------+------------+ | emp_no | birth_date | first_name | last_name | gender | hire_date | +--------+------------+------------+-----------+--------+------------+ | 10001 | 1953-09-02 | Georgi | Facello | M | 1986-06-26 | | 10002 | 1964-06-02 | Bezalel | Simmel | F | 1985-11-21 | | 10003 | 1959-12-03 | Parto | Bamford | M | 1986-08-28 | | 10004 | 1954-05-01 | Chirstian | Koblick | M | 1986-12-01 | | 10005 | 1955-01-21 | Kyoichi | Maliniak | M | 1989-09-12 | | 10006 | 1953-04-20 | Anneke | Preusig | F | 1989-06-02 | | 10007 | 1957-05-23 | Tzvetan | Zielinski | F | 1989-02-10 | | 10008 | 1958-02-19 | Saniya | Kalloufi | M | 1994-09-15 | | 10009 | 1952-04-19 | Sumant | Peac | F | 1985-02-18 | | 10010 | 1963-06-01 | Duangkaew | Piveteau | F | 1989-08-24 | +--------+------------+------------+-----------+--------+------------+ 10 rows in set (0.00 sec)
データのemp_no 10001~10005をupdateで更新し、first_nameカラムに空白、複数の空白、文字列の前後に空白、NULLの入ったデータを作成します。
mysql> update employees_copy set first_name=" " where emp_no=10001; Query OK, 1 row affected (0.24 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> update employees_copy set first_name=" " where emp_no=10002; Query OK, 1 row affected (0.22 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> update employees_copy set first_name=" " where emp_no=10003; Query OK, 1 row affected (0.27 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> update employees_copy set first_name=" Chirstian " where emp_no=10004; Query OK, 1 row affected (0.22 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> update employees_copy set first_name=NULL where emp_no=10005; Query OK, 1 row affected (0.22 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from employees_copy limit 10; +--------+------------+--------------+-----------+--------+------------+ | emp_no | birth_date | first_name | last_name | gender | hire_date | +--------+------------+--------------+-----------+--------+------------+ | 10001 | 1953-09-02 | | Facello | M | 1986-06-26 | | 10002 | 1964-06-02 | | Simmel | F | 1985-11-21 | | 10003 | 1959-12-03 | | Bamford | M | 1986-08-28 | | 10004 | 1954-05-01 | Chirstian | Koblick | M | 1986-12-01 | | 10005 | 1955-01-21 | NULL | Maliniak | M | 1989-09-12 | | 10006 | 1953-04-20 | Anneke | Preusig | F | 1989-06-02 | | 10007 | 1957-05-23 | Tzvetan | Zielinski | F | 1989-02-10 | | 10008 | 1958-02-19 | Saniya | Kalloufi | M | 1994-09-15 | | 10009 | 1952-04-19 | Sumant | Peac | F | 1985-02-18 | | 10010 | 1963-06-01 | Duangkaew | Piveteau | F | 1989-08-24 | +--------+------------+--------------+-----------+--------+------------+ 10 rows in set (0.00 sec)
わかりやすいよう、first_nameカラムの前後にシングルクォーテーションを連結して表示。
mysql> select emp_no, concat("'",first_name,"'") as first_name from employees_copy limit 10; +--------+----------------+ | emp_no | first_name | +--------+----------------+ | 10001 | ' ' | | 10002 | ' ' | | 10003 | ' ' | | 10004 | ' Chirstian ' | | 10005 | NULL | | 10006 | 'Anneke' | | 10007 | 'Tzvetan' | | 10008 | 'Saniya' | | 10009 | 'Sumant' | | 10010 | 'Duangkaew' | +--------+----------------+ 10 rows in set (0.00 sec)
単一の空白、複数の空白にマッチさせる条件として、 trim(first_name) = ” を指定しています。trimは文字列の前後から空白を取り除く関数で、空白のみのカラムは「空文字」になります。空文字とNULLは扱いが異なるため、NULLにもマッチさせるために条件にIS NULLをorで接続しました。
mysql> select * from employees_copy where trim(first_name) = '' or trim(first_name) IS NULL; +--------+------------+------------+-----------+--------+------------+ | emp_no | birth_date | first_name | last_name | gender | hire_date | +--------+------------+------------+-----------+--------+------------+ | 10001 | 1953-09-02 | | Facello | M | 1986-06-26 | | 10002 | 1964-06-02 | | Simmel | F | 1985-11-21 | | 10003 | 1959-12-03 | | Bamford | M | 1986-08-28 | | 10005 | 1955-01-21 | NULL | Maliniak | M | 1989-09-12 | +--------+------------+------------+-----------+--------+------------+ 4 rows in set (0.19 sec)
目的の動作が達成できましたが、where句でtrimを使用する場合、件数によってはパフォーマンスが悪くなります。本来なら、複数の空白文字が挿入されないよう、アプリケーション等でチェックするのがベストと言えるでしょう。
まとめ
- 連続した空白文字は、whereでtrim後の文字列と空文字を比較でマッチ可能
- 空文字とNULLは別扱いなので、IS NULLを組み合わせる必要がある
- where句でtrim関数を使うとレスポンスが悪くなるので、本来はアプリでデータチェックがベスト