Como a tabela Oracle DUAL funciona?

32
SQL> desc dual
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 DUMMY                                              VARCHAR2(1)

SQL> select 4*5 from dual;

       4*5
----------
        20

SQL>

Eu acho isso realmente estranho. Se não houver coluna denominada 4 * 5 em dual, como funciona a instrução select?

Além disso, por que não vejo o mesmo comportamento quando crio minha própria tabela dupla?

SQL> create table dual2(dummy varchar2(1)); 

Table created.

SQL> desc dual2
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 DUMMY                                              VARCHAR2(1)

SQL> select 4*5 from dual2;

no rows selected

SQL> 
lazer
fonte

Respostas:

29

Da Wikipedia :

A tabela DUAL é uma tabela especial de uma linha presente por padrão em todas as instalações de banco de dados Oracle. É adequado para uso na seleção de uma pseudocoluna, como SYSDATE ou USER. A tabela possui uma única coluna VARCHAR2 (1) chamada DUMMY que possui um valor de 'X'.

Portanto, a tabela dupla é uma maneira de executar operações em relação ao que equivale a uma tabela vazia, mas não nula. Isso é útil quando alguém não se importa com a tabela, mas precisa executar operações através de uma instrução select. Se a tabela tivesse mais de uma linha ou coluna, vários resultados seriam retornados (devido à operação em todo o conjunto de tuplas ao executar a operação).

Não deve ser usado na produção, a menos que você precise invocar determinados procedimentos através do SQL.

4*5é uma operação matemática, assim como 'Foo' uma string. Assim, assim como se pode selecionar 4 * 5 em qualquer tabela, assim como se pode selecionar 'Foo' em qualquer tabela, o DUAL é uma maneira de selecioná-lo em uma tabela em bom estado que nunca terá vários resultados.

A partir da documentação (CONCEPTS):

DUAL é uma pequena tabela no dicionário de dados que o Oracle Database e os programas escritos pelo usuário podem fazer referência para garantir um resultado conhecido. A tabela dupla é útil quando um valor deve ser retornado apenas uma vez, por exemplo, a data e a hora atuais. Todos os usuários do banco de dados têm acesso ao DUAL.

A tabela DUAL possui uma coluna chamada DUMMY e uma linha contendo o valor X.

E a referência SQL :

DUAL é uma tabela criada automaticamente pelo Oracle Database junto com o dicionário de dados. DUAL está no esquema do usuário SYS, mas é acessível pelo nome DUAL a todos os usuários. Ele possui uma coluna, DUMMY, definida como VARCHAR2 (1) e contém uma linha com um valor X. A seleção na tabela DUAL é útil para calcular uma expressão constante com a instrução SELECT. Como DUAL possui apenas uma linha, a constante é retornada apenas uma vez. Como alternativa, você pode selecionar uma constante, pseudocoluna ou expressão de qualquer tabela, mas o valor será retornado quantas vezes houver linhas na tabela. Consulte "Sobre as funções SQL" para muitos exemplos de seleção de um valor constante no DUAL.

A partir do Oracle Database 10g Release 1, a E / S lógica não é executada na tabela DUAL ao calcular uma expressão que não inclui a coluna DUMMY. Essa otimização é listada como FAST DUAL no plano de execução. Se você SELECIONAR a coluna DUMMY de DUAL, essa otimização não ocorrerá e a E / S lógica ocorrerá.

Brian Ballsun-Stanton
fonte
5
"Não deve ser usado na produção, a menos que você precise invocar determinados procedimentos através do SQL" Por que não?
Nick Pierpoint
2
Também não posso concordar que não deva ser usado na produção. Isso soa como um meme "cortar as pontas do assado", para mim.
ErikE
11
Essa resposta precisa ser aprimorada, pois discorda de si mesma. Em um lugar, ele copia os documentos oficiais: "A tabela dupla é útil " e, em outro, recomenda "Não deve ser usado na produção, a menos que ..."
ypercubeᵀᴹ
18

DUAL é uma tabela com exatamente uma linha, como a seguinte instrução SQL será exibida:

SELECT * FROM dual;

Sua dual2tabela não possui linhas. Se você inserir um, verá o mesmo comportamento.

4 * 5 é uma expressão que o Oracle pode avaliar sem realmente usar dados da tabela. Ele será avaliado uma vez para cada linha, como faria com uma expressão de coluna normal. Portanto, se não houver linha, nenhum resultado será retornado; se houver duas linhas, você receberá os 20 duas vezes.

Hendrik Brummermann
fonte
14

A dualtabela "funciona" quase da mesma maneira que qualquer outra tabela: é uma tabela da qual você pode selecionar registros.

Isso significa, por exemplo, que você pode descrever a tabela. Aqui, em SQL*Plus:

SQL> set lines 50
SQL> desc dual
Name                    Null?    Typ
----------------------- -------- ----------------
DUMMY                            VARCHAR2(1)

Portanto, a tabela possui uma coluna, denominada dummyqual é a varchar2(1).

A tabela possui, por design, um registro (pelo menos se ninguém mexer com ela):

SQL> select count(*) from dual;

COUNT(*)
----------
         1

Portanto, para obter o mesmo comportamento dual2que você tem dual, é necessário inserir um registro no dual. Melhor ainda, crie-o com um create table as select(ctas):

SQL> create table dual2 as select * from dual;

Agora, sua consulta funciona:

SQL> select 4*5 from dual2;
       4*5
----------
        20

Anteriormente, eu disse que o dual quase funciona como qualquer outra tabela. Então, quando não funciona como qualquer outra tabela?

Ele se comporta de maneira diferente, se nenhum valor da tabela em si for selecionado. Novamente, com suas perguntas, deixo a Oracle explicá- las ...

SQL> set lines 150
SQL> explain plan for select 4*5 from dual2;

EXPLAIN PLAN ausgef³hrt.

... para ver como a tabela é acessada:

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 |
-------------------------------------------------------------------

Pode-se ver que a declaração está full table accessativada dual2.

Agora, a mesma coisa com 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 |
-----------------------------------------------------------------

É aqui que a dualtabela se comporta de maneira diferente: o valor de dummynão é necessário; portanto, uma fast dualoperação é executada para que a instância não leia o valor real no disco.

René Nyffenegger
fonte
10

Aliás, DUAL é uma das poucas 'tabelas' que funciona quando a instância foi iniciada, mas o banco de dados não foi aberto.

Você recebe algo como

ADDR     INDX   INST_ID D
-------- ------ ------- -
0C0362D4      0       1 X
Gary
fonte
9

Além de outras respostas, o Oracle não é tão exigente quanto ao texto SQL dos espaços (pelo menos em alguns lugares). O analisador SQL também simboliza por diferenças de classe de caracteres em alguns casos, não apenas por espaço em branco.

Por exemplo, você pode executar essas instruções:

SQL> selecione * de dual;

D
-
X


SQL> selecione (1) do dual;

       (1)
----------
         1 1

SQL> selecione nulo de dual;

     -NULO
----------


SQL selecione 1 do dual;

        -1
----------
        -1

SQL> 

Também é possível executar o SQL sem nenhum espaço em branco:

SQL> selecione * de / ** / dual;

D
-
X

Eu tenho mais alguns exemplos aqui:

http://blog.tanelpoder.com/2008/01/14/can-you-write-a-working-sql-statement-without-using-any-whitespace/

Tanel Poder

Tanel Poder
fonte
2
Essa capacidade de omitir muitos espaços não é exclusiva do Oracle. Funciona da mesma maneira no SQL Server.
ErikE
8

Uma operação dupla rápida reescreve seu código para consultar x $ dual. Como essa "tabela" é uma estrutura de dados C na SGA, você pode consultá-la no modo nomount.

Eu sei mais que voce
fonte
4

A pergunta já está respondida. Estas são algumas notas para o objetivo da tabela dupla. Dual pode ser usado para avaliar expressões em uma cláusula de seleção. Muitos outros sistemas de banco de dados não precisam dessa tabela para esse fim. MS SQL Server, MySQL, Posgres pode avaliar a seguinte declaração

select 3+5 ;

Oracle não pode. Uma instrução de seleção Oracle sempre precisa de uma cláusula "from".

Algumas funções não podem ser usadas na expressão pl / sql como DUMP .

tão

declare
str varchar2(100);
begin
str:=dump('Hallo');
end;
/

irá gerar uma exceção, mas

declare
str varchar2(100);
begin
select dump('Hallo') into str from dual;
end;
/

vai funcionar.

Pode ser usado para estender o conjunto de resultados de uma consulta

select user_id,username from user_users
union all
select -1,'NO USER'
from dual
/

que deu

| USER_ID |     USERNAME |
|---------|--------------|
|  476267 | USER_4_E8C50 |
|      -1 |      NO USER |

ou gere dados com consultas selecionadas usando CONNECT BY:

select level as n 
from dual
connect by level <= 5 ;

ou um CTE recursivo:

with nlist(n) as (
  select 1 from dual
  union all
  select n+1
  from nlist 
  where n<5    )
select n
from nlist
 ;

que retorna

| N |
|---|
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |

em sqlfiddle

miracle173
fonte
3

Pelo que vale, funciona exatamente da mesma maneira no MySQL.

mysql> use test;
Database changed

mysql> create table fred(billy int);
Query OK, 0 rows affected (0.79 sec)

mysql> select 4 + 5 from fred;
Empty set (0.00 sec)

mysql> select 4 + 5 as mary from fred;
Empty set (0.00 sec)

mysql> insert into fred values(1);
Query OK, 1 row affected (0.13 sec)

mysql> select 4 + 5 from fred;
+-------+
| 4 + 5 |
+-------+
|     9 |
+-------+
1 row in set (0.00 sec)

mysql> select 4 + 5 as mary from fred;
+------+
| mary |
+------+
|    9 |
+------+
1 row in set (0.00 sec)

mysql> insert into fred values(2);
Query OK, 1 row affected (0.08 sec)

mysql> select 4 + 5 from fred;
+-------+
| 4 + 5 |
+-------+
|     9 |
|     9 |
+-------+
2 rows in set (0.00 sec)

mysql> select 4 + 5 as mary from fred;
+------+
| mary |
+------+
|    9 |
|    9 |
+------+
2 rows in set (0.00 sec)

mysql> explain select 4 + 5 as mary from fred;
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | fred  | ALL  | NULL          | NULL | NULL    | NULL |    2 | NULL  |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)

mysql> 

E também parece que DUAL é algum tipo de estrutura de memória no MySQL também. Observe a diferença nos dois planos de explicação - "nenhuma tabela usada" para DUAL no MySQL.

Curiosamente, no entanto, não posso fazer um DESC no dual do MySQL, que é diferente do Oracle - mas foi introduzido especificamente o AIUI para permitir que a sintaxe do Oracle funcione no MySQL.

mysql> select 4 + 5 from dual;
+-------+
| 4 + 5 |
+-------+
|     9 |
+-------+
1 row in set (0.00 sec)

mysql> explain select 4 + 5 from dual;
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra          |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
|  1 | SIMPLE      | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | No tables used |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
1 row in set (0.00 sec)

mysql> desc dual;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'dual' at line 1
mysql> 
Vérace
fonte
2

No banco de dados oracle, a tabela Dual é basicamente usada para obter valor de pseudo-colunas. Ele contém as seguintes propriedades:

  1. É de propriedade do usuário sys
  2. Está disponível para todos os usuários
  3. Ele contém apenas uma coluna cujo nome é fictício com o tipo de dados Varchar2 (1). Essa coluna pode ter largura máxima de um caractere.

Se você quiser obter mais detalhes, clique aqui

Vipul
fonte