SQLのdualについてまとめています。


dualはfrom省略できないデータベース用のダミーテーブル
dualは、Oracleで使われるテーブル。SQLでfrom句を省略できないOracleで使われるダミー表です。
Oracleで、select文によるdualテーブルの全件取得を実行すると以下が出力されます。
- select * from dual;
- DUMMY
- -----
- X
例えば、以下のSQLは、Oracleで現在の日付を取得します。fromを省略すると、エラーが出力されます。
- select SYSDATE from dual;
- SYSDATE
- -----
- 23-APR-20
- select SYSDATE;
- ORA-00923: FROM keyword not found where expected
なお、MySQLやSQL Server、PostgreSQLなどではdual指定は不要です。指定すると、dualテーブルが存在しないというエラーが出力されます。(※ただし、MySQLは互換性確保のため、from dualと記述してもエラーが出力されないようになってまいます。)
OracleのSQLコードをなるべく修正せずに他のデータベースに流用するため、ダミーのdualテーブルを作成するケースもあります。
以下のSQLは、postgreSQLでdualテーブルを作成し、現在時刻をselectで取得するサンプルです。
- $ psql -U postgres
- psql (9.6.17)
- Type "help" for help.
- postgres=#
- postgres=#
- postgres=# select now() from dual;
- ERROR: relation "dual" does not exist
- LINE 1: select now() from dual;
- ^
- postgres=# select now();
- now
- ------------------------------
- 2020-04-23 07:54:31.63905+00
- (1 row)
- postgres=# create table dual (dummy varchar(1));
- CREATE TABLE
- postgres=# insert into dual (dummy) values ('X');
- INSERT 0 1
- postgres=# select * from dual;
- dummy
- -------
- X
- (1 row)
- postgres=# select now() from dual;
- now
- -------------------------------
- 2020-04-23 07:56:31.872746+00
- (1 row)
dualテーブルを使ったSQLサンプル
dualテーブルは、ダミーデータが一件だけ格納されたテーブルです。createテーブルで作成しなくても存在しているテーブルで、基本的に他の一般テーブルと変わりありません。
dualテーブルに対して、様々なSQLを実行してみましょう。
- SQL> desc dual
- Name Null? Type
- ----------------------------------------- -------- ----------------------------
- DUMMY VARCHAR2(1)
- SQL> select * from dual;
- DUMMY
- -----
- X
- SQL> select count(*) from dual;
- COUNT(*)
- ----------
- 1
- SQL> select 'abcabcabcabc' from dual;
- 'ABCABCABCABC'
- ------------------
- abcabcabcabc
- SQL> select 3434334 from dual;
- 3434334
- ----------
- 3434334
- SQL> truncate table dual;
- truncate table dual
- *
- ERROR at line 1:
- ORA-00942: table or view does not exist
- SQL> delete from dual;
- delete from dual
- *
- ERROR at line 1:
- ORA-01031: insufficient privileges
- dualは、カラム名DUMMYにvarchar2(1)のデータ型が設定されている。格納されているデータは「X」。
- データ件数は1件
- selectで文字列や数値を指定すると、指定した値がそのままカラム名として取得される。
- truncate tableを実行しようとすると、テーブルまたはビューが存在しないエラーが出力される。
- dualテーブルをdeleteしようとすると、権限がない旨のエラーが出力される
truncateやdelete実行時にはエラーが出力され、誤って消せないようになっているようです。
dualを使ってunion結合で複数行を生成するサンプルコード
dualはダミーデータが一件だけ格納されているテーブルですが、unionでselect結果を結合し、サブクエリを使うことで、擬似的にテーブルのように扱うことが可能です。
以下のSQLは、1を取得するselect文をUNIONで10件ぶん結合し、サブクエリのrownumを取得することで1~10までの数を取得しています。
- select rownum from (
- SELECT 1 FROM dual UNION ALL
- SELECT 1 FROM dual UNION ALL
- SELECT 1 FROM dual UNION ALL
- SELECT 1 FROM dual UNION ALL
- SELECT 1 FROM dual UNION ALL
- SELECT 1 FROM dual UNION ALL
- SELECT 1 FROM dual UNION ALL
- SELECT 1 FROM dual UNION ALL
- SELECT 1 FROM dual UNION ALL
- SELECT 1 FROM dual);
- ROWNUM
- -----
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
テスト用にテーブルを使いたいけど、createテーブルをしたくないという場合などに、使えそうです。
参考)DUALだけで多行を生成するSQLクエリをいろいろ挙げてみる(Oracle) – Qiita
まとめ

- dualは、Oracleで用意されているダミー表。from指定しないとエラーが出るため用意されている。
- 他の主要なデータベース(SQL Server、MySQL、PostgreSQLなど)では、from指定を省略できるため、dualは不要
- 他のデータベースでもdualテーブルを作成すれば、dualを使ったOracleのSQLを流用可能。
- dualは、ダミーデータが一件のみ格納されていて、truncateやdeleteはできない。
- unionやサブクエリを利用し、dualを使って複数行データを生成することが可能。