こんにちは、Habr!
私は誠実に仕事をするのに慣れていましたが、この投稿を書く前に、実際にバグであることに気づいたことを何度もチェックし
(コンピューターの前で眠れない夜の結果ではなく) 、インターネットで同様のものを見つけようとしました。 無駄だ。 ベロレン。 無駄だ。
したがって、興味がある場合は、Catにようこそ。コンポジットVIEWに最初のレコードを追加しても正しく機能しない単純なアーキテクチャ要素を確認できます。
著者が喫煙したもの
まず、そのようなアーキテクチャソリューションが必要な理由について簡単に説明します。
詳細(機密情報の非開示に関する合意、すべてのもの)を公開せずに、現在のプロジェクトに取り組む際に、次の関係を実装するためにオブジェクトの3つのクラス(
a 、
b 、
c )が必要であると言います:
cから
a -∞から1
cから
b -∞から0..1。
したがって、各オブジェクト
cは1つのオブジェクト
aに関連付けられており、1つのオブジェクト
bに関連付けられている場合も、オブジェクト
bにまったく関連付けられていない場合もあります。
フリーランサー用エクササイズバイク
このデータベースフラグメントは、次のように設計されました。
+クラス
aのすべてのオブジェクトをリストするテーブル(簡単にするために、識別子以外の唯一のパラメーターを名前にします);
+クラス
b (同じパセリ)のすべてのオブジェクトをリストするテーブル。
+クラス
cのすべてのオブジェクトをリストするテーブル(パラメータを持つ識別子を除く:名前、クラス
aのオブジェクトの識別子(必須)、クラス
bのオブジェクトの識別子(オプション));
+クラス
aと
bのオブジェクトの名前が関連付けられたクラス
cのすべてのオブジェクトを含むビュー(セキュリティ上の理由から(テーブル自体に影響を与えずにVIEWに権限を付与できます)、データ整合性検証ロジックの一部をphpからMySQLに転送し、カスケードチェックオプションを使用して、PHPコードのJOINをドラッグしないでください。
ムッシュは子供について多くのことを知っています
ビューの可変性を確保するために、INNER JOIN(LEFT OUTER JOINはビューの可変性を禁止しています)のみを使用する必要がありましたが、一方で、クラス
bのオブジェクトに関連しないクラス
cのオブジェクトもビューに表示する必要がありました。
これを行うために、次のトリックを適用しました。クラス
bの関連オブジェクトの識別子もゼロ( '0')にします。つまり、クラス
bの関連オブジェクトはありません。 また、クラス
bのオブジェクトのテーブルに、クラス
bのオブジェクトが存在しないことに対応する(識別子がゼロの)nullレコードが含まれるようにします(名前 'N / A'とします)。
また、WITH CASCADED CHECK OPTIONと組み合わせたこのトリックは、クラス
cのオブジェクトの表現に適用されるINSERTステートメントの異常な動作を与え
ます 。
INSERTステートメントの不良を教える方法
状況を再現するモデルクエリをデータベースに提供します。
CREATE TABLE `a`(`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,`name` VARCHAR(255) DEFAULT NULL) ENGINE='InnoDB' CHARSET='utf8' COLLATE='utf8_general_ci'; INSERT INTO `a`(`name`) VALUES('test_a'); CREATE TABLE `b`(`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,`name` VARCHAR(255) DEFAULT NULL) ENGINE='InnoDB' CHARSET='utf8' COLLATE='utf8_general_ci'; SET SESSION `SQL_MODE`='NO_AUTO_VALUE_ON_ZERO'; INSERT INTO `b`(`id`,`name`) VALUES('0','N/A'); INSERT INTO `b`(`id`,`name`) VALUES('1','test_b'); SET SESSION `SQL_MODE`=''; CREATE TABLE `c`(`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,`name` VARCHAR(255) NOT NULL,`a` INT NOT NULL,`b` INT DEFAULT '0',FOREIGN KEY(`a`) REFERENCES `a`(`id`),FOREIGN KEY(`b`) REFERENCES `b`(`id`)) ENGINE='InnoDB' CHARSET='utf8' COLLATE='utf8_general_ci'; CREATE VIEW `C` AS SELECT `t1`.`id` `id`,`t1`.`name` `name`,`t2`.`name` `a`,`t3`.`name` `b`,`t1`.`a` `a_id`,`t1`.`b` `b_id` FROM `c` `t1` JOIN `a` `t2` ON(`t1`.`a`=`t2`.`id`) JOIN `b` `t3` ON(`t1`.`b`=`t3`.`id`) WITH CASCADED CHECK OPTION; SELECT `id` FROM `a`; SELECT `id` FROM `b`;
mysql> SELECT `id` FROM `a`; +----+ | id | +----+ | 1 | +----+ 1 row in set (0.01 sec) mysql> SELECT `id` FROM `b`; +----+ | id | +----+ | 0 | | 1 | +----+ 2 rows in set (0.00 sec)
すべてが正しいはずです。
次に、関連付けられたオブジェクト
bのない最初のレコードを
Cビューに挿入してみましょう。
mysql> INSERT INTO `C`(`a_id`,`name`) VALUES('1','test_c'); ERROR 1369 (HY000): CHECK OPTION failed 'test.C' mysql>
がっかり? 私はあなたのことは知りませんが、私は-はい。
わかった それを理解してみましょう。
テーブル
cに対してまったく同じクエリを直接実行し、
Cビューの内容を表示します。
mysql> INSERT INTO `c`(`a`,`name`) VALUES('1','test_c'); Query OK, 1 row affected (0.09 sec) mysql> SELECT * FROM `C`; +----+--------+--------+------+------+------+ | id | name | a | b | a_id | b_id | +----+--------+--------+------+------+------+ | 1 | test_c | test_a | N/A | 1 | 0 | +----+--------+--------+------+------+------+ 1 row in set (0.00 sec) mysql>
がっかり? 私はあなたのことは知りませんが、私はとても知りました。
「バグ」という言葉を除いて、この動作を説明することはできません。
さらに、テーブル
cを元の形式に戻すと、
C表現を介してレコードが強打されて追加されます。
mysql> DELETE FROM `c`; ALTER TABLE `c` AUTO_INCREMENT=1; INSERT INTO `C`(`a_id`,`name`) VALUES('1','test_c'); SELECT * FROM `C`; Query OK, 1 row affected (0.05 sec) Query OK, 0 rows affected (0.09 sec) Records: 0 Duplicates: 0 Warnings: 0 Query OK, 1 row affected (0.00 sec) +
結論は?
ナフは言った。 ハブロフスクの人々が真夜中の回避と真昼の書癖のこの果物を承認した場合、コミュニティでバグレポートを書く方法を学ぶことを考えています(LinuxコミュニティまたはMySQLコミュニティは別の質問です:MySQL 5.6はまだ見ていません:おそらくこのバグはありません)
(少し試してみます:今夜、githubで最初に承認されたプルリクエストを既に受け取りました。)追記
上記はもともとMySQLバージョン5.1に適用されました(はい、残念ながら、これまでのところMySQL 5.1を使用したプラットフォームでの作業は避けられない条件です)が、MySQL 5.5.35を使用してタイプライターで同じことを試しました(リリースをテストしています)公式Debianリポジトリ)と同じすべての落胆的な結果を見た。