Я всегда проповедовал своим разработчикам это SELECT *
является злым и должен избегаться как чумы.
Есть ли какие-либо случаи, где это может быть выровнено по ширине?
Я не говорю о COUNT(*)
- который может выяснить большинство оптимизаторов.
Править
Я говорю о производственном коде.
И один яркий пример, который я видел этой плохой практики, был приложением asp прежней версии, которое использовало select *
в хранимой процедуре, и используемый ADO
циклично выполняться через возвращенные записи, но получило столбцы индексом. Можно вообразить то, что произошло, когда новое поле было добавлено где-нибудь кроме конца cписка полей.
Я - довольно счастливое использование *
в контрольных триггерах.
В этом случае это может на самом деле доказать преимущество, потому что это гарантирует, что, если дополнительные столбцы добавляются к базовой таблице, она повысит ошибку, таким образом, об этом нельзя будет забыть для контакта с этим в контрольном триггере и/или контрольной структуре таблицы.
(Как dotjoe) я - также счастливое использование его в полученных таблицах и выражениях таблицы столбца. Хотя я обычно делаю это наоборот.
WITH t
AS (SELECT *,
ROW_NUMBER() OVER (ORDER BY a) AS RN
FROM foo)
SELECT a,
b,
c,
RN
FROM t;
я главным образом знаком с SQL Server, и там по крайней мере, оптимизатор не имеет никакой проблемы при распознавании, что только столбцы a,b,c
будут требоваться, и использование *
во внутреннем выражении таблицы не вызывает ненужного служебного получения и отбрасывания ненужных столбцов.
В принципе SELECT *
должен быть прекрасным в представлении, а также это - финал SELECT
от представления, где этого нужно избежать однако в SQL Server, это может вызвать проблемы, поскольку это хранит метаданные столбца для представлений, которые автоматически не обновляются, когда изменение базовых таблиц и использование *
могут привести к запутывающим и неправильным результатам, если sp_refreshview
не выполняется для обновления этих метаданных.
Если Вы хотите найти все столбцы и хотеть порядок, можно сделать следующее (по крайней мере, при использовании MySQL):
SHOW COLUMNS FROM mytable FROM mydb;
(1)
Вы видите каждую релевантную информацию обо всех своих полях. Можно предотвратить проблемы с типами, и можно знать наверняка все имена столбцов. Эта команда очень быстра, потому что Вы просто просите структуру таблицы. От результатов Вы выберете все имя и создадите строку как это:
"select " + fieldNames[0] + ", fieldNames[1]" + ", fieldNames[2] from mytable". (2)
, Если Вы не хотите выполнять две отдельных команды MySQL, потому что команда MySQL является дорогой, можно включать (1) и (2) в хранимую процедуру, которая будет иметь результаты как параметр, тот способ, которым Вы просто назовете хранимую процедуру и каждую команду, и поколение данных произойдет в сервере базы данных.
Я знаю, что очень опаздываю стороне, но я внесу это, я использую выбор * каждый раз, когда я знаю, что буду всегда хотеть все столбцы независимо от имен столбцов. Это может быть скорее случай края, но в организации хранилищ данных, я мог бы хотеть подготовить всю таблицу из приложения сторонних производителей. Мой стандартный процесс для этого должен отбросить таблицу подготовки и работать
select *
into staging.aTable
from remotedb.dbo.aTable
Да, если схема на изменениях удаленной таблицы, нисходящие зависимости могут бросить ошибки, но это собирается произойти независимо.
Select *
в производственном коде допустимо любое время когда:
, Почему я хотел бы издержки возвращения и необходимости волноваться об изменении соответствующих хранимых процедур, каждый раз, когда я добавляю поле к таблице?
, Почему я даже хотел бы должным быть думать о том, выбрал ли я правые стороны поля, когда подавляющее большинство времени я хочу большинство из них так или иначе и подавляющее большинство нескольких раз, я не делаю, что-то еще - узкое место?
, Если у меня есть проблема реального исполнения затем, я возвращусь и зафиксирую это. Иначе в моей среде, это просто преждевременно (и дорого), оптимизация, которой я могу обойтись без.
<час>Редактирование.. после обсуждения я предполагаю, что добавил бы к этому:
... и где люди не сделали других нежелательных вещей, любят попробованный получать доступ к столбцам (i), который мог прервать другие ситуации так или иначе :)
Зависит от контекста производственного программного обеспечения.
, Если Вы пишете простой уровень доступа к данным для инструмента управления таблицы, где пользователь будет выбирать таблицы и просматривать результаты в сетке, затем это казалось бы *, ВЫБОР ** прекрасен.
, Другими словами, если Вы принимаете решение обработать "выбор полей" через некоторые другие средства (как в автоматических или указанных пользователями фильтрах после получения набора результатов) затем, это кажется очень хорошо.
, Если, с другой стороны, мы говорим о своего рода программном обеспечении предприятия с бизнес-правилами, определенной схемой, и т.д.... затем, я соглашаюсь, что *ВЫБОР ** является плохой идеей.
РЕДАКТИРОВАНИЕ: О, и когда исходная таблица является хранимой процедурой для триггера или представления, "*SELECT **" должен быть прекрасным, потому что Вы управляете набором результатов через другие средства (определение представления или набор результатов сохраненного proc).
я должен был несколько раз отображать данные из таблицы, имена столбцов которой были неизвестны. Таким образом, я сделал SELECT *
и получил имена столбцов во время выполнения.
мне вручили приложение прежней версии, где таблица имела 200 столбцов, и представление имело 300. Рискозависимость от SELECT *
была бы не хуже, чем из списка всех 300 столбцов явно.
Да, но только в ситуациях, где намерение состоит в том, чтобы на самом деле получить все столбцы от таблицы, не потому что Вы хотите все столбцы, которые в настоящее время имеет таблица.
, Например, в одной системе, что я продолжил работать, у нас был UDFs (Определяемые пользователем Поля), где пользователь мог выбрать поля, они хотели на отчете, порядке, а также фильтрации. При создании набора результатов это имело больше смысла только к "выбору *" из временных таблиц, которые я создавал вместо того, чтобы иметь необходимость отслеживать, которых столбцы были активны.
Возможно, что Вы хотели бы разработать свой DB и приложение так, чтобы можно было добавить столбец к таблице, не будучи должен переписать приложение. Если Ваше приложение, по крайней мере, проверяет имена столбцов, оно может безопасно использовать SELECT *
и рассматривать дополнительные столбцы с некоторым соответствующим действием по умолчанию. Уверенный приложение могло консультироваться с системными каталогами (или определенные для приложения каталоги) для получения информации о столбце, но при некоторых обстоятельствах SELECT *
синтаксический сахар для того, чтобы сделать это.
существуют очевидные риски для этого, однако, и добавление необходимой логики к приложению для создания, это надежный могло просто означать копировать запрос DB, регистрируется в менее подходящем носителе. Я не собираюсь размышлять о том, как расходы и доходы обменивают в реальной жизни.
На практике, я придерживаюсь SELECT *
для 3 случаев (некоторые упомянутые в других ответах:
EXISTS
предикат. Как еще делают разработчики phpmyadmin
удостоверяются, что они отображают все поля Ваших Таблиц базы данных?
Я привык выбор * для таблиц запроса, оптимизированных для чтения (денормализованные, плоские данные). Очень выгодный начиная с цели таблиц должны были просто поддерживать различные представления в приложении.
О единственной вещи, о которой я могу думать, был бы при разработке утилиты или приложения инструмента SQL, которое пишется для выполнения против любой базы данных. Даже здесь, хотя, я был бы склонен запрашивать системные таблицы, чтобы получить структуру таблицы и затем создать любой необходимый запрос из этого.
было одно недавнее место, где моя команда использовала SELECT *
, и я думаю, что она была в порядке... у нас есть база данных, которая существует как фасад против другой базы данных (назовите ее DB_Data), таким образом, она, прежде всего, составлена из представлений против таблиц в другой базе данных. Когда мы генерируем представления, мы на самом деле генерируем списки столбцов, но существует один набор представлений в базе данных DB_Data, которые автоматически сгенерированы, поскольку строки добавляются к универсальной справочной таблице (этот дизайн существовал, прежде чем я добрался здесь). Мы записали триггер DDL так, чтобы, когда представление создается в DB_Data этим процессом затем, другое представление было автоматически создано в фасаде. Так как представление всегда сгенерировано для точного соответствия представлению в DB_Data и всегда обновляется и сохраняется в синхронизации, мы просто использовали SELECT *
для простоты.
я не был бы удивлен, пошло ли большинство разработчиков своя вся карьера, не имея законного использования для SELECT *
в производственном коде все же.
При создавании приложения, которое имеет дело с базой данных, как phpmyadmin, и Вы находитесь на странице, где отобразить полную таблицу, в этом случае использование SELECT *
может быть выровнено по ширине, я предполагаю.
Как инструмент я использую его для быстрого обновления моей памяти относительно того, что я могу возможно возвратить от запроса. Как сам производственный запрос уровня.. никакой путь.
И помните, используете ли Вы выбор *, и у Вас есть соединение, которое по крайней мере одно поле будет отправлено дважды (объединяющее поле). Это тратит впустую ресурсы базы данных и сетевые ресурсы ни по какой причине.
Вы получили много ответов на свой вопрос, но Вы, кажется, отклоняете все, что не бессмысленно повторяет назад, что Вы хотите услышать. Однако, здесь это - для третьего (до сих пор) время: иногда там никакое узкое место. Иногда производительность является путем лучше, чем прекрасный. Иногда таблицы в движении, и исправление каждого Запроса Select является просто еще одним битом возможного несоответствия для управления. Иногда необходимо поставить в невозможном расписании, и это - последняя вещь, о которой необходимо думать.
, Если Вы живете во время маркера, уверенное, тип во всех именах столбцов. Но почему остановка там? Перепишите свое приложение в бессхемной DBMS. Черт, запишите Ваш собственный DBMS в блоке. Это действительно показало бы им.
В производственном коде я был бы склонен согласовывать 100% с Вами.
Однако я думаю, что * больше, чем выравнивают по ширине его существование при выполнении специальных запросов.
Я думаю с помощью select *
в exists
, пункт является соответствующим:
select some_field from some_table
where exists
(select * from related_table [join condition...])
Некоторым людям нравится использовать select 1
в этом случае, но это не изящно, и это не покупает никакой повышения производительности (ранние забастовки оптимизации снова).
Ни один, о чем я могу думать, если Вы говорите о живом коде.
Люди, говорящие, что это делает добавляющие столбцы легче разработать (таким образом, они автоматически возвращаются и могут использоваться, не изменяя Хранимую процедуру), понятия не имеют о написании оптимального кода.
я только когда-либо использую его при записи специальных запросов, которые не будут снова использованы (обнаружение структуры таблицы, получая некоторые данные, когда я не буду уверен, что имена столбцов).
Я буду использовать его в производстве при работе с CTEs. Но, в этом случае это не действительно select *
, потому что я уже указал столбцы в CTE. Я просто не хочу повторно указывать в заключительном выборе.
with t as (
select a, b, c from foo
)
select t.* from t;
Существует много сценариев, где ВЫБОР * является оптимальным решением. При выполнении специальных запросов в Studio управления только для получения смысла данных Вы работаете с. При запросах таблиц, где Вы еще не знаете имен столбцов, потому что это - первый раз, Вы работали с новой схемой. Создание доступных quick'n'dirty инструментов, чтобы сделать одноразовую миграцию или экспорт данных.
я согласился бы, что в "надлежащей" разработке, необходимо избежать его - но существует много сценариев, где "надлежащая" разработка является не обязательно оптимальным решением бизнес-проблемы. Правила и лучшие практики являются большими, пока Вы знаете, когда повредить их. :)