23

テーブルに外部キーの列を作成しようとしていますが、MySQLでは本来よりも難しいです。戻って、すでに使用されているテーブルに特定の変更を加える必要があります。では、MySQLが特定の値が適切であることを確認する必要があるのでしょうか。とにかくこのデータベースにアクセスするために使用しているPHPのような言語でそれを行うことはできませんか?

同様にNOTNULLを使用します。このデータベースにPHPでのみアクセスする場合、null値が入力されていないことをPHPに確認させることはできませんか?

PHPで実行できるのに、なぜMySQLを使用してこれらの制約を適用する必要があるのですか?


上記の理由から、NOTNULLは無視するのが非常に愚かな部分であることに気づきました。しかし、MySQLは、深刻な程度のモンキーなしでは外部キーを強制しません。

あなたの意見では、「偽の」外部キーを使用して、入力する値が他のテーブルでPHPと一致するかどうかを確認するだけでも悪いのでしょうか。

4

15 に答える 15

56

PHP で間違いを犯すことは 100% 保証されています。PHP は手続き型です。必要なのは宣言的な制約です。スタック全体に、「これらはデータに対する制約であり、これらの制約に違反することはできません」と伝えたいと考えています。データに制約を適用する方法として、「ステップ 1 ... ステップ 2 ... ステップ 3 ... ステップ 432 ...」をあまり使いたくないでしょう。

  • あなたはそれを間違えるでしょう
  • 後で変更すると、今行ったことを忘れてしまいます
  • あなたが現在知っているように、これらの暗黙の制約をすべて知っている人は誰もいません。これには、将来の自分も含まれます。
  • 制約を常に適切に適用するには、大量のコードが必要です。データベース サーバーには既にこのコードがありますが、それを記述する準備はできていますか?

実際には、「MySQL でできるのに、PHP を使用してこれらの制約を適用する必要があるのはなぜですか?」という質問をする必要があります。

于 2008-12-19T21:54:24.553 に答える
18

プログラマーがバグのないコードを「ただ」書けないのと同じ理由で、PHPでそれを「ただ」行うことはできません。思ったより難しいです。そんなに難しくないと思うなら特に。

于 2008-12-19T21:58:19.707 に答える
8

(もちろんバグのない) PHP ページ以外の方法で DB にアクセスすることは絶対にないと断言できるなら、PHP だけでそれを実行しても問題ありませ

実際のシナリオには常に不確実性が含まれているため、DB サーバーでデータの整合性を監視することをお勧めします。

単純なデータベースの場合、参照整合性制約は絶対的な要件ではないかもしれませんが、あると便利です。アプリケーションが複雑になればなるほど、それらからより多くの利点を引き出すことができます。早い段階で計画を立てておくと、後の生活が楽になります。

さらに、参照整合性は、すべてのダーティ ハックが可能になったわけではないため、より規則正しい方法でデータベースを設計することを強制する役割を果たします。これも良いことです。

于 2008-12-19T21:57:05.403 に答える
2

未来を予測することは不可能なので、データベースに制約を実装することが重要です! 要件がいつ変更されるかはわかりません。

また、複数の開発者が同じアプリケーションで作業している可能性も考慮してください。あなたはすべての制約が何であるかを知っているかもしれませんが、経験の浅い開発者は知らないかもしれません。データベースに制約があると、後輩の開発者のコ​​ードはエラーを生成し、修正が必要であることを認識します。制約がなければ、コードは失敗せず、データが破損する可能性があります。

于 2008-12-19T21:56:18.247 に答える
2

私は通常、データベースで制約を宣言することに賛成です。制約の引数:

  • 宣言型コードは、命令型コードよりもバグをなくすのが簡単です。アプリ コードにバグが含まれていても、制約が適用されます。
  • 同じデータベースにアクセスする複数のアプリケーションまたはコード モジュールがあり、ビジネス ルールを均一に適用する必要がある場合は、「自分自身を繰り返さない」原則をサポートします。制約を変更する必要がある場合は、多数のアプリがある場合でも 1 か所で行うことができます。
  • ユーザーがアドホック クエリ ツールを使用してデータベースを操作し、アプリケーションをバイパスしようとした場合でも、データの整合性を確保します。
  • 一貫性を強化します。つまり、データ更新の前後でデータが有効な状態にあることを常に確認できます。制約を使用しない場合は、定期的なクエリを実行して、破損した参照をチェックしてクリーンアップする必要がある場合があります。
  • 制約を使用して、カスケード更新/削除を簡単にモデル化できます。アプリケーション コードで同じことを行うのは複雑で非効率的であり、アトミックに変更を適用することはできず (トランザクション分離の使用が推奨されます)、バグの影響を受けやすくなります。
  • 制約は、列名と SQL データ型が役立つのと同様に、データベースをより自己文書化するのに役立ちます。

制約に対する引数:

  • より複雑なビジネス ルールは、宣言型の制約によってモデル化することはできないため、いずれにしてもアプリケーション スペースに実装する必要があります。それを考えると、すべてのビジネス ルールを 1 つの場所 (アプリ) に同じ言語で実装してみませんか? これにより、コード リビジョンのデバッグ、テスト、および追跡が容易になります。
  • 制約には多くの場合、挿入/更新中にある程度のオーバーヘッドが発生するインデックスが含まれます。一方、制約を宣言しなくても、検索条件や結合条件で頻繁に列が使用される可能性があるため、おそらくインデックスが必要になるでしょう。
  • 制約があると、データの誤りを「クリーンアップ」しようとする試みが複雑になる可能性があります。
  • 現在のプロジェクトでは、参照制約に関する MyISAM と InnoDB の非互換性が問題になっています。
于 2008-12-19T23:09:30.843 に答える
2

それらは非常に重要です。モデル全体を PHP で定義したくない場合。PHP コードにバグがある場合はどうなりますか? ビジネス ルールで禁止されている列を簡単に null にすることができます。データベース レベルで定義することにより、少なくとも無料でそのチェックを取得できます。PHP にバグがある場合や、他のツールがデータベースを使用する場合は、本当に嫌になるでしょう。あなたは問題を求めているだけです、IMHO。

これはストーリーの非常に短いバージョンです。

于 2008-12-19T21:54:25.097 に答える
1

私にとって NOT NULL の使用に関する最も重要なことは、ドキュメントの部分です。数か月後にプロジェクトに戻ると、NULL を許容できる列を忘れてしまいます。列に NOT NULL と表示されていれば、その列からの潜在的な NULL 値に対処する必要がないことがわかります。そして、それが null を許可する場合、それらに対処する必要があることは確かです。

もう 1 つは、他の人が指摘しているように、どこかで何かを見逃している可能性があり、データのクリーンアップが面倒であるか、完全に不可能である可能性があることです。データベース内のすべてのデータが一貫していることを確認することをお勧めします。

于 2008-12-19T22:00:28.830 に答える
1

MySQL でこれらの制約を有効にすると、ほとんど時間がかかりません。PHP やその他のコードの欠陥によるバグが 1 つでも防げるなら、それだけの価値はありませんか?

自分自身を救うバグの種類はかなり厄介なものになる可能性があることに注意してください. バグ自体を見つけて修正することは難しくありません。厄介な点は、バグを修正すると、復旧できない可能性のある大量の不完全なデータが残ることです。

私は、「まあ、PHP 以外の何かがいつかあなたのデータにアクセスするかもしれない」という角度からこの問題にアプローチすることさえしません。それは本当ですが、私の考えではさらに重要なのは、いくつかの単純な制約を追加するだけで自分自身を救うことができる頭痛、時間 (お金)、およびデータの損失です。

于 2008-12-19T22:02:37.920 に答える
1

構造データの整合性にはデータベースを使用し、残りの部分には BR レイヤーを使用します。そして、できるだけ早くエラーをキャッチします。彼らは一緒に働きます。

運が良ければ、コードが完成すると、データベース RI エラーは発生しなくなります。そして、誇らしげに自分が最初であることを発表できます。

于 2008-12-19T22:03:28.963 に答える
1

データ層で制約によってデータの一貫性を強制すると、データの一貫性が維持され、アプリケーション内で低コストのランタイム バグ チェックが提供されます。

制約に価値がないと思われる場合は、小規模/非ミッション クリティカルなシステムを使用しているか、システムの品質を向上させる大きなチャンスを逃していることになります。これは控えめに言っても過言ではありません。

選択肢には、別の RDBMS を選択する、独自のメタデータ システムを再発明する、制約を手動で管理するなどがあります。スキーマ/システムの複雑さが増し、進化するスキーマが不必要に複雑になるにつれて、メタデータ システムを使用しないクエリの手動管理は、適切に維持および監査することがすぐに不可能になります。

別の RDBMS を選択することをお勧めします。

整合性チェックは、想像以上に難しいものです。たとえば、MySQL はトランザクション読み取り一貫性を使用します。これは、チェック対象の値が別のトランザクションのスコープ内で同じ値ではない可能性があることを意味します。データ層に直接バインドされていない場合、同時アクセスの一貫性スキーマを正しく理解することは非常に困難です。

結局のところ、手作業によるチェックに多少の労力を費やしたとしても、考慮に入れなかった、または形成時にエラーを犯したコーナーケースをトラックで通過できる可能性が高い.

NOT NULL の質問について... 明らかなデータ フィールドの要件は、出発点として適切です。列の NULL 可能性を定義する際に考慮すべき事項が他にもいくつかあります。

クエリを作成するときに非常に役立つ保証を提供します。さまざまな結合で NULL 条件を使用して、条件が NULL を許可する場合に想定できない NULL 値とは別に、テーブルの行が一致しないことを示す場合があります。(NULL が許可されている場合、一致は、行が一致しなかったか、行は一致したが列の値が null であることを意味します。)

NOT NULL を使用すると、値に一致するより単純なクエリのルールを定義するのにも役立ちます。value1 と value2 の両方が NULL の場合、「WHEN value1 = value2」とは言えないため、評価の結果は依然として false です。

于 2008-12-22T07:04:25.843 に答える
1

PHP コードに完全にバグがない場合でも、スクリプトの途中で停止し (メモリ不足エラー、一部のライブラリでの segfault など)、データベースに半分挿入されたものが残る可能性があるため、InnoDB とトランザクションを使用することが重要です。

制約についても同じです。もちろん、適切なフォーム検証と、バグをキャッチするためのデータベース制約が必要です。

データベースの制約を指定するのは簡単ですが、アプリケーションのバグを見つけるのは難しく、制約がなければさらに困難です。

私の経験では、不適切に制約されたデータベースや、MyISAM を使用するものはすべて、数か月使用すると一貫性のないデータになり、そのデータがどこから来たのかを見つけるのは非常に困難です。

于 2009-07-25T10:58:51.377 に答える
0

データベース レベルでデフォルト値と制約を実装します。消費するアプリケーションにとって受け入れ可能なデータになるルール。これにより、完全性の問題を回避できます。

次に、アプリケーション レベルでより適切な既定値と制約を実装します。データベース レベルでの制約の実装やデフォルト値の生成が技術的に禁止されている場合 (データベース外部の API へのアクセス) は、アプリケーションで実行する必要があります。これにより、より適切なデフォルト値が得られます。ただし、セグメンテーション違反またはアプリケーションの一般的な障害によって、許容できないデータが永続化されることはありません。

于 2013-03-23T13:41:43.823 に答える
0

宗教的な話題で恐縮です。

純粋な観点からは、データベースに参照整合性を持たせたいと考えています。これは、制約が 1 か所にあるため、データベースにアクセスするアプリケーションが多数ある場合に理想的です。残念ながら、現実の世界は理想的ではありません。

私の経験では、何らかの参照整合性を強制する必要がある場合、アプリケーションはこれを行う方法を知る必要があります。これは、それが最終的なアービターであるか、データベースもチェックするかどうかに関係ありません。また、データベース参照整合性を実行する場合でも、参照整合性に違反するため、アプリケーションは、データベースが更新を拒否した場合に何をすべきかを知る必要があります...

補足として、外部キー制約をサポートするように MySQL を設定するのは、InnoDBに移行する必要があるため、少し手間がかかります。それだけを行えば、1 に設定することで多くのパフォーマンスを取り戻すことができますinnodb_flush_log_at_tx_commit。しかし、その代わりに、サイトを再設計してトランザクションを認識できるようにしたほうがよいでしょう。そうすれば、InnoDB の 2 つの利点が得られます。

于 2008-12-22T05:24:36.420 に答える
0
  1. あなたのデータベースが PHP によってのみアクセスされると確信できるとは思いません。

  2. これらの制約をスキーマに含めると、スキーマを調査することで、データがどのように使用され、関連付けられているかをよく理解できます。これらすべてをコードに入れるだけでは、誰かがデータベースと PHP コードの両方を調べる必要があります。

しかし、それは設計ドキュメント、データ ディクショナリ、および論理データベース設計に含まれるべきではないでしょうか?

はい。ただし、これらのドキュメントは古くなって古くなることで有名です。あなたがそんなことを決して許さないことはわかっていますが、規律の緩いプロジェクトの経験がある人は、あなたのプロジェクトについてこれを想定し、ドキュメントではなく実際のコードとスキーマを調べたいと思うかもしれません。

于 2008-12-19T22:16:44.850 に答える
0

デフォルト値のルールはデータベース側ではなくコード側で実装する必要があると深く確信しているため、あなたの質問に非常に感謝します。これは非常に単純な理由で、ユーザーがデータベースの変更を開始する場合 ( INSERTS、SELECTS、UPDATES)、これらの変更はすべてのビジネス ルールを統合し、デフォルト値は基本的にビジネス ルールです。

  • 請求書番号のない請求書はありません
  • 数量のない請求書明細はなく、0 または NULL は受け入れられません
  • 受信日のないメールは来ない

私たちは数年前に、「null でない」、「空の文字列を (許可しない) 許可する」、およびその他の「デフォルト値」のトリックなどの「データベース側」のアーティファクトをすべて取り除くことを決定しましたが、それは完全に機能します。デフォルト値を支持する引数は、主に一種の「セキュリティ」原則を指します (「コード側で忘れてしまうので、データベース側で行います / あなたの言語はそのために作られていません / それを行う方が簡単です」データベース側で」)、データベース側でデフォルト値を実装しないことを選択すると意味がありません。デバッグ中にビジネスルールが適切に実装されていることを確認してください.

過去 2 年間、チームの誰もテーブルでデフォルト値を宣言することを考えたことはありませんでした。私たちの後輩は「デフォルト値」というものさえ知らないのではないでしょうか。

編集:ここでいくつかの回答を読み直すと、私の最後のコメントは次のようになります:DBまたはコードのいずれかの側で実行しますが、選択して片側のみで実行してください! そのようなコントロールを両側に持つことほど危険なことはありません。なぜなら、最終的には (1) 両方の側が本当に同じルールを実装しているかどうかがわからないからです。つまり、(2) ルールをチェックするということは、両方の側をチェックすることを意味するということです。ぐちゃぐちゃになる!もちろん、最悪の状況は、ジョブの一部 (つまり、データベースの作成時に識別されたルール) がデータベース側で実行され、残りの部分 (つまり、新しく識別されたルール) がクライアント側で実行される場合です...悪夢 ....

于 2008-12-19T22:34:53.317 に答える