Худший SQL когда-либо?

Какой самый худший SQL-запрос вы когда-либо видели? Что сделало это плохим?

Может, захотите сделать это сообществом WIKI, иначе кто-то его отключит.

JaredPar 31.12.2008 03:41

У него определенно достаточно репутации, чтобы сделать свой вопрос вики. Wikify это.

ctacke 31.12.2008 03:51

Выделение того, что составляет плохую практику программирования, - это про программирование (и в большей степени, чем некоторые другие нежелательные темы, которые я видел)

Mitch Wheat 31.12.2008 03:57

@mitch: Это не вопрос, на который можно дать хотя бы отдаленно однозначный ответ. Напротив, это вопрос, на который ожидается много обоснованных ответов. Ergo: вики.

NotMe 07.01.2009 09:56

Я только что нашел худший пост на свете.

Shane 29.01.2016 23:19
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
10
5
13 140
21
Перейти к ответу Данный вопрос помечен как решенный

Ответы 21

выберите из *

Очень плохо.

ВЫБРАТЬ * ИЗ * ГДЕ * = '%%'; я не смею проверять, действительно ли это работает.

Ólafur Waage 31.12.2008 03:52

или любое перекрестное соединение между двумя или более достаточно большими таблицами.

Otávio Décio 31.12.2008 03:56

перекрестное соединение между двумя большими, но узкими таблицами часто является оптимальным решением, например, для сопоставления наборов - многие ко многим - распространенная проблема

annakata 31.12.2008 14:18

Конечно, классический xkcd:

WHERE name = ROBERT'); DROP TABLE students;--

Почему вы получили за это отрицательные голоса? Это весело!

some 31.12.2008 03:39

О, кто-то снял свой отрицательный голос.

some 31.12.2008 03:41

Мы называем его Little Bobby Tables

Bob Probst 31.12.2008 04:33

Как это считается «худшим»? Это великолепно.

icelava 31.12.2008 04:53

Величие не в запросе, а в названии :)

biozinc 31.12.2008 11:13

Клиент хранил список из трех значений, разделенных запятыми, в поле varchar (классическое приложение ASP), поэтому у него была хранимая процедура, которая выглядела примерно так:

SELECT *
FROM
    SomeTable
WHERE
    Field LIKE @Param + ',%'
    OR
    Field LIKE '%,' + @Param + ',%'
    OR
    Field LIKE '%,' + @Param

Должно быть очевидно, почему это ужасно :)

ай! От этого у меня болят зубы!

Mitch Wheat 31.12.2008 03:40

Я видел похожие вещи в большой производственной программе: S

Ólafur Waage 31.12.2008 04:08

Есть ли лучший способ написать это?

Alterlife 31.12.2008 10:24

Не знаю, подходящее ли слово лучше, но - WHERE ',' + Field + ',' LIKE '%,' + @Param + ',%' - вероятно, будет работать быстрее. Конечно, у вас не должно быть данных, разделенных запятыми, внутри полей в СУБД.

jmucchiello 31.12.2008 10:39

Недавно я видел (более чем) 4000-строчную хранимую процедуру TSQL, которая представляла собой цепочку статусов IF для сопоставления частей адресов. Его можно сократить до менее чем 50 строк!

Сохраняю код для будущего DailyWTF!

SELECT * FROM some_table;

Что сделало это настолько плохим, так это то, что код полагался на получение результатов в порядке на основе отметки времени. Это, по-видимому, работало какое-то время, прежде чем меня вызвали, чтобы это исправить.

Ответ принят как подходящий
DELETE FROM table

Сразу после того, как я напечатал и выполнил его, я забыл о предложении WHERE. Теперь я всегда сначала запускаю оператор SELECT и меняю SELECT на DELETE после того, как убедился, что это повлияет на правильные строки.

Ой ..! Я параноик, я всегда окружаю операторы обновления / удаления командами begin tran / rollback, пробую и затем выполняю внутреннюю часть, когда чувствую себя в безопасности.

Otávio Décio 31.12.2008 03:44

Я делаю нечто подобное, за исключением того, что просто пишу TableName как TableNameFOO, пока пишу его. Я также оставляю поле "Кому:" для писем пустым, прежде чем напишу все письмо и вычитаю его ... на всякий случай;)

Sean Bright 31.12.2008 03:45

@ocdecio: Это был MySQL, до того, как они поддерживали транзакции :(

Robert Gamble 31.12.2008 03:50

@sean: у меня есть коллега, который запускает операторы DELETE с WHERE 1 = 0 на тот случай, если они забудут добавить правильное предложение WHERE до того, как нажмут кнопку выполнения. Точно так же я поступаю с электронной почтой.

Robert Gamble 31.12.2008 03:54

То же самое, и меня поражает, как часто я получаю результат, отличный от ожидаемого.

EvilTeach 31.12.2008 05:58

Ребята ... выберите * в z_backup из <important table> в качестве первого шага. Тогда иди с ума.

Robert C. Barth 31.12.2008 09:58

Я делал это раньше, пока работал, к счастью, я работал на сервере разработки и только что восстановил последнюю резервную копию базы данных. Я также недавно написал веб-страницу для управления образовательным статусом сотрудников и пропустил пункт where. Скажем так, у всех есть ученая степень.

Kezzer 31.12.2008 14:29

ха-ха. Я всегда начинаю с BEGIN на производстве.

Arthur Thomas 31.12.2008 20:10

Вот почему я считаю, что команды DELETE и INSERT должны требовать от программиста явного выражения своего намерения применить оператор ко всем строкам, например УДАЛИТЬ ВСЕ ИЗ таблицы

Tamas Czinege 05.01.2009 19:44

Ой. Я сам чувствовал эту боль. Один раз.

Christian Nunciato 15.01.2009 00:59

Однажды со мной случилось то же самое - я всегда сначала выбираю, а потом меняю запрос, когда доволен результатами.

Mark Brittingham 02.03.2009 01:33

То же самое и с UPDATE, особенно с таблицей, содержащей (лингвистические) переводы :)

Stefan Steiger 13.12.2011 15:47
select * from users where clue > 0;
0 results found.

Хуже всего в этом sql то, что он никогда не возвращает никаких результатов, независимо от того, где вы его запускаете

Steven A. Lowe 31.12.2008 03:54

Вот почему мы должны иметь возможность голосовать за комментарии :)

Robert Gamble 31.12.2008 03:56

Что происходит, почему вы запускаете этот запрос в базе данных Stack Overflow? Он по-прежнему возвращает 0 результатов? Или он просто возвращает идентификатор пользователя 22656

Kibbee 31.12.2008 05:29

Почему этот плохой SQL? Зачем играть в стрелять в посыльного?

Loren Pechtel 31.12.2008 05:36

Вероятно, это не самое худшее, но я вижу это слишком часто (Неправильное использование группы by clause):

SELECT
  C.CustomerID, C.CustomerName, C.CustomerType, C.Address1, C.City,   
  C.State, SUM(S.Sales) as TotalSales
FROM
  Customers C
INNER JOIN Sales S
  ON C.CustomerID = S.CustomerID
GROUP BY
  C.CustomerID, C.CustomerName, C.CustomerType, C.Address1, C.City, C.State

Вместо:

SELECT
  C.CustomerID, C.CustomerName,
  C.CustomerType, C.Address1, C.City,
  C.State, S.TotalSales
FROM
  Customers C
INNER JOIN
  (SELECT CustomerID, SUM(Sales) as TotalSales FROM Sales GROUP BY CustomerID) S
ON
  C.CustomerID = S.CustomerID

Вызовите меня по этому поводу, но я не согласен с тем, что, как правило, 1 - это плохо, а 2 - хорошо. В более сложном примере поддерживать 2 становится немного сложнее. Для меня цель 1 очень ясна, и поэтому ее проще поддерживать. 2 может предложить лучшую производительность, но выигрыш того не стоит.

Bob Probst 31.12.2008 04:32

Кроме того, правило 2 работает медленнее под mysql. mysql--. последний еще более удобен в обслуживании, если вы его дизассемблируете и используете подстановку строк для составления окончательного запроса. ВНУТРЕННЕЕ СОЕДИНЕНИЕ ($ customerTotals): D

Kent Fredric 31.12.2008 05:12

Не будет ли лишнего соединения с синтаксисом 2? Может иметь значение или не иметь значения

erikkallen 31.12.2008 14:54

+1 за интересный рефакторинг - хороший момент. Версия 1 - это простой запрос до SQL-92, адаптированный для использования нотации соединения SQL-92. Второй не должен быть медленнее - он группирует в одной таблице, а затем объединяет ее с исходным (если, я полагаю, оптимизатор не упорядочивает результат подзапроса и не использует этот порядок в объединении слияния с клиентом table, и в этом случае это может быть медленнее, чем индексированное соединение).

Jonathan Leffler 18.04.2009 10:54

Мое собственное, о котором еще далеко до публикации - сейчас закрывается на 3500 строках.

Я действительно должен разделить вину с абсолютно ужасной схемой. То, что начиналось как простое упражнение по преобразованию денормализованных данных с помощью некоторых объединений, превратилось в громоздкий кошмар. Сильно требует ремонта.

Второе место занял:

select 
case datepart(mm,getdate())
when 1 then 'Jan'
when 2 then 'Feb'
when 3 then 'March'
when 4 then 'Apr'
when 5 then 'May'
when 6 then 'Jun'
when 7 then 'July'
when 8 then 'Aug'
when 9 then 'Sept'
when 10 then 'Otc'
when 11 then 'Nov'
when 11 then 'Dec'
end

В этом посте нет опечаток - так оно и было написано. Спасибо, консультации долларов!

Я, конечно, реорганизовал с помощью Select left (datename (mm, getdate ()), 3)

11 сопоставлены с ноябрем и декабрем ?? Действительно?

abelenky 31.12.2008 05:28

Мы обнаружили эту жемчужину в декабре.

Bob Probst 31.12.2008 05:52

На рабочем месте, которое останется безымянным, ваше исправление будет осуждено, потому что оно нарушает написание слов «сентябрь» и «март» (не говоря уже о том, что оно исправляет ошибку).

dreftymac 31.12.2008 06:50

@Shivasubramanian: Да, в Otc была орфографическая ошибка; это один из моментов.

Jonathan Leffler 01.01.2009 12:31

@TrickyNixon: преимущество этого решения в том, что оно не зависит от локали, поэтому даже французские, испанские, немецкие или японские пользователи вынуждены использовать английские сокращения для названий месяцев. : D

Jonathan Leffler 01.01.2009 12:33

@ Джонатан, ах !! Спасибо что подметил это... ;-)

Shivasubramanian A 02.01.2009 08:57

<сарказм> Разве все не говорят на американском английском? Ба! </sarcasm>

James Schek 05.01.2009 19:52

Джонатан Леффлер: Это тоже недостаток. Вполне возможно, что существует язык, в котором два месяца имеют одни и те же первые 3 буквы.

Tamas Czinege 06.01.2009 20:18

прочтите это вслух.

select [select],*,star as [as] from [from],[order] order by [by] 

Это должно быть что-то вроде slashdot.org

Kibbee 31.12.2008 05:32

Когда я впервые получил свою текущую работу, моим первым проектом было создание приложения, которое суммировало бы наши данные об использовании лицензий в наших компьютерных лабораториях. Он настаивал на том, что не хочет нормализовать серверную базу данных, потому что соединения были «слишком дорогими». Это была моя первая неделя, и я не мог спорить.

Теперь, чтобы извлечь какие-либо полезные данные из базы данных, нужно «отменить» денормализацию в каждом запросе, который должен извлекать сводки для удаления дублированных данных в каждой строке. Конечно, это единственные реально используемые запросы. Вы видите множество вложенных выборок, которые были бы совершенно ненужными, если бы данные были нормализованы, например:

select location, sum(login_time) as total_login_time
from
    (select location, session_id, max(login_time) as login_time
     from sessions
     where location in ('lab1','lab2') 
           and session_start >= @start_date 
           and session_end <= @end_date
     group by location, session_id) tbl
group by location

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

Сейчас босса нет, а переписывать некогда ...

сделайте несколько просмотров, чтобы денормализовать данные для вас: D

Kent Fredric 31.12.2008 05:09

Это неправильно на многих уровнях. Особенно замечание о том, что присоединение «слишком дорого».

Mark Brittingham 02.03.2009 03:02

УДАЛИТЬ ИЗ some_table WHERE some_thing IN (ВЫБЕРИТЕ some_column_from_wrong_table ИЗ правильной_таблицы, ГДЕ some_id = something).

В some_column_from_wrong_table есть столбец, которого даже не было в таблице, но он был в другой таблице. Проблема заключалась в том, что правильная_таблица была названа «Событие», и каким-то образом она вернула ВСЕ строки вместо НЕТ строк (или, что более важно, ошибку!).

Два извлеченных урока: НИКОГДА и ни при каких обстоятельствах не называйте таблицу после формы имени системы любой. Во-вторых, сначала нужно запустить операторы выбора, а затем изменить на удаление.

Между прочим, это был SqlServer 2005. Я все еще злюсь, что это не привело к ошибке.

В базе данных Access был запрос, подобный следующему:

SELECT *
FROM Bad_2 INNER JOIN Bad_1 ON Bad_2.Bad_1_id = Bad_1.ID;

и в обеих таблицах было поле с тем же именем. Когда Access встречает имя поля во второй раз, он создает для него новое имя. Предыдущий парень использовал сгенерированное имя поля в коде.

В свое время видел много прискорбных кусков SQL. Один, который приходит на ум, имеет форму

загружать данные из файла, перебирать этот файл, обращаясь к базе данных для каждой строки в файле.

Кажется нормальным в тестовых системах с 10 или около того строками, 100 000–1 миллион = неприятно даже для первичной ключевые поиски.

Кстати, решение состоит в том, чтобы загрузить данные в базу данных и думать наборами.

- Выберите свой любимый язык, например. perl, питон ...

загрузить файл в структуру данных (например, массив)

for (1 .. n) loop
myid := array[n];
select * from table where id = myid;
if the row exists update table set ... where id = myid;
end loop;

Худший ИСПОЛЬЗОВАТЬ SQL-запроса каждые:

Запрос SELECT, который подсчитывает количество строк, соответствующих определенному условию, вызываемый в условии остановки цикла for. Что-то вроде этого:

for(int i = 0; i < query("SELECT COUNT .... WHERE ..."); i++)
{

}

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

В сообщении в группу новостей comp.databases.informix - настоящая рабочая таблица Informix (которую я не рекомендую использовать):

CREATE TABLE VIEW
(
    DECIMAL     CHAR(30),
    NOT         INTEGER NOT NULL,
    SERIAL      DATE NOT NULL,
    NULL        CHAR(1) NOT NULL,
    INTEGER     DECIMAL(13,6) NOT NULL
);

Помогает (незначительно), если вы знаете, что SERIAL - это тип в базах данных Informix - по сути, один из типов для последовательной генерации автоматически назначаемых номеров.

Мне понравился репостен недавно на dailywtf, история, которая идет с ним, тоже замечательна.

Хранимая процедура PL / SQL (Oracle), которая сортирует набор результатов с помощью Пузырьковая сортировка. Это было обнаружено, когда меня и администратора базы данных попросили выяснить серьезную проблему с производительностью. Разработчик, «эксперт» Oracle, работал над этим больше недели. Он объяснил с невозмутимым видом, что узнал о пузырьковой сортировке на уроке информатики. Алгоритм обычно используется для иллюстрации низкой производительности.

Заменил весь беспорядок предложением ORDER BY. Производительность улучшилась на несколько порядков.

Могут быть консультанты Oracle, которые не так уж и плохи, но я никогда их не встречал. Я работал с одной группой, чей «эксперт» по Oracle написал целую бухгалтерскую программу, используя «летучие» файлы, привязанные к ключам. Так, «I.bat» запускал форму счета-фактуры, «R.bat» - отчеты. Да, это было в конце 90-х.

Mark Brittingham 02.03.2009 03:07

Думаю, это худшее (особенно после болезненного и нулевого отката):

DROP DATABASE;
ROLLBACK;
SUBSTRING(
(SUBSTRING(LastName, 0, CHARINDEX(' ', LastName)) + ', ' + FirstName),
0,
CHARINDEX(' ', (SUBSTRING(LastName, 0, CHARINDEX(' ', LastName)) + ', ' + 
FirstName), LEN(LastName) + 3)
)

Очевидно, они не были знакомы с RTRIM;

RTRIM(LastName) + ', ' + RTRIM(FirstName)
SELECT name FROM categories WHERE id IN (".implode(",",corrected_cats($ad->id)).") ORDER BY name ASC

Да, вы правильно прочитали ... поля в поле, разделенные запятыми.

Другие вопросы по теме