4

次のように定義された Oracle DB にテーブルがあります。

CREATE TABLE AVALUES
(
  ACODE   VARCHAR2(4) NOT NULL,
  ATYPE   NUMBER NOT NULL,
  ANAME   VARCHAR2(50),
  CREATED DATE DEFAULT SYSDATE
)

Delphi 内には、アプリケーションに値を返す、これに似た ADOQuery コンポーネントのクエリがあります。

with qryComp do
begin
  Close;
  SQL.Text := 
    'SELECT ATYPE FROM AVALUES ORDER BY CREATED';
  Open;
  while not EOF do
  begin
    AddComponents('NAME' + FieldByName('ATYPE').AsString);
    Next;
  end;
  Close;
end;

多くのさまざまなクライアント PC に展開され、これは何年もの間正常に機能しており、コードは何も変更されていません。ただし、いくつかのクライアント PC では、最近、たとえば2ではなく1.999999999969を返すようになり、アプリケーションがクラッシュするようになりました。問題を探してみましたが、非常に断続的です。リモート デスクトップ経由でクライアント コンピューターに接続されているため、まったく再現できません。

これをさらに調査するために私ができることについて何か提案はありますか? 断続的で、少数のコンピューターでのみ発生するため、デバッグが困難です。Oracle クライアントに問題があるのではないかと思いますが、実際にそれを確認する方法がわかりません。

助けてくれてありがとう。

4

3 に答える 3

13

私が見ることができる唯一のことは、クライアントマシン上のFPU制御ワードの違いであり、浮動小数点型の処理に固有の丸めの問題があるため、精度の処理が異なります。( DelphiのドキュメントのSet8087CWを参照してください。リンクはXE2のドキュメントへのリンクですが、最近私が知っている重要な変更はないので、機能するはずです。)

それを修正する4つの方法があります(1つはありそうにない、3つはかなり簡単です):

  • データベース列を実際にはintegerタイプではなくタイプに変更しますNUMBER

  • 直接integer値を要求し、それを自分で変換します

    AddComponent('Name' + IntToStr(FieldByName('ATYPE').AsInteger));

  • 使用時に、列を使用するコードを変更します。

    AddComponents(Format('NAME%d', [FieldByName('ATYPE').AsInteger]));

またはAddComponentsそれ自体:

procedure AddComponents(Prefix: string; Value: Integer);
begin
  DoWhateverIDo(Prefix + IntToStr(Value));
end;

// calling code
AddComponents('Name', FieldByName('ATYPE').AsInteger);
  • データベースを操作する前に8087CWの値を明示的に設定し、終了したら元に戻します。これは私にとって最悪の選択肢のようです。上記のドキュメントリンクにこれを行う例があります。
于 2012-05-22T12:33:57.600 に答える
2

通貨のデータ型で同様の問題が発生しました(ブログ記事: 1.99 が突然 1.99 に等しくなくなった理由 )。一部の DLL が FPU (プロセッサ) 制御ワードを変更しているようです。これは、問題がマシンに依存する理由を説明しています。また、Delphi にはSafeLoadLibrary、コントロール ワードを復元する関数が含まれていることもわかりました。しかし、DLL をロードした後でも、DLL 関数の呼び出しによって制御ワードが再び台無しになる可能性があるため、これは大きな助けにはなりません。

于 2012-05-22T15:20:40.567 に答える
1

Oracle NUMBER データ型は浮動小数点データ型であるため、float / double 近似の問題があります。What Every Computer Scientist Should Know About Floating-Point Arithmeticを必ずお読みください。

于 2012-05-22T12:27:34.753 に答える