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