В данном посте рассмотрим варианты добавления записи в БД MySQL. Для простоты будем использовать технологию DBExpress. Для других технологий и БД, думаю, принципы будут схожими.
Подготовительные работы
Для начала, воссоздадим пример подключения к БД, а также прочитаем таблицы БД. Для работы, будем использовать созданную нами БД test_db и таблицу Departments. Несколько изменим кнопки на вкладке DBGrid. Добавим кнопки “Добавить через SQL”, а также “Добавить через Append Post Refresh”
Итак, наша задача – различными способами добавить новую запись в DBGrid. На данном этапе я знаю о 2-х способах добавления записи – напрямую через SQL запрос и через Delphi, в процессе, может быть, обнаружится что-то ещё.
Как в Delphi добавить запись через SQL запрос?
В нашей схеме есть следующие компоненты для работы с БД
SQLConnection
SimpleDataSet
DataSource
это необходимый минимум…., а также компонент SQLQuery, через него мы получали таблицы БД…
Самый простой способ – отправить SQL запрос через SQLConnection1.Execute(‘Text_of_SQL_Request’). Как делать сами запросы (в консольном клиенте MySQL) на добавление записей, можно посмотреть здесь.
Таким образом, в самом простом случае, в Delphi, я написал обработчик таким образом…
1 2 3 4 5 6 7 8 |
procedure TMainForm.AddUsingQLClick(Sender: TObject); begin sqlconnection1.Connected:=true; sqlconnection1.ExecuteDirect('insert into departments(name) values (''New Record'') '); end; |
В подтверждение того, что запись отобразилась, можно посмотреть в консольном клиенте…
Действительно… “New Record” есть под номером 6…
Далее, нам нужно как-то обновить отображение таблицы в Delphi… Для этого, я дополнил код таким образом…
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 |
procedure TMainForm.AddUsingQLClick(Sender: TObject); begin sqlconnection1.Connected:=true; sqlconnection1.ExecuteDirect('insert into departments(name) values (''New Record'') '); //Обновляем DBGrid1 SimpleDataSet1.Connection:=sqlconnection1; // подключаем simpledataset... SimpleDataSet1.Active:=false; with simpledataset1 do //Настраиваем Simpledataset... begin DataSet.Active:=false; DataSet.CommandType:=ctQuery; DataSet.CommandText:= 'SELECT*from departments'; // ''sql_groupby'' DataSet.Active:=true; end; SimpleDataSet1.Active:=true; end; |
Результат получился таким…
Этот способ, на мой взгляд, достаточно простой и надежный. Единственное, что нужно – уметь общаться с выбранной СУБД на языке SQL. Я на данный момент выбрал для себя MySQL – на мой взгляд достаточно простую СУБД. В процессе обучения работе с ней – написал цикл статей.
(КАК НЕ НУЖНО ДЕЛАТЬ) Вариация добавления записи через SimpleDataSet…
Когда мы отправляем запрос из simpledataset, да и вообще, из любого dataset, то delphi ожидает возвращения множества и курсора в нем… Поэтому, если запрос у Вас не связан с возвращением множества (например Select – возвращает множество, а insert не возвращает), тогда лучше запрос из dataset не отправлять…
Ошибочный код мог бы быть таким…
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 |
sqlconnection1.Connected:=true; //sqlconnection1.ExecuteDirect('insert into departments(name) values (''New Record'') '); //Вставляем запись... SimpleDataSet1.Connection:=sqlconnection1; // подключаем simpledataset... SimpleDataSet1.Active:=false; with simpledataset1 do //Настраиваем Simpledataset... begin DataSet.Active:=false; DataSet.CommandType:=ctQuery; DataSet.CommandText:= 'insert into departments(name) values (''New Record'')'; // ''sql_groupby'' DataSet.Active:=true; end; SimpleDataSet1.Active:=true; //Обновляем DBGrid1 //SimpleDataSet1.Connection:=sqlconnection1; // подключаем simpledataset... SimpleDataSet1.Active:=false; with simpledataset1 do //Настраиваем Simpledataset... begin DataSet.Active:=false; DataSet.CommandType:=ctQuery; DataSet.CommandText:= 'SELECT*from departments'; // ''sql_groupby'' DataSet.Active:=true; end; SimpleDataSet1.Active:=true; end; |
При этом, запись добавляется как нужно…. Просто будет выскакивать неприятная ошибка невозврата курсора…
Как ещё можно добавить запись через SQL запрос?
А очень просто – через специализированный компонент SQLQuery. Уж он то не ожидает возвращения курсора. Поэтому, направляем код добавления новой записи в него. Обратите внимание, что обновление DBGrid, мы производим, всё таки через SimpleDataSet…
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 |
procedure TMainForm.AddUsingQLClick(Sender: TObject); begin sqlconnection1.Connected:=true; sqlquery1.SQL.Clear; sqlquery1.SQL.Add( 'insert into departments(name) values (''New Record'')'); sqlquery1.ExecSQL; //Обновляем DBGrid1 SimpleDataSet1.Connection:=sqlconnection1; // подключаем simpledataset... SimpleDataSet1.Active:=false; with simpledataset1 do //Настраиваем Simpledataset... begin DataSet.Active:=false; DataSet.CommandType:=ctQuery; DataSet.CommandText:= 'SELECT*from departments'; // ''sql_groupby'' DataSet.Active:=true; end; SimpleDataSet1.Active:=true; end; Таким образом всё работает как нужно... |
Можно также добавлять записи через SQLTable.Insert или SQLTable.insertrecord… Но это уже тема для отдельного обзора.
1 2 3 |
Важное замечание Вообще, на мой взгляд в приложении удобно выводить отдельную форму для "вбивания" новой записи в базу, а также оформлять всё в виде транзакции, чтобы не было конфликтов при доступе к данным. |
Как добавить запись через Append Post ApplyUpdates Refresh?
Здесь интересные моменты получились – разобрался не сразу. Вот рабочий код…
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 |
procedure TMainForm.AddUsingQLClick(Sender: TObject); var PK:integer; 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'; DataSet.Active:=true; end; SimpleDataSet1.Active:=true; PK:=simpledataset1.RecordCount; //Cобственно производим добавление записи SimpleDataSet1.Append; SimpleDataSet1.FieldByName('Primary_key').AsInteger:=PK+1; SimpleDataSet1.FieldByName('Name').AsString:='New Record'; SimpleDataSet1.Post; SimpleDataSet1.ApplyUpdates(-1); {-1 означает нет ограничения по ошибкам, любое другое число - максимальное число ошибок} SimpleDataSet1.Refresh; end; |
Но, в процессе создания кода у меня произошел трабл.
ТРАБЛ
Изначально я создал код без строчки
1 |
SimpleDataSet1.FieldByName('Primary_key').AsInteger:=PK+1; |
А что это за строчка? Это главный ключ этой таблицы. Я наивно полагал, что раз поле автоинкрементное, то либо Delphi, либо MySQL, его обработают и добавят следующую запись. Но не тут-то было !!!
Оказалось, надо было всё делать “ручками”. Что же! Теперь мы об этом моменте знаем!!! Когда я добавил эту строчку – всё заработало как надо. То есть, иными словами, при этом методе, надо будет следить за этим автоинкрементным полем.
В случае, когда мы добавляем запись через запрос SQL, за нумерацией в автоинкрементном поле следит CУБД, поскольку, в предыдущем случае, мы добавляли всего одну строчку.
ДРУГОЕ РЕШЕНИЕ ТРАБЛА
Можно просто, при формировании таблицы на автоинкрементном поле убрать NOT NULL, и тогда всё встанет на место (не проверял сам, но должно работать)
Но, к слову сказать, на mysql.ru, очень рекомендуют ставить галочку NOT NULL. Говорят убирать её только в крайнем случае, если это действительно нужно. Думаю, это как раз такой случай.