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

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

INSETR INTO cycle (code,type,description) SELECT code,type,description FROM cycle WHERE id=1
Code 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 не будет опубликован. Обязательные поля помечены *