How does the Oracle DUAL table work?
From Wikipedia:
The DUAL table is a special one-row table present by default in all Oracle database installations. It is suitable for use in selecting a pseudocolumn such as SYSDATE or USER. The table has a single VARCHAR2(1) column called DUMMY that has a value of 'X'.
Thus, the dual table is a way to perform operations against what amounts to be an empty but not null table. This is useful when one doesn't care about the table, but needs to perform operations through a select statement. If the table had more than one row or column, multiple results would be returned (due to operating over the entire set of tuples when performing the operation.)
It shouldn't be used in production, unless you specifically need to invoke certain procedures through SQL.
4*5
is a mathematical operation, just as 'Foo'
is a string. Thus, just as one can select 4*5 from any table, just as one can select 'Foo' from any table, DUAL is a way of selecting it from a known-good table that will never have multiple results.
From the documentation (CONCEPTS):
DUAL is a small table in the data dictionary that Oracle Database and user-written programs can reference to guarantee a known result. The dual table is useful when a value must be returned only once, for example, the current date and time. All database users have access to DUAL.
The DUAL table has one column called DUMMY and one row containing the value X.
And the SQL Reference:
DUAL is a table automatically created by Oracle Database along with the data dictionary. DUAL is in the schema of the user SYS but is accessible by the name DUAL to all users. It has one column, DUMMY, defined to be VARCHAR2(1), and contains one row with a value X. Selecting from the DUAL table is useful for computing a constant expression with the SELECT statement. Because DUAL has only one row, the constant is returned only once. Alternatively, you can select a constant, pseudocolumn, or expression from any table, but the value will be returned as many times as there are rows in the table. Refer to "About SQL Functions" for many examples of selecting a constant value from DUAL.
Beginning with Oracle Database 10g Release 1, logical I/O is not performed on the DUAL table when computing an expression that does not include the DUMMY column. This optimization is listed as FAST DUAL in the execution plan. If you SELECT the DUMMY column from DUAL, then this optimization does not take place and logical I/O occurs.
DUAL
is a table with has exactly one row as the following SQL statement will show:
SELECT * FROM dual;
Your dual2
table has no rows. If you insert one, you will see the same behavior.
4*5 is an expression that Oracle can evaluate without actually using data from the table. It will evaluate it once for every row, just like it would do with a normal column expression. So if there is no row, no result is returned, if there are two rows, you will get the 20 twice.
The dual
table "works" almost just the way any other table works: it is a table from which you can select records.
This means, for example, you can describe the table. Here, in SQL*Plus
:
SQL> set lines 50
SQL> desc dual
Name Null? Typ
----------------------- -------- ----------------
DUMMY VARCHAR2(1)
So, the table has one column, named dummy
which is a varchar2(1)
.
The table has, by design, one record (at least if nobody fiddled with it):
SQL> select count(*) from dual;
COUNT(*)
----------
1
So, in order to get the same behaviour with dual2
as you have with dual
, you have to insert one record into dual. Better yet, create it with a create table as select
(ctas):
SQL> create table dual2 as select * from dual;
Now, your query works:
SQL> select 4*5 from dual2;
4*5
----------
20
Earlier, I said that dual almost works like any other table. So, when does it not work like any other table?
It behaves differently, if no value from the table itself is selected. Again, with your queries, I let Oracle explain them ...
SQL> set lines 150
SQL> explain plan for select 4*5 from dual2;
EXPLAIN PLAN ausgef³hrt.
... in order to see how the table is accessed:
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------
Plan hash value: 3445655939
-------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| DUAL2 | 1 | 3 (0)| 00:00:01 |
-------------------------------------------------------------------
It can be seen that the statement does a full table access
on dual2
.
Now, same thing with dual
:
SQL> explain plan for select 4*5 from dual;
EXPLAIN PLAN ausgef³hrt.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------
Plan hash value: 1388734953
-----------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 |
| 1 | FAST DUAL | | 1 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------
This is where the dual
table behaves differently: the value of dummy
is not needed, so a fast dual
operation is executed, in order for the instance not to read the actual value on the disk.