我有二进制数据需要存储在 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 之前的参数值与读取后的 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 字节,一切正常。我只是没有看到任何可能导致它的特别之处。