2

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 バイトにすると、すべて正常に動作します。ここには、それを引き起こす可能性のある特別なものは見当たりません。

4

1 に答える 1

1

末尾の NULL が文字列の問題のように見えるという Gerry に同意します。

変更したコードは、引き続き TStringStream を使用してデータを書き込みます。TBlobStream を使用してデータを書き込んでみて、違いがあるかどうかを確認しましたか?

または、問題データの末尾にパッキング バイトを追加して、特定のサイズ/境界の問題に関連しているかどうかを確認します。または、問題データを固定のテスト パターンに置き換えて、問題を絞り込んでみてください。

FWIW私は長い間問題なくブロブを使用してきましたが、それらを文字列として扱ったことはありません.

問題を絞り込んで頑張ってください。

更新:あなたのコードは問題ないように見えますが、データベース/データアクセスソフトウェアのどこかで他の誰かのバグに遭遇しています。どのデータベース/ドライバー/アクセス コードを使用していますか?

于 2009-08-24T11:54:55.333 に答える