Заметки программера Чему равно дважды два равно четыре?
Revert
Переводим ASDF в ФЫВА и наоборот.
Хорошо!!
Радикальный улучшатель настроения.
Грамота
Покажи всем, насколько ты крут - выпиши себе мега-грамоту!
28.07.2011, 11:58   Статьи » Как не надо делать

Несколько слов о базах данных и SQL

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

Вообще всё это напоминает мне анекдот про "чем этого лечить - проще нового сделать". Но, если с оболочкой для работы всё понятно - следует писать новую (чем я и занимаюсь), то с базой всё гораздо сложнее. От старой оболочки отказаться сразу не получилось, в то же время - новую надо тестировать в работе. Т.е. - они должны работать с одними и и теми же данными. Учитывая это, мне приходится вплотную работать с невнятным набором информации, по недоразумению названным базой данных отдела АСУ.

В данной заметке я не стану расписывать все косяки - их слишком много. Просто напишу несколько рекомендаций, которые пришли мне в голову только за сегодняшний день.

1. Не надо, блядь, формировать многокилобайтные запросы в коде программы!!!

Небольшие, впрочем, тоже не надо. Вынеси все запросы в виде констант в отдельный юнит. Или - в отдельный файл, а в нужный момент - загружай из него. Или запихни в базу данных. Не надо писать различную хуйню типа

with Form1.ADOQuery2 do begin
Close;
SQL.Clear;
SQL.Add('BEGIN TRANSACTION');
SQL.Add('INSERT INTO LogBasis(iConF, s1, iTypOper, sNotes, iUsTab, sUchNom, sTable, sField, s2, sFIOZr, sFIOZ, sORGZ)');

SQL.Add('VALUES ('+''''+Buf1.sName+''''+','+''''+trim(EditFIO.Text)+''''+',5,'+''''+trim(EditComment.Text)+''''+','+''''+trim(RepName)+''''+','+''''+trim(Form1.Edit51.Text)+''''+','+''''+trim(EditDolg.Text)+''''+','+''''+trim(EditRuk.Text)+''''+','+''''+trim(EditGlavbuh.Text)+''''+','+''''+trim(Edit1.Text)+''''+','+''''+trim(Edit2.Text)+''''+','+''''+trim(Edit3.Text)+''''+')');
Form1.ADOQuery17.First;

while not Form1.ADOQuery17.EOF do
begin
  if Form1.ADOQuery17.FieldByName('iTProdID1').AsInteger<>-1 then
  begin
    SQL.Add('INSERT INTO LogBasis(iConF, s2, iTypOper, iUsTab, sUchNom, iCodProd, iCodeT)');

    SQL.Add('VALUES ('+''''+Buf1.sName+''''+','+''''+Form1.ADOQuery17.FieldByName('sFctNum1').AsString+''''+',5,'+''''+trim(RepName)+''''+','+''''+trim(Form1.Edit51.Text)+''''+','+''''+Form1.ADOQuery17.FieldByName('iCode3').AsString+''''+',8)');

    SQL.Add('UPDATE Products SET sRegNum='+''''+trim(Form1.Edit51.Text)+''''+',iStatID=8'+',sInfo='+''''+trim(EditComment.Text)+'''');
    SQL.Add('WHERE iCode='+''''+Form1.ADOQuery17.FieldByName('iCode3').AsString+'''');

  end else
  begin
    SQL.Add('INSERT INTO LogBasis(iConF,iTypOper, iUsTab, sUchNom,sPredIsm,sTable,sField,iCodeT)');
    SQL.Add('VALUES ('+''''+Buf1.sName+''''+',5,'+''''+trim(RepName)+''''+','+''''+trim(Form1.Edit51.Text)+''''+','+''''+Form1.ADOQuery17.FieldByName('sNameR1').AsString+''''+','+''''+Form1.ADOQuery17.FieldByName('sMark1').AsString+''''+','+''''+Form1.ADOQuery17.FieldByName('sFctNum1').AsString+''''+',8)');

  end;
  Form1.ADOQuery17.Next;
end;
Form1.ADOQuery16.First;
while not Form1.ADOQuery16.EOF do
begin
  SQL.Add('INSERT INTO LogBasis(iConF, s2, iTypOper, iUsTab, sUchNom, iCodProd, iCodeT)');
  SQL.Add('VALUES ('+''''+Buf1.sName+''''+','+''''+Form1.ADOQuery16.FieldByName('sFctNum1').AsString+''''+','+''''+'5'+''''+','+''''+trim(RepName)+''''+','+''''+trim(Form1.Edit51.Text)+''''+','+''''+Form1.ADOQuery16.FieldByName('iCode3').AsString+''''+',2)');

  SQL.Add('UPDATE Products SET sRegNum='+''''+''''+',iStatID=2'+',sInfo='+''''+trim(EditComment.Text)+'''');
  SQL.Add('WHERE iCode='+''''+Form1.ADOQuery16.FieldByName('iCode3').AsString+'''');

  Form1.ADOQuery16.Next;
end;

Такую хуйню ты заебешься отлаживать. И ладно бы ты сам - это твои проблемы, каждый сам себе мудак. Но о других-то подумай! Иначе тебя будут часто поминать всякими нехорошими словоформами типа "пиздоглазый мудофель", "хуерукий выблядок", "каломозговый недоёбок" и прочили лестными характеристиками.

2. Используй параметры sql-запросов.

Для того, чтобы не приходилось страдать хуйней, описанной в предыдущем пункте, умные люди давно придумали такую замечательную вещь, как параметры запросов. Т.е., вместо того, чтобы городить на всю башку пизданутые конструкции типа SQL.Text := 'insert into TABLE1(FIELD1, FIELD2, FIELD3)values('+Var1+', '+Var2+', '+Var3+')';), мы пишем аккуратно SQL.Text := 'insert into TABLE1(FIELD1, FIELD2, FIELD3)values(:P1, :P2, :P3)';), а нужные значения передаем в качестве параметров. Преимущества - налицо:

  • Гораздо легче отлаживать.
  • Запрос можно вынести в константу.
  • Меньше нагрузка на сервер (сервер хранит кэш запросов, при изменении хоть одного символа в кэш пишется еще один запрос, а вот при использовании параметров такого не происходит).
  • Никто хитроплечий не запихнет тебе в запрос всякую хуйню (см. sql-injection).

3. Хранимые процедуры - наше всё.

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

4. Делай правильную, блядь, структуру базы! Не забывай про внешние ключи!!!

Вышеуказанные Служенко Константин Викторович и Сергиенко Валерий Вячеславович на FK клали хуй. Этого делать ни в коем случае нельзя. Данные должны иметь четкую структуру и не рассыпаться, как трухлявый мешок, в который нагрузили семьдесят три килограмма щебенки из-за того, что погромисту внутренний голос подсказал, что внешние ключи только мешают творческому полёту мысли.

Итогом поклажи детородного органа на foreign keys являются записи, непонятно к чему относящиеся, и замусоривающие базу до такой степени, что и WALL-E не справится с таким количеством хлама.

5. Не пользуйся автоинкрементируемыми полями! Ни в коем случае!!!

Конечно, поле primary key проще всего сделать автоинкрементируемым (если есть такая возможность) - тогда оно стопудово будет содержать уникальные значения, а тебе можно не забивать этим голову. Но со временем ты напорешься на охуенные грабли - тебе внезапно понадобится руками указать значение поля, а СУБД тебе в ответ выпишет хуй размером с Пизанскую башню.

Не поленись - напиши триггер, в котором, допустим, сделай проверку - а не null ли пытаются скормить в качестве значения твоего РК? И если таки null - то сгенерируй нужное значение самостоятельно. И вот при таком раскладе тебе не придется рвать последние волосы на жопе, когда ты захочешь изменить значение этого поля.

А на сегодня это всё. До новых встреч в эфире.

Комментарии

Vlad 27.09.2011, 13:15 #1
Забавно написано...)

Добавлние комментов отключено на время переезда

Картинки

Прекрасная игра

Егор и разработка

Когда нет домкрата
Ссылки