如何解决使用TFDBatchMove复制数据库:如何设置从TIMESTAMP到INTEGER的转换?
我的程序应该能够在脱机模式下工作,而无需连接到远程MySQL数据库。为此,我想创建一个选项,将特定表下载到本地SQLite数据库,并在工作完成后将其重新上传回服务器。我尝试将TFDBatchMove组件用于此任务。
该解决方案适用于除一个字段以外的所有字段:MySQL TIMESTAMP。当前,本地数据库使用INTEGER来存储时间戳。当我将数据从SQLite复制到MySQL时,出现错误。在逆操作中,时间戳已损坏。
我想我需要某种类型的数据映射,但是我还没有找到如何设置它。有人可以帮忙吗?
错误消息:“ Project VRDB.exe引发了异常类EVariantError,消息为“无效的变量类型转换”。 “ Project VRDB.exe引发异常类EDatabaseError,并显示消息'字段'TimeStamp'的值无效”。
我的测试代码:
procedure TForm1.ButtonDownloadDBClick(Sender: TObject);
var queryFrom,queryTo: TFDQuery;
FDBatchMove: TFDBatchMove;
begin
queryFrom := TFDQuery.Create(nil);
queryTo := TFDQuery.Create(nil);
FDBatchMove := TFDBatchMove.Create(nil);
with FDBatchMove do begin
// Use "always insert record" mode
Mode := dmAlwaysInsert;
// Erase destination dataset before moving data
Options := [poClearDest];
end;
try
queryFrom.Connection := FDConnection2; //MySQL
queryTo.Connection := FDConnection1; //SQLite
queryFrom.SQL.Clear;
queryFrom.SQL.Add('SELECT * FROM Clients');
queryFrom.Open();
queryFrom.Prepare;
queryFrom.Close;
queryTo.SQL.Clear;
queryTo.SQL.Add('SELECT * FROM Clients');
queryTo.Open();
queryTo.Prepare;
queryTo.Close;
with TFDBatchMoveDataSetReader.Create(FDBatchMove) do begin
DataSet := queryFrom;
Optimise := False;
end;
with TFDBatchMoveDataSetWriter.Create(FDBatchMove) do begin
DataSet := queryTo;
Optimise := False;
end;
FDBatchMove.Execute;
finally
queryFrom.Close;
queryFrom.Destroy;
queryTo.Close;
queryTo.Destroy;
FDBatchMove.Destroy;
end;
end;
解决方法
所以看来我已经解决了这个问题。这就是我的方法。我假设TimeStamp字段在MySQL中为TIMESTAMP
,在SQLite中为INTEGER
,并且DateTimeFormat = String
。
非常感谢Brian的想法。
您应该修改queryFrom SQL。对于MySQL-> SQLite,请执行以下操作:
queryFrom.SQL.Add('SELECT ID,Phone,Name,<...>,UNIX_TIMESTAMP(TimeStamp) FROM Clients');
这会将Date字段类型转换为整数时间码。
对于SQLite-> MySQL,请执行以下操作:
queryFrom.SQL.Add('SELECT ID,datetime(TimeStamp,"unixepoch") FROM Clients');
重要说明:datetime
返回字符串。 TFDBatchMove将使用默认的Delphi StrToDateTime
进行转换。如果您在应用中更改了日期格式,它将失败。因此,您要么想在执行之前还原它,要么手动格式化TimeStamp:
queryFrom.SQL.Add('SELECT ID,strftime("%d.%m.%Y %H:%M:%S",TimeStamp,"unixepoch") FROM Clients');
另一个重要说明:由于某种原因,我无法使其与Mappings一起使用。如果有人知道如何正确映射具有功能的列,请回复此帖子,我将添加配方。
我的测试代码中也有一个错误。如您所见,我想保留ID值,即Primary Key
值,保持原样。如果需要,您必须在BatchMove Options中指定poIdentityInsert
:
FDBatchMove.Options := [poIdentityInsert,<OtherOptions>];
在其他情况下,您会收到错误的Fetch command fetched [0] instead of [1] record.
错误。