Почему я должен выбрать из двойной таблицы?


15

Это работает в основных системах управления базами данных Relation, которые чаще всего появляются в StackOverflow / dba.stackexchange, а именно в SQL Server, MySQL, PostgreSQL и SQLite (WebSQL) .

select 'abc' abc, 1 def;

Это не работает на Oracle. Почему нам нужно выбрать из DUAL в Oracle? Требует ли стандарт ISO / ANSI для SQL условия FROM для операторов SELECT ?


Редактировать:

За Bacon Bitответ «S, это , кажется , требуется стандартом SQL.

Так что на самом деле, потому что имя DUAL является таким неправильным, если бы я создал таблицу и назвал ее ATOM или ONE, например create table one (atom int);... select 'abc' abc, 1 def FROM one;- Есть ли снижение производительности по сравнению с SELECT .. FROM DUAL?


Я думаю, что DB2 также не может обойтись selectбез from. В DB2 есть аналогичная фиктивная таблица SYSIBM.SYSDUMMY1 . Кроме того, вы, вероятно, уже знаете это, но когда вы select 'A' from dual, к dualтаблице, на самом деле нет доступа , что отвечает на вопрос в вашем редактировании (который заслуживает нового вопроса между прочим).
Джек говорит, попробуйте topanswers.xyz

1
Это не работает во «всех» СУБД. Есть несколько СУБД, которые не позволяют SELECT без FROM. Руководство отвечает на ваш вопрос о производительности: docs.oracle.com/cd/E11882_01/server.112/e26088/…
a_horse_with_no_name

3
@JackDouglas: Вы правы. DB2 требует FROMпункт. Сверху головы: Informix, Firebird и Apache Derby также требуют этого.
a_horse_with_no_name

1
DB2 требует предложение FROM, но альтернативой является использование такого выражения, как values ('abc', 1). Можно, конечно, также выбрать из такого утверждения:select abc from ( values ('abc',1) ) as t(abc,def)
Леннарт

Ответы:


30

Строго говоря, да, FROMпредложение SELECTне является обязательным. Синтаксис для SQL-99 детализирует основную SELECTстатистику, и в FROMпредложении нет квадратных скобок. Это означает, что стандарт считает его необязательным:

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]

При реальном использовании программисты и администраторы баз данных часто считают полезным делать что-то, кроме манипулирования данными в таблицах или манипулирования таблицами и структурами данных. Этот тип вещей в значительной степени выходит за рамки стандарта SQL, который связан с функциями данных больше, чем суть конкретных реализаций. Хотим ли мы запускать SELECT getdate()или SELECT 1или SELECT DB_NAME()(или как бы вы ни предпочитали ваш диалект), нам на самом деле не нужны данные из таблицы.

Oracle решает проблему несоответствия стандарту и реализации с использованием фиктивной таблицы со следующим эффективным определением:

CREATE TABLE DUAL (
  DUMMY CHAR(1)
  )

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

Другие РСУБД по существу предполагают, что используется фиктивная таблица, если не FROMуказано иное.

История DUAL таблицы на Википедии:

Таблица DUAL была создана Чарльзом Вейссом из корпорации Oracle для предоставления таблицы для объединения во внутренние представления:

Я создал таблицу DUAL как базовый объект в Oracle Data Dictionary. Он никогда не предназначался для того, чтобы его видели, а вместо этого использовался внутри представления, которое, как ожидалось, будет запрошено Идея заключалась в том, что вы можете выполнить JOIN к таблице DUAL и создать две строки в результате для каждой строки в вашей таблице. Затем с помощью GROUP BY полученное объединение можно суммировать, чтобы показать объем хранилища для экстента DATA и экстента (ов) INDEX. Название DUAL казалось подходящим для процесса создания пары строк из одного.

Исходная таблица DUAL содержала две строки (отсюда и название), но впоследствии в ней была только одна строка.


3
+1 и добро пожаловать на dba.se. Это отличный ответ с увлекательной историей - я надеюсь, что вас могут побудить остаться и внести свой вклад :)
Джек говорит попробуйте topanswers.xyz

4
Однажды я провел часы бесконечного веселья, когда разработчик вставил еще несколько строк в двойной. Сломал много вещей :) Потребовалось время, чтобы выследить преступника!
Philᵀᴹ

8

Преимущество, dualкоторое понимает оптимизатор, dual- это специальная таблица из одной строки и одного столбца (с varchar2типом данных) - когда вы используете ее в запросах, он использует эти знания при разработке плана.

Почему нам нужно выбрать из dualв Oracle?

Вы можете выбрать из dualили из ваших собственных таблиц, вы можете, если хотите.

Для меня я буду придерживаться, dualпотому что я знаю, что dualсуществует. Я знаю, что у него есть как минимум 1 и максимум 1 ряд. Я знаю, что оптимизатор знает все dualи делает для меня самое эффективное. Оптимизатор понимает, dualчто это волшебная специальная таблица из 1 строки. Он остановился на том, select *что там должен быть один ряд. Так что это так, как это работает.


«Я знаю, у него есть как минимум 1 и максимум 1 ряд». Ну, придурок (или идиот) с привилегиями администратора может изменитьсяDUAL . Быть осторожен!
Ник Чаммас

хорошо, если это случится с тобой. отменить все привилегии, кроме СОЗДАТЬ СЕССИЯ от этого кого-то человека. а что, если дуал был случайно уронен кем-то?
DevYudh

Вы можете создать его, используя хранилище create table dual (dummy varchar2 (1)) (начальная 1) или таблицу flashback, двойную до удаления
DevYudh

Что ж, это преимущество в использовании DUAL по сравнению с выбором выражения из любой другой существующей таблицы, но оно не объясняет, в чем преимущество наличия DUAL в качестве альтернативы отсутствия необходимости иметь FROM, как в PostgreSQL или SQLServer
Danubian Sailor

@Lukasz Лех в Oracle нет SELECT без FROM для #MSSQL Serv: вообще нет необходимости в двойной таблице в SQL Server. но если вы перенесли свой код из Oracle в SQL Serv, вы можете создать двойной с помощью этого скрипта CREATE TABLE DUAL (DUMMY VARCHAR (1)) GO INSERT INTO DUAL (DUMMY) VALUES ('X') GO, но я не вижу никаких причина использовать / создать двойную таблицу на сервере SQL. а также MSSQL Serv и PostGRE SQL не требуют
фиктивной

1

Два других ответа обеспечивают хороший фон для моего ответа.

На базах данных Oracle это традиционно и надежно. Это не удастся на других базах данных, которые не имеют DUALтаблицы. Это не обязательно, что вы используете DUAL, но я бы порекомендовал вам сделать.

Для совместимых со стандартами баз данных потребуется FROMпункт, в котором будет указана хотя бы ссылка на таблицу. Если у вас есть таблица FROM DUALORDERS, сработает следующая замена для этого предложения:

FROM   orders
WHERE  rownum =1

Замените любую таблицу или представление, из которого вы можете выбрать, и это будет работать. Замените таблицу или представление, из которого вы не можете выбрать, и это не удастся. DUALявляется более надежным, так как запрещает администратору базы данных нарушать его, все пользователи могут выбирать из него и получат только одну строку в наборе результатов. (Это иногда ломается.)

Мне неизвестен глагол, соответствующий стандартам, для доступа к данным, которых нет в таблице без ссылки на таблицу. Учитывая, как мало я получаю доступ к таким данным, я не вижу такой необходимости. Во многих случаях, с которыми я сталкиваюсь, лучше разбираться по-разному.


2
SELECT CURRENT_TIMESTAMP FROM (VALUES(1)) V(C) я верю стандарту и не полагаюсь ни на какой конкретный стол.
Мартин Смит

@MartinSmith Я обновил свой ответ, чтобы использовать ссылку на таблицу. Это то, что я имел в виду и должен был указать.
BillThor
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.