Spec-Zone.ru › MySQL 8.4

15.2.13 Оператор SELECT

  • 15.2.13.1 Оператор SELECT ... INTO
  • 15.2.13.2 Оператор JOIN
SELECT
    [ALL | DISTINCT | DISTINCTROW ]
    [HIGH_PRIORITY]
    [STRAIGHT_JOIN]
    [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
    [SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
    select_expr [, select_expr] ...
    [into_option]
    [FROM table_references
      [PARTITION partition_list]]
    [WHERE where_condition]
    [GROUP BY {col_name | expr | position}, ... [WITH ROLLUP]]
    [HAVING where_condition]
    [WINDOW window_name AS (window_spec)
        [, window_name AS (window_spec)] ...]
    [ORDER BY {col_name | expr | position}
      [ASC | DESC], ... [WITH ROLLUP]]
    [LIMIT {[offset,] row_count | row_count OFFSET offset}]
    [into_option]
    [FOR {UPDATE | SHARE}
        [OF tbl_name [, tbl_name] ...]
        [NOWAIT | SKIP LOCKED]
      | LOCK IN SHARE MODE]
    [into_option]

into_option: {
    INTO OUTFILE 'file_name'
        [CHARACTER SET charset_name]
        export_options
  | INTO DUMPFILE 'file_name'
  | INTO var_name [, var_name] ...
}

export_options:
    [{FIELDS | COLUMNS}
        [TERMINATED BY 'string']
        [[OPTIONALLY] ENCLOSED BY 'char']
        [ESCAPED BY 'char']
    ]
    [LINES
        [STARTING BY 'string']
        [TERMINATED BY 'string']
    ]

SELECT используется для извлечения строк, выбранных из одной или нескольких таблиц, и может включать операции UNION и подзапросы. Также поддерживаются операции INTERSECT и EXCEPT. Операторы UNION, INTERSECT и EXCEPT описаны более подробно в этом разделе. См. также Раздел 15.2.15, «Подзапросы».

Оператор SELECT может начинаться с предложения WITH для определения общих табличных выражений, доступных в операторе SELECT. См. Раздел 15.2.20, «WITH (Общие табличные выражения)».

Наиболее часто используемыми предложениями в операторах SELECT являются следующие:

  • Каждый select_expr указывает столбец, который вы хотите извлечь. Должен быть хотя бы один select_expr.

  • table_references указывает таблицу или таблицы, из которых необходимо извлечь строки. Его синтаксис описан в Разделе 15.2.13.2, «Оператор JOIN».

  • SELECT поддерживает явное выделение разделов с помощью предложения PARTITION со списком разделов или подразделов (или того и другого) после имени таблицы в table_reference (см. Раздел 15.2.13.2, «Оператор JOIN»). В этом случае строки выбираются только из указанных разделов, а все остальные разделы таблицы игнорируются. Более подробная информация и примеры приведены в Разделе 26.5, «Выбор разделов».

  • Предложение WHERE, если задано, указывает условие или условия, которым должны удовлетворять строки, чтобы быть выбранными. where_condition — это выражение, которое вычисляется как истинное для каждой строки, подлежащей выбору. Если предложение WHERE отсутствует, запрос выбирает все строки.

    В выражении WHERE можно использовать любые функции и операторы, поддерживаемые MySQL, кроме агрегатных (групповых) функций. См. Раздел 11.5, «Выражения» и Главу 14, Функции и операторы.

Оператор SELECT также может использоваться для извлечения строк, вычисленных без ссылки на какую-либо таблицу.

Например:

mysql> SELECT 1 + 1;
        -> 2

Разрешается указать DUAL как псевдоним таблицы в ситуациях, когда таблицы не ссылаются:

mysql> SELECT 1 + 1 FROM DUAL;
        -> 2

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

В общем случае предложения должны быть указаны в точном порядке, показанном в описании синтаксиса. Например, предложение HAVING должно следовать за предложением GROUP BY и предшествовать предложению ORDER BY. Предложение INTO, если оно присутствует, может находиться в любом положении, указанном в описании синтаксиса, но в данном операторе может быть только один раз, а не в нескольких позициях. Более подробная информация о INTO приведена в Разделе 15.2.13.1, «Оператор SELECT ... INTO».

Список select_expr терминов образует список выбора, указывающий, какие столбцы извлекать. Элементы списка указывают столбец, выражение или могут использовать *-сокращение:

  • Список выбора, состоящий только из одного неуточнённого *, может использоваться в качестве сокращения для выбора всех столбцов из всех таблиц:

    SELECT * FROM t1 INNER JOIN t2 ...
    
  • tbl_name.* может использоваться в качестве уточнённого сокращения для выбора всех столбцов из указанной таблицы:

    SELECT t1.*, t2.* FROM t1 INNER JOIN t2 ...
    
  • Если у таблицы есть скрытые столбцы, * и tbl_name.* их не включают. Чтобы они были включены, скрытые столбцы должны быть указаны явно.

  • Использование неуточнённого * с другими элементами в списке выбора может привести к синтаксической ошибке. Например:

    SELECT id, * FROM t1
    

    Чтобы избежать этой проблемы, используйте уточнённую ссылку на tbl_name.*:

    SELECT id, t1.* FROM t1
    

    Используйте уточнённые ссылки на tbl_name.* для каждой таблицы в списке выбора:

    SELECT AVG(score), t1.* FROM t1 ...
    

В следующем списке приводится дополнительная информация об остальных предложениях SELECT:

  • Выражению select_expr можно присвоить псевдоним, используя AS alias_name. Псевдоним используется в качестве имени столбца выражения и может быть использован в GROUP BY, ORDER BY или HAVING фрагментах. Например:

    SELECT CONCAT(last_name,', ',first_name) AS full_name
      FROM mytable ORDER BY full_name;
    

    Ключевое слово AS необязательно при присвоении псевдонима select_expr с идентификатором. Предшествующий пример можно было записать так:

    SELECT CONCAT(last_name,', ',first_name) full_name
      FROM mytable ORDER BY full_name;
    

    Однако, поскольку ключевое слово AS необязательно, может возникнуть неявная проблема, если вы забудете запятую между двумя выражениями select_expr: MySQL интерпретирует второе как имя псевдонима. Например, в следующем операторе columnb интерпретируется как имя псевдонима:

    SELECT columna columnb FROM mytable;
    

    По этой причине рекомендуется всегда явно использовать AS при указании псевдонимов столбцов.

    Ссылаться на псевдоним столбца в фрагменте WHERE недопустимо, так как значение столбца может быть еще не определено во время выполнения фрагмента WHERE. См. Раздел B.3.4.4, «Проблемы с псевдонимами столбцов».

  • Фрагмент FROM table_references указывает таблицу или таблицы, из которых необходимо извлечь строки. Если вы указываете более одной таблицы, вы выполняете объединение. Подробнее о синтаксисе объединения см. в Разделе 15.2.13.2, «Фрагмент JOIN». Для каждой указанной таблицы можно необязательно указать псевдоним.

    tbl_name [[AS] alias] [index_hint]
    

    Использование подсказок индексов предоставляет оптимизатору информацию о том, как выбирать индексы во время обработки запроса. Подробное описание синтаксиса указания этих подсказок см. в Разделе 10.9.4, «Подсказки индексов».

    Вы можете использовать SET max_seeks_for_key=value в качестве альтернативного способа, чтобы заставить MySQL предпочесть сканирование ключей вместо сканирования таблицы. См. Раздел 7.1.8, «Системные переменные сервера».

  • Вы можете обратиться к таблице в базе данных по умолчанию как tbl_name, или как db_name.tbl_name, чтобы явно указать базу данных. Вы можете обратиться к столбцу как col_name, tbl_name.col_name, или db_name.tbl_name.col_name. Префикс tbl_name или db_name.tbl_name для ссылки на столбец указывать не нужно, если эта ссылка не является неоднозначной. Подробнее об неоднозначности, требующей более явных форм ссылок на столбец, см. в Разделе 11.2.2, «Квалификаторы идентификаторов».

  • Ссылка на таблицу может быть переименована, используя tbl_name AS alias_name или tbl_name alias_name. Эти операторы эквивалентны:

    SELECT t1.name, t2.salary FROM employee AS t1, info AS t2
      WHERE t1.name = t2.name;
    
    SELECT t1.name, t2.salary FROM employee t1, info t2
      WHERE t1.name = t2.name;
    
  • На столбцы, выбранные для вывода, можно ссылаться в ORDER BY и GROUP BY фрагментах, используя имена столбцов, псевдонимы столбцов или позиции столбцов. Позиции столбцов — это целые числа, начинающиеся с 1:

    SELECT college, region, seed FROM tournament
      ORDER BY region, seed;
    
    SELECT college, region AS r, seed AS s FROM tournament
      ORDER BY r, s;
    
    SELECT college, region, seed FROM tournament
      ORDER BY 2, 3;
    

    Для сортировки в обратном порядке добавьте ключевое слово DESC (по убыванию) к имени столбца в фрагменте ORDER BY, по которому вы сортируете. По умолчанию сортировка происходит по возрастанию; это можно явно указать, используя ключевое слово ASC.

    Если ORDER BY встречается в скобочном выражении запроса и также применяется во внешнем запросе, результаты неопределенны и могут измениться в будущей версии MySQL.

    Использование позиций столбцов устарело, так как синтаксис удален из стандарта SQL.

  • Когда вы используете ORDER BY или GROUP BY для сортировки столбца в SELECT, сервер сортирует значения, используя только начальное количество байтов, указанное системной переменной max_sort_length.

  • MySQL расширяет использование GROUP BY, разрешая выбор полей, не упомянутых во фрагменте GROUP BY. Если вы не получаете ожидаемых результатов от запроса, обратитесь к описанию GROUP BY в Разделе 14.19, «Функции агрегирования».

  • Фрагмент HAVING, как и фрагмент WHERE, задает условия отбора. Фрагмент WHERE задаёт условия на столбцах в списке выбора, но не может ссылаться на агрегатные функции. Фрагмент HAVING задаёт условия на группах, как правило, сформированных фрагментом GROUP BY. Результат запроса включает только группы, удовлетворяющие условиям HAVING. (Если фрагмент GROUP BY отсутствует, все строки неявно образуют одну агрегированную группу.)

    Фрагмент HAVING применяется практически в последнюю очередь, непосредственно перед отправкой данных клиенту, без оптимизации. (LIMIT применяется после HAVING.)

    Стандарт SQL требует, чтобы фрагмент HAVING ссылался только на столбцы в фрагменте GROUP BY или на столбцы, используемые в агрегатных функциях. Однако MySQL поддерживает расширение этого поведения и допускает, что фрагмент HAVING может ссылаться на столбцы в списке SELECT и столбцы во внешних подзапросах.

    Если фрагмент HAVING ссылается на неоднозначный столбец, возникает предупреждение. В следующем операторе col2 является неоднозначным, потому что используется как псевдоним и как имя столбца:

    SELECT COUNT(col1) AS col2 FROM t GROUP BY col2 HAVING col2 = 2;
    

    Предпочтение отдаётся поведению стандартного SQL, поэтому если имя столбца HAVING используется как в GROUP BY, так и в качестве псевдонима столбца в списке столбцов выборки, предпочтение отдаётся столбцу в списке GROUP BY столбцов.

  • Не используйте HAVING для элементов, которые должны быть во фрагменте WHERE. Например, не пишите следующее:

    SELECT col_name FROM tbl_name HAVING col_name > 0;
    

    Вместо этого напишите:

    SELECT col_name FROM tbl_name WHERE col_name > 0;
    
  • Фрагмент HAVING может ссылаться на агрегатные функции, которых фрагмент WHERE не может:

    SELECT user, MAX(salary) FROM users
      GROUP BY user HAVING MAX(salary) > 10;
    

    (Это не работало в некоторых старых версиях MySQL.)

  • MySQL допускает дублирование имён столбцов. То есть, может быть более одного select_expr с одинаковым именем. Это расширение стандартного SQL. Поскольку MySQL также допускает GROUP BY и HAVING ссылаться на select_expr значения, это может привести к неоднозначности:

    SELECT 12 AS a, a FROM t GROUP BY a;
    

    В этом операторе оба столбца имеют имя a. Чтобы убедиться, что используется правильный столбец для группировки, используйте разные имена для каждого select_expr.

  • Фрагмент WINDOW, если он присутствует, определяет именованные окна, на которые могут ссылаться оконные функции. Подробнее см. в Разделе 14.20.4, «Именованные окна».

  • MySQL разрешает неквалифицированные ссылки на столбцы или псевдонимы во фрагментах ORDER BY, выполняя поиск в значениях select_expr, а затем в столбцах таблиц в фрагменте FROM. Для GROUP BY или HAVING фрагментов он ищет в фрагменте FROM перед поиском в значениях select_expr. (Для GROUP BY и HAVING это отличается от поведения до MySQL 5.0, которое использовало те же правила, что и для ORDER BY.)

END_OF_DOCUMENT_MARKER
  • Запрос LIMIT может использоваться для ограничения количества строк, возвращаемых оператором SELECT. Запрос LIMIT принимает один или два числовых аргумента, которые должны быть неотрицательными целочисленными константами, за исключением следующих случаев:

    • В подготовленных запросах параметры LIMIT могут быть указаны с использованием маркеров замены ?.

    • В хранимых программах параметры LIMIT могут быть указаны с использованием целочисленных параметров процедуры или локальных переменных.

    При использовании двух аргументов, первый аргумент указывает смещение первой строки для возврата, а второй — максимальное количество строк для возврата. Смещение начальной строки равно 0 (а не 1):

    SELECT * FROM tbl LIMIT 5,10;  # Retrieve rows 6-15
    

    Чтобы получить все строки с определенного смещения до конца набора результатов, можно использовать большое число для второго параметра. Данный запрос получает все строки с 96-й строки до последней:

    SELECT * FROM tbl LIMIT 95,18446744073709551615;
    

    При использовании одного аргумента, его значение определяет количество строк, которые нужно вернуть с начала набора результатов:

    SELECT * FROM tbl LIMIT 5;     # Retrieve first 5 rows
    

    Другими словами, LIMIT row_count эквивалентно LIMIT 0, row_count.

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

    SET @a=1;
    PREPARE STMT FROM 'SELECT * FROM tbl LIMIT ?';
    EXECUTE STMT USING @a;
    

    Следующие запросы возвращают строки со второй по шестую из таблицы tbl:

    SET @skip=1; SET @numrows=5;
    PREPARE STMT FROM 'SELECT * FROM tbl LIMIT ?, ?';
    EXECUTE STMT USING @skip, @numrows;
    

    Для совместимости с PostgreSQL, MySQL также поддерживает синтаксис LIMIT row_count OFFSET offset.

    Если LIMIT встречается внутри выражения запроса в скобках и также применяется во внешнем запросе, результаты неопределены и могут измениться в будущих версиях MySQL.

  • Форма SELECT ... INTO оператора SELECT позволяет записать результат запроса в файл или сохранить его в переменные. Дополнительная информация содержится в разделе 15.2.13.1, «Оператор SELECT ... INTO».

  • Если вы используете FOR UPDATE с движком хранения, использующим блокировки страниц или строк, строки, просмотренные запросом, будут заблокированы на запись до конца текущей транзакции.

    Вы не можете использовать FOR UPDATE в качестве части оператора SELECT в таком запросе, как CREATE TABLE new_table SELECT ... FROM old_table .... (Если вы попытаетесь это сделать, запрос будет отклонен с ошибкой Невозможно обновить таблицу 'old_table' во время создания 'new_table'.)

    FOR SHARE и LOCK IN SHARE MODE устанавливают общие блокировки, которые разрешают другим транзакциям читать просмотренные строки, но не обновлять или удалять их. FOR SHARE и LOCK IN SHARE MODE эквивалентны. Однако, FOR SHARE, как и FOR UPDATE, поддерживает опции NOWAIT, SKIP LOCKED и OF tbl_name. FOR SHARE — замена для LOCK IN SHARE MODE, но LOCK IN SHARE MODE остается доступной для обратной совместимости.

    NOWAIT заставляет запрос FOR UPDATE или FOR SHARE выполняться немедленно, возвращая ошибку, если строковая блокировка не может быть получена из-за блокировки, удерживаемой другой транзакцией.

    SKIP LOCKED заставляет запрос FOR UPDATE или FOR SHARE выполняться немедленно, исключая строки из набора результатов, которые заблокированы другой транзакцией.

    Опции NOWAIT и SKIP LOCKED небезопасны для репликации на основе операторов.

    Примечание

    Запросы, пропускающие заблокированные строки, возвращают несогласованный вид данных. Поэтому SKIP LOCKED не подходит для общей транзакционной работы. Однако он может использоваться для предотвращения конфликтов блокировок, когда несколько сеансов обращаются к одной и той же таблице, подобной очереди.

    OF tbl_name применяет FOR UPDATE и FOR SHARE запросы к именованным таблицам. Например:

    SELECT * FROM t1, t2 FOR SHARE OF t1 FOR UPDATE OF t2;
    

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

    Дополнительную информацию о FOR UPDATE и FOR SHARE см. в разделе 17.7.2.4, «Блокирующие чтения». Дополнительную информацию об опциях NOWAIT и SKIP LOCKED см. в разделе про блокировку чтения с использованием NOWAIT и SKIP LOCKED.

После ключевого слова SELECT можно использовать множество модификаторов, которые влияют на работу оператора. HIGH_PRIORITY, STRAIGHT_JOIN и модификаторы, начинающиеся с SQL_, являются расширениями MySQL для стандартного SQL.

  • Модификаторы ALL и DISTINCT определяют, должны ли возвращаться дублирующиеся строки. ALL (по умолчанию) указывает, что должны возвращаться все совпадающие строки, включая дубликаты. DISTINCT указывает на удаление дублирующих строк из набора результатов. Указание обоих модификаторов является ошибкой. DISTINCTROW является синонимом для DISTINCT.

    DISTINCT может использоваться с запросом, который также использует WITH ROLLUP.

  • HIGH_PRIORITY придает запросу SELECT более высокий приоритет по сравнению с оператором, обновляющим таблицу. Использовать следует только для очень быстрых запросов, которые необходимо выполнить сразу. Запрос SELECT HIGH_PRIORITY, выпущенный, пока таблица заблокирована для чтения, выполняется, даже если оператор обновления ожидает освобождения таблицы. Это влияет только на движки хранилища, использующие только блокировку на уровне таблицы (такие как MyISAM, MEMORY и MERGE).

    HIGH_PRIORITY нельзя использовать с операторами SELECT, которые являются частью UNION.

  • STRAIGHT_JOIN заставляет оптимизатор объединять таблицы в том порядке, в котором они указаны в предложении FROM. Это можно использовать для ускорения запроса, если оптимизатор объединяет таблицы в неэффективном порядке. STRAIGHT_JOIN также может использоваться в списке table_references. См. Раздел 15.2.13.2, “Предложение JOIN”.

    STRAIGHT_JOIN не применяется к любой таблице, которую оптимизатор обрабатывает как таблицу const или system. Такая таблица генерирует одну строку, считывается на стадии оптимизации выполнения запроса и ссылки на её столбцы заменяются соответствующими значениями столбцов до продолжения выполнения запроса. Эти таблицы появляются первыми в плане запроса, отображаемом EXPLAIN. См. Раздел 10.8.1, “Оптимизация запросов с помощью EXPLAIN”. Это исключение может не применяться к таблицам const или system, которые используются на стороне, дополненной NULL, внешнего соединения (то есть правой таблице LEFT JOIN или левой таблице RIGHT JOIN).

  • SQL_BIG_RESULT или SQL_SMALL_RESULT могут использоваться с GROUP BY или DISTINCT, чтобы указать оптимизатору, что набор результатов содержит много строк или является небольшим соответственно. Для SQL_BIG_RESULT MySQL напрямую использует временные таблицы на диске, если они созданы, и отдаёт предпочтение сортировке по сравнению с использованием временной таблицы с ключом на элементах GROUP BY. Для SQL_SMALL_RESULT MySQL использует временные таблицы в памяти для хранения результирующей таблицы вместо использования сортировки. Обычно это не требуется.

  • SQL_BUFFER_RESULT заставляет результат помещаться во временную таблицу. Это помогает MySQL раньше освободить блокировки таблицы и помогает в случаях, когда на отправку набора результатов клиенту уходит много времени. Данный модификатор может использоваться только для операторов SELECT верхнего уровня, а не для подзапросов или последующих UNION.

  • SQL_CALC_FOUND_ROWS сообщает MySQL, чтобы он вычислил количество строк в наборе результатов, игнорируя любое предложение LIMIT. Количество строк затем можно получить с помощью SELECT FOUND_ROWS(). См. Раздел 14.15, “Функции информации”.

    Примечание

    Модификатор запроса SQL_CALC_FOUND_ROWS и сопровождающая его функция FOUND_ROWS() устарели; ожидается их удаление в будущей версии MySQL. См. описание FOUND_ROWS() для получения информации об альтернативной стратегии.

  • Модификаторы SQL_CACHE и SQL_NO_CACHE использовались с кэшем запросов до MySQL 8.4. Кэш запросов был удалён в MySQL 8.4. Модификатор SQL_CACHE также был удалён. Модификатор SQL_NO_CACHE устарел и не имеет эффекта; ожидается его удаление в будущей версии MySQL.

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-8.4-en/select.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API