Копирование записей – довольно частая операция для бизнес-приложений, созданных в My Visual Database. Обычно для этого используют форму в режиме редактирования и трюк со значением свойства dbGeneralTableID у кнопки, отвечающей за сохранение данных.

Другой способ получения копии записи таблицы – это использование SQL запроса.

INSETR INTO cycle (code,type,description) SELECT code,type,description FROM cycle WHERE id=1Code language: SQL (Structured Query Language) (sql)

В этом примере делается копия записи с ID=1 для таблицы cycle, в которой имеется три поля: code, type и description.

А можно ли скопировать запись, не зная структуры таблицы? Можно! Для этого нам понадобится временная таблица (данная технология поддерживается в СУБД SQLite и MySQL).

function DB_CopyRecord( ATableName: string; AID: integer ):integer;
// универсальная функция копирования записи
begin
  // создаем временную таблицу со структурой, идентичной копируемой записи
  SQLExecute('CREATE TEMPORARY TABLE tmp AS SELECT * FROM ['+ATableName+'] WHERE id = '+IntToStr(AID));
  // сбрасываем значение поля ID
  SQLExecute('UPDATE tmp SET id = NULL');
  // вставляем запись обратно
  SQLExecute('INSERT INTO ['+ATableName+'] SELECT * FROM tmp');
  // получаем ID новой записи
  Result := Last_Insert_ID();
  // удаляем временную таблицу
  SQLExecute('DROP TABLE tmp');
end;

Code language: Delphi (delphi)

На вход процедуры подаются название таблицы и идентификатор записи для копирования. На выходе – идентификатор копии.

На уровне базы данных уникальность записей в проектах My Visual Database поддерживается только для обязательного поля ID, поэтому в строке 7 выполняется команда, устанавливающая его значение в NULL. Это необходимо для того, чтобы при вставке копии (строка 9) значение поля ID установилось автоматически самой СУБД.

Пример использования процедуры, в котором у копии модифицируется поле с названием.

var
  tmpIDOrder: integer;
  tmpIDNewOrder: integer;
begin
  ...
  tmpIDNewOrder := DB_CopyRecord( 'order', tmpIDOrder ); // копируем заказ
  SQLExecute('UPDATE [order] SET name = (SELECT name FROM [order] WHERE id = '+IntToStr(tmpIDNewOrder)+') || " (копия)" WHERE id = '+IntToStr(tmpIDNewOrder));
Code language: JavaScript (javascript)

Примечание

Особенностью работы команды SQLQuery является блокировка базы SQLite, поэтому, если вы решили использовать процедуру DB_CopyRecord() для копирования нескольких записей, то убедитесь, что не вызываете её внутри цикла, в котором используется открытый командой SQLQuery датасет. Это требование вызвано тем, что для выполнения команды DROP TABLE требуется полный доступ к БД.

Обойти это ограничение можно, если заменить цикл while и SQLQuery на цикл for и SQLExecute. Так как для копирования вам нужны только ID записей, то можно извлечь и преобразовать в массив. Ниже приводится пример кода для копирования детализации заказа:

var
  tmpID: integer;
  tmpIDOrder: integer;
  tmpListID: array of string;
  i: integer;

  tmpSQL: string;
begin
  ...
  tmpSQL := 'SELECT GROUP_CONCAT(id) FROM orderPosition WHERE id_order = '+IntToStr(tmpIDOrder);
  tmpListID := SplitString(SQLExecute(tmpSQL),',');
  for i:=0 to length(tmpListID) - 1 do
  begin
    tmpID := DB_CopyRecord( 'orderPosition', StrToInt( tmpListID[i] ) ) );
    ...
  end;

  ...
end;Code language: Delphi (delphi)

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *