【问题标题】:Problem with updating blob, if blob contains specific data如果 blob 包含特定数据,则更新 blob 时出现问题
【发布时间】:2023-03-23 06:14:01
【问题描述】:

我有二进制数据需要存储在 SQL 数据库的 BLOB 字段中。 在 UPDATE(存储到数据库中)的情况下,二进制数据以字符串形式出现(BDS2006,无 unicode)。 当 BLOB 字段为 READ 时,需要将二进制数据作为字符串返回。 因此,我使用了这两段代码(qry是一个TQuery):

阅读:

var s: string;
begin
  qry.SQL.Text := 'SELECT BlobField FROM Table WHERE ID=xxx';
  qry.Open;
  if qry.RecordCount > 0 then
    begin
      qry.First;
      s := qry.FieldByName('BlobField').AsString;
    end;
end;

更新:

var s: string;
begin
  s := ...binary data...
  qry.SQL.Text := 'UPDATE Table Set BlobField=:blobparam WHERE ID=xxx';
  qry.ParamByName('blobparam').AsBlob = s;
  qry.ExecSQL;
end;

我不确定这是否是正确/好/好的方法,但它已经运行了几年。

现在一组特定的二进制数据存在问题,在被更新到数据库中然后从数据库读取后被更改/损坏。 将ExecSQL前的param值与读取后s的值进行比较,数据的最后一个字节(本例共1519字节)由02h变为00h。

由于我不确定我的代码是否正常工作,我尝试使用 TBlobStream 来检查结果是否发生变化。

阅读:

var s: string;
    bs: TStream;
    st: TStringStream;
begin
  qry.SQL.Text := 'SELECT BlobField FROM Table WHERE ID=xxx';
  qry.Open;
  if qry.RecordCount > 0 then
    begin
      qry.First;
      st := TStringStream.Create('');
      bs := qry.CreateBlobStream(qry.FieldByName('BlobField'), bmRead);
      bs.Position := 0;
      st.CopyFrom(bs, bs.Size);
      st.Position := 0;
      s := st.ReadString(st.Size);
    end;
end;

更新:

var s: string;
    bs: TStream;
    st: TStringStream;
begin
  s := ...binary data...
  st := TStringStream.Create(s);
  st.Position := 0;
  qry.SQL.Text := 'UPDATE Table Set BlobField=:blobparam WHERE ID=xxx';
  qry.ParamByName('blobparam').LoadFromStream(st, ftBlob);
  qry.ExecSQL;
end;

结果一样,读取数据的最后一个字节损坏了。

我的问题可能是什么?


编辑:

仅使用流会产生同样的问题。

我发现只有当数据正好是 1519 字节时才会发生这种情况。然后,只有在那时,最后一个字节才被设置为 0,不管它之前是什么。当然,问题可能还有其他情况,但这是我每次都可以重现的情况。

如果我在末尾再添加一个字节,使其达到 1520 字节,一切正常。 我只是没有看到任何可能导致它的特殊情况。

【问题讨论】:

  • 服务器操作系统或数据库软件中是否安装了任何更改/补丁?
  • 不,我只是获取运行了一段时间的可执行文件,并为其提供特定的二进制数据,然后它从更改的数据库中返回。我尝试了过去几年完成的几个版本,都表现相同。如果它与一组数据中断,则通常是中断的。我确定这不是数据库本身,它应该是我的代码中的某些东西,可能是一些转换。我只是看不到它。
  • 对不起,对数据库服务器也没有更改。它是一个嵌入式数据库引擎,这使它成为我依赖的可执行文件。
  • 尾随的 NULL (00h) 使它看起来像是某种缓冲区大小问题,通过 PChar(C 字符串)传递了一些东西。不过 5EFh / 5F0 看起来很奇怪。
  • 只有Pascal字符串和TParams,所以应该不会有这样的问题。如果我这样做的方式是正确的,那么可能还有另一个原因。我只是不确定我是否在这里做了我不知道的坏事。

标签: delphi blob


【解决方案1】:

我同意 Gerry 的观点,即尾随 NULL 看起来像一个字符串问题。

您修改后的代码仍然使用 TStringStream 写入数据。您是否尝试过使用 TBlobStream 写入数据,并查看是否有所作为?

或者,在问题数据的末尾添加一些打包字节,以检查它是否与特定的大小/边界问题有关。或者尝试用固定的测试模式替换问题数据,以缩小问题范围。

FWIW 我使用 blob 很长时间都没有问题,但从未将它们视为字符串。

祝你好运,缩小问题范围。

更新:在我看来您的代码很好,但是您在数据库/数据访问软件的某个地方遇到了其他人的错误。您使用的是什么数据库/驱动程序/访问代码?

【讨论】:

  • 问题与数据库有关,感谢所有有助于解决问题的建议。
猜你喜欢
  • 1970-01-01
  • 2013-04-14
  • 2021-04-21
  • 2020-02-06
  • 2014-04-03
  • 2017-05-07
  • 1970-01-01
  • 2019-03-19
  • 1970-01-01
相关资源
最近更新 更多