Может ли выбор * использование когда-либо быть оправданным? - PullRequest
62 голосов
/ 03 сентября 2010

Я всегда проповедовал своим разработчикам, что SELECT * - зло, и его следует избегать, как чумы.

Есть ли случаи, когда это можно оправдать?

Я не говорю о COUNT(*) - который может понять большинство оптимизаторов.

1009 ** * Редактировать 1010 ** * 1011

Я говорю о производственном коде.

И одним замечательным примером этой плохой практики, которую я видел, было устаревшее приложение asp, которое использовало select * в хранимой процедуре и использовало ADO для циклического просмотра возвращаемых записей, но получало столбцы по индексу. Вы можете себе представить, что произошло, когда новое поле было добавлено где-то, кроме конца списка полей.

Ответы [ 20 ]

45 голосов
/ 03 сентября 2010

Я очень рад, используя * в триггерах аудита.

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

(Как и 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 не запущен для обновления этих метаданных.

34 голосов
/ 03 сентября 2010

Есть много сценариев, где SELECT * является оптимальным решением.Выполнение специальных запросов в Management Studio только для того, чтобы получить представление о данных, с которыми вы работаете.Запрос к таблицам, в которых вы еще не знаете имен столбцов, потому что вы впервые работали с новой схемой.Создание одноразовых быстрых и грязных инструментов для одноразовой миграции или экспорта данных.

Я бы согласился, что при «правильной» разработке вам следует избегать этого - но существует множество сценариев, где «правильная»развитие не обязательно является оптимальным решением бизнес-проблемы.Правила и лучшие практики великолепны, если вы знаете, когда их нарушать.:)

28 голосов
/ 03 сентября 2010

Я буду использовать его в работе при работе с CTE.Но в данном случае это не совсем select *, потому что я уже указал столбцы в CTE.Я просто не хочу уточнять окончательный выбор.

with t as (
    select a, b, c from foo
)

select t.* from t;
25 голосов
/ 03 сентября 2010

Я не могу придумать, если вы говорите о живом коде.

Люди говорят, что это облегчает разработку добавления столбцов (поэтому они автоматически возвращаются и могут использоваться без изменения хранимой процедуры)понятия не имею о написании оптимального кода / sql.

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

16 голосов
/ 03 сентября 2010

Я думаю, что целесообразно использовать select * в предложении exists:

select some_field from some_table 
where exists 
 (select * from related_table [join condition...])

Некоторым людям нравится использовать select 1 в этом случае, но это не элегантно, и не стоит покупать любое улучшение производительности (ранняя оптимизация снова наступает).

7 голосов
/ 03 сентября 2010

В рабочем коде я склонен согласиться с вами на 100%.

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

6 голосов
/ 04 сентября 2010

Вы получили несколько ответов на свой вопрос, но, похоже, вы отклоняете все, что не попугает то, что вы хотите услышать. Тем не менее, это уже третий (пока) случай: иногда не является узким местом. Иногда производительность намного лучше, чем хорошая. Иногда таблицы находятся в движении, и внесение поправок в каждый запрос SELECT - это еще один кусочек возможной несогласованности, с которым нужно справиться. Иногда вам нужно доставить по невозможному графику, и это последнее, о чем вам нужно подумать.

Если вы живете в режиме маркера, обязательно введите все имена столбцов. Но зачем останавливаться на достигнутом? Переписать ваше приложение в БД без схемы. Черт, напиши свои собственные дБмс в сборке. Это действительно показало бы их.

4 голосов
/ 03 сентября 2010

И помните, что если вы используете select * и у вас есть соединение, по крайней мере одно поле будет отправлено дважды (поле объединения).Это приводит к бесполезной трате ресурсов базы данных и сетевых ресурсов.

2 голосов
/ 20 сентября 2010

Как еще разработчики phpmyadmin гарантируют, что они отображают все поля ваших таблиц БД?

2 голосов
/ 03 сентября 2010

Единственное, о чем я могу подумать, это при разработке утилиты или приложения-инструмента SQL, которое пишется для работы с любой базой данных. Хотя и здесь я хотел бы запросить системные таблицы, чтобы получить структуру таблиц, а затем построить любой необходимый запрос из этого.

Было одно недавнее место, где моя команда использовала SELECT *, и я думаю, что это было нормально ... у нас есть база данных, которая существует как фасад по отношению к другой базе данных (назовите ее DB_Data), поэтому она в основном состоит из просмотров против таблиц в другой базе данных. Когда мы генерируем представления, мы фактически генерируем списки столбцов, но в базе данных DB_Data есть один набор представлений, которые автоматически генерируются, когда строки добавляются в общую справочную таблицу (этот дизайн был в месте до того, как я сюда попал). Мы написали триггер DDL, чтобы при создании этого представления в DB_Data этим процессом автоматически создавалось другое представление на фасаде. Поскольку представление всегда создается для точного соответствия представлению в DB_Data и всегда обновляется и синхронизируется, мы просто использовали SELECT * для простоты.

Я бы не удивился, если бы большинство разработчиков прошли всю свою карьеру без законного использования SELECT * в рабочем коде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...