Delphi 11.x-12.x Android运行时创建/删除InterBase数据库报错求助
我正在为Android平台重写一款旧应用,需新增仅含一张表的InterBase数据库功能。创建数据库和表的过程无异常,但删除数据库时遇到诸多问题。已配置ReadingExternalStorage、WriteExternalStorage权限,使用TMobilepermission组件处理权限,问题在Delphi 11.3和12.2版本上表现一致。
测试代码
主窗体代码
unit Form_Main; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Controls.Presentation, FMX.StdCtrls, MobilePermissions.Model.Signature, MobilePermissions.Model.Dangerous, MobilePermissions.Model.Standard, MobilePermissions.Component; type TForm1 = class(TForm) MP1: TMobilePermissions; Button1: TButton; btn2: TButton; btn1: TButton; procedure Button1Click(Sender: TObject); procedure btn2Click(Sender: TObject); procedure btn1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation uses Module_DataBase; {$R *.fmx} procedure TForm1.btn1Click(Sender: TObject); begin Close; end; procedure TForm1.btn2Click(Sender: TObject); begin EraseDB; end; procedure TForm1.Button1Click(Sender: TObject); begin CreaDb; end; procedure TForm1.FormCreate(Sender: TObject); begin MP1.Apply; // Apply the permissions end; end
数据库模块代码
unit Module_DataBase; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, System.IOUtils, FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf, FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys, FireDAC.FMXUI.Wait, Data.DB, FireDAC.Comp.Client, FireDAC.Stan.Param, FireDAC.DatS, FireDAC.DApt.Intf, FireDAC.DApt, FireDAC.Comp.DataSet, FireDAC.Phys.IB, FireDAC.Phys.IBDef, FireDAC.Phys.SQLite, FireDAC.Phys.SQLiteDef, FireDAC.Stan.ExprFuncs, FireDAC.Phys.SQLiteWrapper.Stat; type TDM = class(TDataModule) Con1: TFDConnection; FQR1: TFDQuery; private { Private declarations } public { Public declarations } end; var DM: TDM; DBPath : string; procedure CreaDB; Procedure EraseDB; implementation {%CLASSGROUP 'FMX.Controls.TControl'} {$R *.dfm} procedure CreaDB; var Tables : TStringList; SqlStr : string; MS : TMemoryStream; I : Integer; begin DBPath := TPath.GetDocumentsPath+PathDelim +'interbase' + PathDelim + 'TestDB.ib'; DM.Con1.Params.Values['Database'] := DBPath; DM.Con1.Params.Values['CreateDatabase'] := BoolToStr(not FileExists(DBPath),True); DM.Con1.Open; Tables := TStringList.Create; DM.Con1.GetTableNames('','','',Tables); // Get Tables // Check for Test table ... if Tables.Count=0 then begin SqlStr:='CREATE TABLE TabellaTest ('; SqlStr:=SqlStr + 'Id INTEGER NOT NULL PRIMARY KEY,'; SqlStr:=SqlStr + 'Articolo CHAR(40),'; SqlStr:=SqlStr + 'Prezzo FLOAT(2)'; SqlStr:=SqlStr + ')'; DM.FQR1.SQL.Clear; DM.FQR1.SQL.Add(SqlStr); DM.FQR1.ExecSQL; DM.Con1.GetTableNames('','','',Tables); end else begin // Just to check the tablename For I:=0 To Tables.Count - 1 do SqlStr:=Tables[i]; end; FreeAndNil(Tables); end; procedure EraseDB; begin if not FileExists(DBPath) then Exit; DM.Con1.Connected:=False; DM.FQR1.SQL.Clear; //DM.FQR1.SQL.Add('DROP SCHEMA ' + DBPath); // * 1 DM.FQR1.SQL.Add('DROP DATABASE ' + 'TestDB.ib'); // * 2 DM.FQR1.ExecSQL; end; end.
连接配置
Con1.DriverName := IB
错误信息
执行删除操作时,无论使用注释的DROP SCHEMA语句还是DROP DATABASE语句,均会触发EIBNativeException错误:
- 错误1:
Project DB_TEST.apk raised exception class EIBNativeException with message '[FireDAC][Phys][IB]Dynamic SQL Error
SQL error code = -104
Token unknown - line 1, char 6
DATABASE'.
- 错误2:EIBNativeException提示"TestDB.ib"已存在。
问题根源与解决方法
InterBase不支持
DROP DATABASE或DROP SCHEMA的SQL语法
InterBase的SQL规范里没有DROP DATABASE这条指令,DROP SCHEMA也不是用来删除整个数据库文件的,这就是触发错误1的核心原因——SQL语法不被数据库引擎识别。删除InterBase数据库的正确方式
InterBase数据库以文件形式存储在Android设备上,确保数据库连接完全断开后,直接通过文件系统删除对应的.ib文件即可,无需执行SQL语句。
修改后的EraseDB函数示例:
procedure EraseDB; var DBFolder: string; begin if not FileExists(DBPath) then Exit; // 确保连接完全断开并释放资源,避免文件被锁定 if DM.Con1.Connected then DM.Con1.Close; DM.FQR1.Close; DM.Con1.Free; DM.Con1 := nil; // 删除数据库文件 DeleteFile(DBPath); // 可选:删除数据库所在的空文件夹 DBFolder := ExtractFilePath(DBPath); if DirectoryExists(DBFolder) then RemoveDir(DBFolder); end;
- 额外注意事项
- Android平台上,删除文件前必须确保没有其他进程或组件占用该文件,否则会删除失败。
- 重新创建数据库前,要确认目标文件已被彻底删除,否则会触发"文件已存在"的错误(即错误2)。
内容的提问来源于stack exchange,提问作者Daniele

