12

Genderと制約があるとしますCHECK( Gender IN ('F', 'M', 'OTHER'))。 私が誤ってこれをクライアント側で処理するのを忘れた場合、ユーザーは、ユーザーにとっても、保守またはデバッグする開発者にとっても、あまり役に立たない
ようなsmthを目にするでしょう。
ORA-02290: check constraint (SYS_C099871244) violated

(疑似)Javaのような開発者定義のメッセージを提供する方法はありますか
assert Gender IN (0,1):'Gender must be F or M'

私が考えることができる唯一の方法は、制約をBEFORE UPDATE OR INSERTトリガーに移動し、失敗した場合は実行することですRaise_Application_Error( code, my_message )。しかし、私はそれが好きではありません

コメントにあるように、特定の理由のリストを編集
します 1.ロジックをできるだけデータに近づけたい
2.エンドユーザーの場合Raise_Application_Errorメッセージはアプリケーションメッセージと区別がつかない
3.アクセスデータがバイパスされている場合でも、開発者には素晴らしいメッセージが表示されますアプリケーション
4.制約をトリガーに移動するのは醜いです(そうですか?)ので、Raise_Application_Errorとは異なるsmthを見つける必要があります

EDIT2 1 .5年後、db関連の仕事を辞めた後、ついにそれが私に起こりました。これについて私が本当に気に入らないのは、コードの重複です。サーバー側とクライアント側でまったく同じロジックを繰り返す必要があります。ほとんどの場合、2つの異なる言語で。そして、それらの同期を維持します。これはただ醜いです。

答えがはっきりと示しているように、これについて私ができることは何もありません。それで、私が良い市民になり、最終的に答えを受け入れる時が来ました(申し訳ありませんが、それを忘れてしまいました)。

4

4 に答える 4

9

制約は、データベースがユーザーからではなく、誤ったアプリケーションから自身を保護するために使用するものです。

つまり、制約違反はアプリケーションによってキャプチャされ、場合によってはユーザーに表示するためにクリーンアップされる必要があります。それをしなかったアプリケーションは、なんらかの形で欠陥があると思います。

あなたのアプリケーション(少なくともこの場合)は決してそれが起こるのを見るべきではないので、私は「おそらく」と言います。そのようなものには、ほぼ確実にドロップダウン限定選択コントロールを使用する必要があります。コンボボックスまたは(ショック、ホラー)自由形式のテキスト入力フィールドを使用した場合は、再定義する必要があります。

これは、もちろん、アプリケーションと制約がいずれかの時点で同期しなくなっていない限り、違反が発生しないことを意味します。しかし、それは、顧客があなたのアプリケーションに汚い小さな手を差し伸べるずっと前に、テストで捕らえられるべきものです。


実際の質問に答えるために、制約違反に対してOracleから出力されるメッセージは変更できません。できる最善の方法は、制約にインテリジェントな名前を付けて、エンドユーザーにとって意味のあるものにすることです。

しかし、私は、ユーザーへのこの問題の提示は、データベース層ではなく、アプリケーション層の責任であると主張しています。

于 2011-05-20T07:36:23.243 に答える
5

例外メッセージ「ORA-02290:チェック制約(SYS_C099871244)違反」を「ORA-20001:性別はFまたはMである必要があります」などの別のメッセージに置き換えるようにOracleに常に指示する方法を探している場合、答えは次のとおりです。いいえ、できません。

あなたができることは、開発者がコードで次のようなものを使用できるソリューションを提供することです。

...
begin
    insert into emp (empno, gender) values (p_empno, p_gender);
exception
    when others then
       error_pkg.handle_exception;
end;

このerror_pkg.handle_exceptionプロシージャは、Oracle例外メッセージを解析し、制約の名前を抽出し(制約違反の場合)、相互参照テーブルでその制約名を検索して必要なメッセージを取得し、を使用raise_application_errorして新しい例外を再発生させます。メッセージ。

オラクルはこのようなパッケージとテーブルを標準で提供できると思いますが、実際にはシステムでのエラー処理にはさまざまな要件があるため、一般的に十分に役立つとは考えられていません。

于 2011-05-20T09:01:44.690 に答える
4

つまり
、私が知っているカスタム処理のOracleエラーをキャッチする方法はありません。しかし、とにかくそうしようとすべきではないと思います。


長いバージョン:
あなたの理由の背後にある意図は良いです、しかし...

ロジックをできるだけデータに近づけるのが本当に好きです

ロジックは可能な限りデータに近づける必要があります。それは事実です。ただし、これは適格ではありません。これはロジックではありません。これは、すでに定義されたロジックの例外を識別するコードの表示であり、表示をデータまたはロジックレイヤーと混合しないでください(エラーメッセージのドメインはシステムのすべての部分にまたがっています。クライアント側からサーバー側へ、メッセージの翻訳、一貫性のある更新、より簡単な管理と概要などについても考えてください...)

エンドユーザーの場合、Raise_Application_Errorメッセージはアプリケーションメッセージと区別できません

真ですが、その逆も有効であるため、特に関連性はありません-DBエラーコード、アプリケーションエラーコードの中央リポジトリがあり、エラー処理がそれを処理する場合、どのレイヤーがエラーメッセージを表示しているかは(エンドユーザーにとって)無関係です。また、長期的には、それがあなたの仕事を節約するかどうかは明らかではありません。

アプリケーションをバイパスするデータにアクセスする場合でも、開発者にはすばらしいメッセージが表示されます

これは真実です。DBに直接アクセスする開発者にとっては、より良いエラーメッセージが表示されます。ここでもいくつかのコメントが当てはまります。複雑なシステムでは、アプリケーション層をバイパスすることは許可されるべきではありません(開発者であっても)。それが許可されれば、開発者は制約名からエラーメッセージを検索する場所を知っていると期待できます(エラーコードとメッセージの中央リポジトリは同じデータベースに保持される必要があります)

制約をトリガーに移動するのは醜いので(そうですか?)、Raise_Application_Errorとは異なるsmthを見つける必要があります

それはプレゼンテーションであり、DDLであってはならないという意味で醜いです。また、トリガーを介して実行すると、不当な(?)パフォーマンスペナルティが発生します(どれだけ大きく、どれだけエレガントに実行できるかはわかりません)。

注:全体として、DBMSエラー処理にフックする可能性があると便利な機能になることに同意します。

ただし、エラー処理とエラーメッセージ処理には次のプロパティがあります

  • 保守可能である必要があります(これは、理論的には、カスタムエラーメッセージを情報スキーマに格納することでクリーンに実行できますが、SQL標準では指定されていないため、これは純粋に理論的なコメントです-実際には、このような目的のために独自のテーブルを用意する必要があります)。

そして、さらに重要なのは

  • エラーメッセージの処理はコンテキストに依存します(エラーハンドラーはデータクライアントの観点から最も通知されます-同じエラーコードが異なる表示、異なるメッセージを必要とする場合があります)
于 2011-05-20T09:50:44.507 に答える
3

制約がクライアントに発生する場合でも、サポートによる(潜在的な)分析のためにファイルにログインする場合でも、より有用なメッセージが表示されるはずです。

制約に名前を付けると、さらに役立ちます。

私は次のようなものに行きます

ALTER TABLE blah ADD CONSTRAINT blah_gender_ck CHECK ( Gender IN ('F', 'M', 'OTHER'));
于 2011-05-20T08:35:46.003 に答える