В этом посте напишу о своем опыте с DBExpress MySQL и попыткой INSERT… То есть, хотелось бы научить программу вставлять в любую строку, а не только в последнюю. Но не тут-то было!
В самом простом случае (когда у нас нет ключевых полей) INSERT из DELPHI работает прекрасно… Жмём кнопку INSERT, вставляем запись – сохраняем в физической БД нажатием на SAVE…
Но такая “идилия” длится до тех пор, пока не нажмешь на Refresh…
Как я обработал кнопку INSERT?
1 2 3 4 |
procedure TMainForm.Button3Click(Sender: TObject); begin simpledataset1.Insert; end; |
Как я обработал кнопку SAVE?
1 2 3 4 5 6 7 8 9 |
procedure TMainForm.Button4Click(Sender: TObject); begin if simpledataset1.Modified then begin simpledataset1.Post; simpledataset1.ApplyUpdates(-1); simpledataset1.Refresh; end; end; |
И вроде бы всё Ок! Но, стоило сделать единственное поле экспериментальной таблицы MyTable сделать ключевым, то есть при формировании таблицы написать такой код…
1 2 3 4 5 6 7 |
CREATE TABLE IF NOT EXISTS `test_db`.`MyTable` ( `MyField` VARCHAR(45) NOT NULL , PRIMARY KEY (`MyField`) ) ENGINE = InnoDB; |
Как тут же я столкнулся с тем, что записи переставляются в алфавитном, либо возрастающем порядке по тому или иному номеру. В нашем случае – одно поле VarChar, поэтому СУБД MySQL сортирует в алфавитном порядке… (хотя впоследствии запись всегда вставлялась в конец.. в общем разбираюсь в данном вопросе)
Проблема
1 |
Внимание, если у Вас стоит ключевое поле в таблице, а оно скорее всего стоит (без него немыслимо серьезное приложение), то СУБД, скорее всего будет упорядочивать записи по этому полю. В результате, вы вставляете запись в середину, а она вставляется в конец или в начало. Что делать в этом случае? Читайте далее. |
При всех моих попытках идти стандартными способами новая строка всё время вставлялась в конец! Вот как выглядел “стандартный” код для INSERT, который рекомендуют в некоторых онлайн учебниках…
SimpleDataSet1.Insert; SimpleDataSet1.FieldByName(‘Primary_key’).AsInteger:=PK+1; SimpleDataSet1.FieldByName(‘Name’).AsString:=’New Record’; SimpleDataSet1.Post; SimpleDataSet1.ApplyUpdates(-1); SimpleDataSet1.Refresh;
Оканчивалось это так… Запись постоянно оказывалась в конце… Это и понятно! У нас есть ключевое поле в этой таблице и СУБД автоматически упорядочивает записи по нему. Чтобы этого избежать, нужно либо убрать ключевое поле (что немыслимо при разработке серьезного приложения), либо воспользоваться дополнительной колонкой Sort (см. решение проблемы ниже).
Решение
Итак, решение в том, чтобы ввести новый столбец Sort, и далее, умело нумеруя и переставляя записи отображать “всё это дело” пользователю. То есть, примерно таким образом…
Теперь, имея такой столбец, можно вставлять в любое место нашей таблицы, и вот какой результат у нас получится…
Вот основные шаги по коду…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
procedure TMainForm.AddUsingQLClick(Sender: TObject); var PK:integer; s:string; begin //Загружаем множество как есть... sqlconnection1.Connected:=true; SimpleDataSet1.Connection:=sqlconnection1; // подключаем simpledataset... SimpleDataSet1.Active:=false; with simpledataset1 do //Настраиваем Simpledataset... begin DataSet.Active:=false; DataSet.CommandType:=cttable; DataSet.CommandText:='departments'; // ''sql_groupby'' DataSet.Active:=true; end; SimpleDataSet1.Active:=true; { -пусть курсор стоит на CursorNO в колонке Sort... -начиная с CursorNO+1 надо все остальные подвинуть на+1 -поставить последнюю запись на место СursorNO -поменять номер последней записи, установить CurcorNO -Отсортировать по возрастанию Order by Sort... } // сдвигаем все записи после курсорной... s:='update departments set sort=sort+1 where sort>'+s2; sqlconnection1.ExecuteDirect(s); PK:=simpledataset1.RecordCount; //Cобственно производим добавление записи SimpleDataSet1.Insert; SimpleDataSet1.FieldByName('Primary_key').AsInteger:=PK+1; SimpleDataSet1.FieldByName('Name').AsString:='New Record'; SimpleDataSet1.FieldByName('Sort').AsInteger:=strtoint(s2)+1; SimpleDataSet1.Post; SimpleDataSet1.ApplyUpdates(-1); //SimpleDataSet1.Refresh; // Перезагружаем множество... SimpleDataSet1.Active:=false; with simpledataset1 do //Настраиваем Simpledataset... begin DataSet.Active:=false; DataSet.CommandType:=ctquery; DataSet.CommandText:='select*from departments order by sort'; DataSet.Active:=true; end; SimpleDataSet1.Active:=true; end; |