Spec-Zone.ru › MySQL 9.2

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 9.2. Кэш запросов был удалён в MySQL 9.2. Модификатор SQL_CACHE также был удалён. Модификатор SQL_NO_CACHE устарел и не оказывает никакого влияния; ожидается его удаление в будущей версии MySQL.

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

Spec-Zone.ru

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