SQL データベースの BLOB フィールドに格納する必要があるバイナリ データがあります。UPDATE (データベースへの格納) の場合、バイナリ データは文字列 (BDS2006、ユニコードなし) として提供されます。BLOB フィールドが READ の場合、バイナリ データを文字列として返す必要があります。したがって、次の 2 つのコードを使用しました (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;
それが正しい/良い/良い方法かどうかはわかりませんが、数年間はうまくいきました.
現在、特定のバイナリ データのセットに問題があり、データベースに UPDATE され、データベースから読み取られた後、変更/破損されます。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 に設定されます。もちろん、問題には他のケースもあるかもしれませんが、それは私が毎回再現できるものです.
最後にもう 1 バイト追加して 1520 バイトにすると、すべて正常に動作します。ここには、それを引き起こす可能性のある特別なものは見当たりません。