SQLITE3.EXE批量执行点命令的方法

发布时间 2023-04-07 01:18:18作者: Luo大哥

这两天在使用Firedac进行sqlite数据库编程,遇到了一个问题,这个问题的本身是这样的:

有一个数据库文件,其它一切都正常,但在文件中存在一个有错的INDEX,导致无法使用FIREDAC打开,需要先删除该INDEX后,才能正常使用FIREDAC打开该数据库文件,然而如果删除该INDEX,则会对该文件进行修改,所以在删除该INDEX之前,还需先行备份该文件,这两项工作我都准备通过调用sqlite3.exe来完成。

该文件的文件名是:CCA3.DB

如果在sqlite3.exe中直接执行下面的点命令即可:

.OPEN CCA3.DB
.BACKUP CCA3.DBB
.OPEN CCA3.DBB
DROP INDEX IF EXISTS IDX1

但是因为我是在程序中通过调用shellexecute函数来实现的,不准备让程序使用者进行操作和等待,因此需要在调用函数shellexecute时批量完成这些操作,只能在sqlite3的参数上下功夫。

好吧,下面先来谈谈sqlite3.exe的参数吧,我在sqlite的官网上,只看到unix下面的操作,参数之间使用符号“|”来进行分割,依葫芦画瓢的做,结果出错了。

如果不使用“|”来进行分割呢?依然出错。

当我执行:sqlite3.exe CCA3.DB ".BACKUP CCA3.DBB",只是用一个语句时却没问题。

后来经过摸索我才发现,在windows系统下,sqlite3.exe的参数是不限制的,但是参数的分隔符是空格,所以只需要把每个命令用双引号或单引号囊括起来,并用空格分隔开即可,下面的命令就可以完成所有的操作。

sqlite3.exe CCA3.DB ".BACKUP CCA3.DBB" ".OPEN CCA3.DBB" "DROP INDEX IF EXISTS IDX1" 

当然,如果需要的操作再长点,似乎命令行的长度是有限制的,只有采用另外的方法了。

  tsl:=TStringList.Create;
  tsl.Add('.backup CCA3\\'+ss1);
  tsl.Add('.open CCA3\\'+ss1);
  tsl.Add('drop index if exists IX_alternate_destination_airport_id;') ;
  tsl.SaveToFile('a1.txt');

  ss1:=dlgOpen1.FileName+' ".read a1.txt"';
  h:=shellexecute(Self.Handle,'open','sqlite3.exe',
                PChar(ss1),nil,SW_SHOWNORMAL);
  while GetStdHandle(h)=h do
  begin
    Application.ProcessMessages;
  end;

.read可以读取一个sqlite3.exe的“批处理”文档,适用于需要批量处理的命令很多的情况。

这段代码很简单,就懒得解释了。

最后一段循环的目的是用于等待执行shellexecute完毕后再继续,因为windows下shellexecute调用的程序和本程序是同时进行的,在sqlite3.exe执行完毕前,你可能会得到一个不完整的数据库文件。