15.2.13 Оператор SELECT
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_nameGROUP 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указывает таблицу или таблицы, из которых необходимо извлечь строки. Если вы указываете более одной таблицы, вы выполняете объединение. Подробнее о синтаксисе объединения см. в Разделе 15.2.13.2, «Фрагмент JOIN». Для каждой указанной таблицы можно необязательно указать псевдоним.table_referencestbl_name[[AS]alias] [index_hint]Использование подсказок индексов предоставляет оптимизатору информацию о том, как выбирать индексы во время обработки запроса. Подробное описание синтаксиса указания этих подсказок см. в Разделе 10.9.4, «Подсказки индексов».
Вы можете использовать
SET max_seeks_for_key=в качестве альтернативного способа, чтобы заставить MySQL предпочесть сканирование ключей вместо сканирования таблицы. См. Раздел 7.1.8, «Системные переменные сервера».value Вы можете обратиться к таблице в базе данных по умолчанию как
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_nameASalias_nametbl_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_nameFROMtbl_nameHAVINGcol_name> 0;Вместо этого напишите:
SELECT
col_nameFROMtbl_nameWHEREcol_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.)
-
Запрос
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_countLIMIT 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_countOFFSEToffsetЕсли
LIMITвстречается внутри выражения запроса в скобках и также применяется во внешнем запросе, результаты неопределены и могут измениться в будущих версиях MySQL. Форма
SELECT ... INTOоператораSELECTпозволяет записать результат запроса в файл или сохранить его в переменные. Дополнительная информация содержится в разделе 15.2.13.1, «Оператор SELECT ... INTO».-
Если вы используете
FOR UPDATEс движком хранения, использующим блокировки страниц или строк, строки, просмотренные запросом, будут заблокированы на запись до конца текущей транзакции.Вы не можете использовать
FOR UPDATEв качестве части оператораSELECTв таком запросе, какCREATE TABLE. (Если вы попытаетесь это сделать, запрос будет отклонен с ошибкой Невозможно обновить таблицу 'new_tableSELECT ... FROMold_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_nameFOR 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_nameFOR UPDATEиFOR SHAREзапросы к именованным таблицам. Например:SELECT * FROM t1, t2 FOR SHARE OF t1 FOR UPDATE OF t2;
Все таблицы, на которые ссылается блок запроса, блокируются, когда
OFопущено. Вследствие этого, использование запроса блокировки безtbl_nameOFв сочетании с другой блокировкой возвращает ошибку. Указание одной и той же таблицы в нескольких запросах блокировки возвращает ошибку. Если в оператореtbl_nameSELECTв качестве имени таблицы указан псевдоним, запрос блокировки может использовать только псевдоним. Если оператор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_RESULTMySQL напрямую использует временные таблицы на диске, если они созданы, и отдаёт предпочтение сортировке по сравнению с использованием временной таблицы с ключом на элементахGROUP BY. ДляSQL_SMALL_RESULTMySQL использует временные таблицы в памяти для хранения результирующей таблицы вместо использования сортировки. Обычно это не требуется. -
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.