我有二进制数据需要存储在SQL数据库的BLOB字段中。 在UPDATE(存储到数据库中)的情况下,二进制数据以字符串形式出现(BDS2006,没有unicode)。 当BLOB字段为READ时,二进制数据需要作为字符串返回。 因此,我使用了这两段代码(qry是一个TQuery):
READ:
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;
我不确定这是否是正确/好/好的方式,但它已经运作了好几年。
现在有一组特定的二进制数据存在问题,这些二进制数据在更新到数据库之后,然后更改/损坏数据库中的READ。 将ExecSQL之前的参数值与读取后的s值进行比较时,数据的最后一个字节(在本例中为1519字节)从02h变为00h。
由于我不确定我的代码是否正常工作,我尝试使用TBlobStream来检查结果是否发生了变化。
READ:
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字节,一切正常。 我只是没有看到任何可能导致它的特殊情况。
答案 0 :(得分:1)
我同意Gerry的说法,尾随的NULL看起来像一个字符串问题。
您修改的代码仍使用TStringStream写入数据。您是否尝试使用TBlobStream编写数据,并查看是否会产生影响?
或者,在问题数据的末尾添加一些打包字节,以检查它是否与特定的大小/边界问题相关。或者尝试使用固定的测试模式替换问题数据,以缩小问题范围。
FWIW我长时间使用blob没有问题,但从未将它们视为字符串。
祝你好运缩小问题。
更新:在我看来你的代码很好,但你在数据库/数据访问软件的某个地方遇到了别人的错误。你使用什么数据库/驱动程序/访问代码?