It's just a table with one row. It was created by Charles Weiss of Oracle to provide a table for joining in internal views of the Oracle Data Dictionary.
I created the DUAL table as an underlying object in the Oracle Data
Dictionary. It was never meant to be seen itself, but instead used
inside a view that was expected to be queried. The idea was that you
could do a JOIN to the DUAL table and create two rows in the result
for every one row in your table. Then, by using GROUP BY, the
resulting join could be summarized to show the amount of storage for
the DATA extent and for the INDEX extent(s). The name, DUAL, seemed
apt for the process of creating a pair of rows from just one.
There are lot of neat things you can leverage dual for. I use it to generate a list of numbers. For example
SELECT LEVEL just_a_column
FROM dual
CONNECT BY LEVEL <= 365
Also note that as of 10g Oracle recognizes dual for its unique usages and that the logical reads / full table scans in 9i and earlier have been eliminated for applications. Upgrading to 10g had signficant performance benefits for applications that used dual. (e.g. Select sysdate from dual).
Explain Plan example:
In 10g and above, dual is a magic table - if you select sysdate from dual, the plan would be:
sql> select sysdate from dual;
SYSDATE
---------
12-DEC-02
Execution Plan
-----------------------------------------------------------------
| 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 |
-----------------------------------------------------------------