当另一个字段数据不存在时清除字段

时间:2017-08-27 18:09:02

标签: delphi sqlite sql-update pascal

我有一个名为“refFile”的字段,其中可能包含或不包含路径描述。

我需要遍历整个数据库并检查“refFile”中定义的路径是否仍然存在。

使用Delphi(Pascal)这需要很多很多分钟

[{
    "rank": 1,
    "id": "something2", 
    "diff": "0.7"
},     
{
    "rank": 2,
    "id": "something3", 
    "diff": "0.1"
},     
{
    "rank": 3,
    "id": "something1", 
    "diff": "0.09"
}] 

我如何在SQL中执行此操作?

谢谢。

3 个答案:

答案 0 :(得分:2)

您无法在SQLLite中检查路径的有效性,但可以使用路径中的某些内容过滤记录,并减少要检查的行列表。

您可以在此字段上订购记录(如果您有索引)并仅检查之前未检查过的路径。

您还可以使用线程在后台执行此长操作。只需使用TThread.Createanonymousthread(程序开始结束).Start;

答案 1 :(得分:2)

您无法在纯 SQLLite 查询中检查文件是否存在。你可以使用UDF (User defined function)来做到这一点,但它会稍微复杂一些,需要一些其他编程语言的技能(请注意,在这种情况下,你的文件应该可以从服务器访问,否则它将无法工作)。

如果您正在寻找一个更简单的解决方案,我认为您可以通过减少查询产生的记录数量以及改进 Delphi 代码来加快您的程序速度效率更高。

选择SQL:

  • 使用lengthtrim函数,因为减少了 Delphi 代码验证的记录数。

    select refFile 
    from myTable
    where (refFile is not null) and (length(trim(refFile)) > 0)
    

<强>的Delphi:

  • 只打电话TDataSet.FieldByName一次。
  • 尝试使用TDataSet.DisableControlsTDataSet.EnableControls(这样,即使数据集组件未链接到任何控件,某些数据集的组件也会更快。)

    var
      Fld : TField;
    begin
      BigDB.DisableControls();
      try
        Fld := BigDB.FieldByName('refFile');
    
        BigDB.First;
        while not(BigDB.Eof) do
        begin
          if not(FileExists(Fld.AsString)) then
          begin
            BigDB.Edit;
            Fld.AsString := '';
            BigDB.Post;
          end;
          BigDB.Next;
        end;
      finally
        BigDB.EnableControls();
      end;
    

此外,您可以考虑其他优化:

  • 如果refFile字段多次包含相同的值,您可以按refFile字段对查询进行排序,并更改 Delphi 代码,以便仅验证每个文件名一旦。 (您可以通过存储FileExists函数的最后一个值和结果来实现。
  • 您可以使用TThread类来异步运行代码。通过这种方式,您的应用程序不会冻结,而且可能会更快。

答案 2 :(得分:2)

例如,使用FireDAC,创建用户定义的函数非常容易。如果您正在使用它,请尝试这样的事情。它可以节省一些时间,因为引擎不需要将结果集提取到客户端应用程序:

uses
  FireDAC.Phys.SQLiteWrapper;

type
  TForm1 = class(TForm)
    Button1: TButton;
    FDQuery1: TFDQuery;
    FDConnection1: TFDConnection;
    FDGUIxWaitCursor1: TFDGUIxWaitCursor;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    FValidator: TSQLiteFunction;
    procedure ValidateFile(AFunc: TSQLiteFunctionData; AInputs: TSQLiteInputs;
      AOutput: TSQLiteOutput; var AUserData: TObject);
  end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FDConnection1.Open;

  FValidator := TSQLiteFunction.Create((TObject(FDConnection1.CliObj) as TSQLiteDatabase).Lib);
  FValidator.Args := 1;
  FValidator.Name := 'FileExists';
  FValidator.OnCalculate := ValidateFile;
  FValidator.InstallAll;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  FDQuery1.SQL.Text :=
    'UPDATE MyTable SET FileName = NULL WHERE ' +
    'FileName IS NOT NULL AND NOT FileExists(FileName)';
  FDQuery1.ExecSQL;
end;

procedure TForm1.ValidateFile(AFunc: TSQLiteFunctionData; AInputs: TSQLiteInputs;
  AOutput: TSQLiteOutput; var AUserData: TObject);
begin
  AOutput.AsBoolean := FileExists(AInputs[0].AsString);
end;

或者简单地删除TFDSQLiteFunction组件,使用函数名填写FunctionName属性,编写类似于上面的OnCalculate事件处理程序,并通过设置{{来启用组件3}}属性。