Firebird 使用 GUID 字段在 Delphi 中如何操作

探讨在FireBird数据库中使用16字节OCTETS类型存储GUID的方法,节省空间并提高效率。通过Delphi的TBytesField与TGUIDField进行数据读写,解析Locate与FindKey定位差异。

FireBird 数据库里面没有专门的 GUID 类型的字段。采用字段类型为:Char(16) OCTETS 可以存储 GUID;

在 Delphi 里面,用 FireDAC FdQuery 去打开有这个字段的表,对应的字段类型是:TBytesField;强行将这个字段改为 TGUIDField 类型的字段,打开表会出现类型不匹配的异常;同样,ClientDataSet 里面对应的字段类型也是 TBytesField,不能强制为 TGUIDField 类型的字段;

 

如果某个 ClientDataSet 里面,有 TGUIDField 类型的字段,比如字段名叫:ID, 对这个字段进行 Locate 搜索,不会出现异常,但定位不到。如果用 FindKey 可以定位到,但必须先指定这个字段是 Index 字段。代码如下:

function VarFromGuid(const aGuid: TGuid): Variant;
 var
    Ptr: Pointer;
 begin
    Result := VarArrayCreate( [1, Sizeof(aGuid)], varByte);
    Ptr := VarArrayLock(Result);
    try
      Move(aGuid, Ptr^, Sizeof(aGuid));
    finally
     VarArrayUnlock(Result);
   end;
 end;

上述函数是把 GUID 转换为 Variant,因为 DataSet.Locate 需要的参数类型是 variant 类型。

procedure TForm1.Button7Click(Sender: TObject);
var
  G: TGUID;
  S: string;
  V: Variant;
begin
  //这里的 ID 字段是 TGUIDField 类型
  S := Edit2.Text;
  G := StringToGUID(S);
  V := VarFromGUID(G);

  with ClientDataSet2 do
  begin
    Locate('ID',varArrayOf([V]) , []); //定位不到。但执行不会出异常。
    //ClientDataSet2.FindKey([S]);  //可以定位到。
  end;
end;

-----------------------------------

如果 ClientDataSet 的字段类型是 TBytesField,则不能执行 Locate('ID',varArrayOf([V]) , []); 方法,运行时会提示不支持的类型。

但对于 FireDAC,FdMemTable 如果有字段是 TBytesField 类型,可以执行 Locate('ID',varArrayOf([V]) , []) 方法能够成功搜索到。

对ClientDataSet 的 TBytesField 字段,执行 FindKey 方法可以成功定位。代码如下:

procedure TForm1.Button5Click(Sender: TObject);
var
  G: TGUID;
  S: string;
  V: Variant;
begin
  //这里的 M_ID 字段是 TBytesField 类型,对应的是 FireBird 里面的 Char(16) OCTETS 类型字段
  S := '{F3E75FED-5C47-439D-A5BE-913EF9457577}';
  G := StringToGUID(S);
  V := VarFromGUID(G);

  { 以下代码对 FdMemTable1 进行 Locate 成功。
  FdQuery1.Open();
  FDMemTable1.CopyDataSet(ClientDataSet1);

  DataSource1.DataSet := FDMemTable1;
  with FDMemTable1 do
  begin
    Locate('M_ID', varArrayOf([VarFromGuid(G)]), []);
  end;
  }

  with ClientDataSet1 do
  begin
    //Locate('M_ID',varArrayOf([V]) , []); // 会出现异常
    FindKey([V]);
  end;

end;

 

对应的 TBytesField,直接写入 GUID 成功:

procedure TForm1.Button3Click(Sender: TObject);
begin
  //M_ID 是 TBytesField 类型的字段,写入成功
  with ClientDataSet1 do
  begin
    Insert;
    FieldByName('M_ID').AsGuid := Self.GetGUID;
    Post;
  end;
end;

 

 

又:

如果是 FdMemTable,同样的 TBytesField 字段,采用上述 Locate 方法,可以成功定位。

因此,FdMemTable 比 ClientDataSet 确实好用一些。

 

SQL 查询:

在 Firebird 中对该 GUID 字段进行 query:select * from MATERIAL where M_ID=:MID

使用 FdQuery 控件,测试成功:

procedure TForm1.Button4Click(Sender: TObject);
begin
  //能够成功搜索到正确记录
  with FdQuery2 do
  begin
    Close;
    Params[0].AsGUID := StringToGUID('{F3E75FED-5C47-439D-A5BE-913EF9457577}');
    Open;
    DataSource1.DataSet := FdQuery2;
  end;
end;

 总结:

可以在 Firebird 数据库中采用16字节的 OCTETS 类型的字段来存储 GUID,比存储字符串格式的GUID要节约很多空间;字符串格式要36个字节.

对应到 Delphi 的 DataSet 的字段类型,是 TBytesField。可以在运行期采用 Field.AsGUID 的方式写入 TGUID 类型的数据,提交成功。

对于 FdQuery 和 FdMemTable 来说,上述 TBytesField 字段,可以进行 Locate,需要先把GUID参数转换为 Variant。

对于 ClientDataSet 来说,对 TBytesField 字段进行 Locate 会出现异常;对 TGUIDField 自动进行 Locate 不会出现异常但定位不到。但是,采用 FindKey 方法来定位,成功。因此对应 Firebird 数据库的 GUID 字段,ClientDataSet 可以使用 FindKey 的方式。需要注意的是,DataSet.FindKey 的字段,必须是索引字段。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值