Pourquoi dois-je choisir dans la double table?

15

Cela fonctionne dans les principaux systèmes de gestion de bases de données de relations les plus susceptibles d'apparaître sur StackOverflow / dba.stackexchange, à savoir SQL Server, MySQL, PostgreSQL et SQLite (WebSQL) .

select 'abc' abc, 1 def;

Cela ne fonctionne pas sur Oracle. Pourquoi devons-nous choisir parmi DUAL dans Oracle? La norme ISO / ANSI pour SQL requiert-elle une clause FROM pour les instructions SELECT ?


Éditer:

Par Bacon Bitréponse, il semble requis par la norme SQL.

Donc en réalité, parce que le nom DUAL est si mal approprié, si je devais créer une table et la nommer ATOM ou ONE, par exemple create table one (atom int);.. select 'abc' abc, 1 def FROM one;- Y a-t-il une pénalité de performance par rapport à SELECT .. FROM DUAL?

孔夫子
la source
Je pense que DB2 ne peut pas non plus faire selectsans from. DB2 possède une table factice similaire appelée SYSIBM.SYSDUMMY1 . De plus, vous le savez probablement déjà, mais quand vous select 'A' from dual, le dualtableau n'est pas vraiment accessible , ce qui répond à la question dans votre édition (qui méritait une nouvelle question btw).
Jack dit d'essayer topanswers.xyz
1
Il ne fonctionne pas dans "tous" les SGBD. Il existe plusieurs SGBD qui n'autorisent pas un SELECT sans un FROM. Le manuel répond à votre question sur les performances: docs.oracle.com/cd/E11882_01/server.112/e26088/…
a_horse_with_no_name
3
@JackDouglas: Vous avez raison. DB2 nécessite une FROMclause. Du haut de ma tête: Informix, Firebird et Apache Derby en ont également besoin.
a_horse_with_no_name
1
DB2 nécessite une clause FROM, mais une alternative consiste à utiliser une instruction comme values ('abc', 1). Vous pouvez bien sûr également sélectionner une telle déclaration:select abc from ( values ('abc',1) ) as t(abc,def)
Lennart

Réponses:

30

Strictement, oui, la FROMclause d'une SELECTdéclaration n'est pas facultative. La syntaxe de SQL-99 détaille la SELECTdéclaration de base et la FROMclause n'a pas de crochets autour. Cela indique que la norme considère qu'elle n'est pas facultative:

SELECT [ DISTINCT | ALL ]
{Column expression [ AS name ]} [ ,... ] | *
FROM <Table reference> [ {,<Table reference>} ... ]
[ WHERE search condition ]
[ GROUP BY Columns [ HAVING condition ] ]
[ORDER BY {col_name | expr | position} [ASC | DESC],...]                                     
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
[PROCEDURE procedure_name(argument_list)]
[INTO OUTFILE 'file_name' export_options |
 INTO DUMPFILE 'file_name' |
 INTO var_name [, var_name]]
[FOR UPDATE | LOCK IN SHARE MODE]

En utilisation réelle, les programmeurs et les administrateurs de base de données trouvent souvent utile de faire autre chose que de manipuler des données dans des tableaux ou de manipuler des tableaux et des structures de données. Ce type de chose dépasse largement le cadre de la norme SQL, qui s'intéresse davantage aux fonctionnalités de données qu'aux écrous et boulons d'implémentations spécifiques. Que nous voulions exécuter SELECT getdate()ou SELECT 1ou SELECT DB_NAME()(ou ce que votre dialecte préfère), nous ne voulons pas réellement de données d'une table.

Oracle choisit de résoudre l'écart standard et d'implémentation à l'aide d'un tableau factice avec la définition efficace suivante:

CREATE TABLE DUAL (
  DUMMY CHAR(1)
  )

INSERT INTO DUAL (DUMMY) VALUES ('X')

D'autres SGBDR supposent essentiellement qu'une table fictive est utilisée si aucun FROMn'est spécifié.

L' histoire de la table DUAL est sur Wikipédia:

La table DUAL a été créée par Charles Weiss de la société Oracle pour fournir une table de jonction dans les vues internes:

J'ai créé la table DUAL en tant qu'objet sous-jacent dans le dictionnaire de données Oracle. Il n'a jamais été conçu pour être vu lui-même, mais plutôt utilisé à l'intérieur d'une vue qui devait être interrogée. L'idée était que vous pouviez faire un JOIN à la table DUAL et créer deux lignes dans le résultat pour chaque ligne de votre table. Ensuite, en utilisant GROUP BY, la jointure résultante peut être résumée pour afficher la quantité de stockage pour l'étendue DATA et pour les extensions INDEX. Le nom, DUAL, semblait approprié pour le processus de création d'une paire de lignes à partir d'une seule.

La table DUAL d'origine contenait deux lignes (d'où son nom), mais par la suite, elle ne comportait qu'une seule ligne.

Lardons
la source
3
+1 et bienvenue sur dba.se. C'est une excellente réponse avec un peu d'histoire fascinante - j'espère que vous pouvez être encouragé à rester et à contribuer davantage :)
Jack dit essayer topanswers.xyz
4
Des heures de plaisir sans fin ont été faites par moi une fois quand un développeur a inséré quelques lignes de plus dans le dual. J'ai cassé plein de choses :) J'ai mis du temps à retrouver le coupable!
Philᵀᴹ
8

L'avantage dualest que l'optimiseur comprend dualune table spéciale à une ligne et une colonne (avec varchar2type de données) - lorsque vous l'utilisez dans des requêtes, il utilise ces connaissances lors du développement du plan.

Pourquoi devons-nous sélectionner dualdans Oracle?

Vous pouvez également sélectionner à partir de dualou à partir de vos propres tables, si vous le souhaitez.

Pour moi, je vais m'en tenir dualparce que je sais qu'il dualexiste. Je sais qu'il a au moins 1 et au plus 1 ligne. Je sais que l'optimiseur sait tout dualet fait la chose la plus efficace pour moi. L'optimiseur comprend qu'il duals'agit d'un tableau magique spécial à 1 ligne. Il s'est arrêté le select *parce qu'il doit y avoir une rangée là-dedans. C'est donc comme ça que ça fonctionne.

DevYudh
la source
"Je sais qu'il a au moins 1 et au plus 1 ligne." Eh bien, un idiot (ou un idiot) avec des privilèges DBA peut modifierDUAL . Faites attention!
Nick Chammas du
bien si cela vous arrive. révoquer tous les privilèges à l'exception de CRÉER UNE SESSION de cette personne Quelqu'un. et si le dual a été abandonné accidentellement par quelqu'un?
DevYudh
vous pouvez le créer en utilisant create table dual (dummy varchar2 (1)) storage (initial 1) ou flashback table dual to before drop
DevYudh
Eh bien, c'est un avantage d'utiliser DUAL par rapport à la sélection de l'expression à partir de toute autre table existante, mais cela n'explique pas quel est l'avantage d'avoir DUAL comme alternative pour ne pas avoir de FROM, comme dans PostgreSQL ou SQLServer
Danubian Sailor
@Lukasz Lech dans Oracle, il n'y a pas de SELECT sans FROM pour #MSSQL Serv: Il n'y a pas du tout besoin de table double dans SQL Server. mais si vous avez transféré votre code d'Oracle vers SQL Serv, vous pouvez créer un double en utilisant ce script CREATE TABLE DUAL (DUMMY VARCHAR (1)) GO INSERT INTO DUAL (DUMMY) VALUES ('X') GO but, I don't see any raison d'utiliser / créer une double table dans le serveur sql. et également MSSQL Serv et PostGRE SQL ne nécessitent pas de table
factice
1

Les deux autres réponses fournissent un bon contexte pour ma réponse.

Sur les bases de données Oracle, il est traditionnel et fiable. Il échouera sur d'autres bases de données qui n'ont pas de DUALtable. Il n'est pas nécessaire que vous l'utilisiez DUAL, mais je vous le recommande.

Les bases de données conformes aux normes nécessiteront une FROMclause spécifiant au moins la référence de la table. Si vous avez une table ORDERS, le remplacement suivant de la FROM DUALclause fonctionnerait:

FROM   orders
WHERE  rownum =1

Remplacez n'importe quelle table ou vue que vous pouvez sélectionner et cela fonctionnera. Remplacez une table ou une vue que vous ne pouvez pas sélectionner et elle échouera. DUALest plus fiable que si un DBA le brise, tous les utilisateurs peuvent le sélectionner et n'obtiendront qu'une seule ligne dans le jeu de résultats. (Il se casse parfois.)

Je ne connais pas de verbe conforme aux normes pour accéder aux données qui ne sont pas dans un tableau sans inclure une référence de tableau. Étant donné le peu d'accès à ces données, je ne vois pas un tel besoin. Bon nombre des cas que je rencontre peuvent être mieux traités de différentes manières.

BillThor
la source
2
SELECT CURRENT_TIMESTAMP FROM (VALUES(1)) V(C)est conforme aux normes, je crois, et ne repose sur aucune table particulière.
Martin Smith
@MartinSmith J'ai mis à jour ma réponse pour utiliser la référence de table. C'est ce que je voulais dire et aurais dû préciser.
BillThor