1

編集-以下の回答に基づいて、デザインを再検討します。ビジネスオブジェクトとルールの設定方法をもう少し賢くすることで、この混乱を回避できると思います。皆さんの助けに感謝します!

-

私は次のモデルを持っています:

SはTに属します

TにはSがたくさんあります

A、B、C、D、E(etc)にはそれぞれ1つのTがあるため、TはA、B、C、D、E(etc)のそれぞれに属する必要があります。

最初に、Aではfk_a_tがAt to T(id)の外部キー、Bではfk_b_tなどになるように外部キーを設定しました。UMLではすべてが正常に見えますが(MySQLWorkBenchを使用)、 yiiモデルでは、Tには多くのA、B、C、D(など)があると考えられますが、これは私にとっては逆です。

A_T、B_T、C_T(など)のテーブルが必要なように思えますが、この関係にあるテーブルがたくさんあるので、これは面倒です。また、これを行うためのより良い方法は、A、B、C、D(など)がTとして動作できるような、ある種の動作であるとグーグルで調べましたが、これを行う方法が正確にはわかりません(私はこれについてもっとグーグルし続けます)

編集-明確にするために、TはA、B、またはC(など)の1つにのみ属することができ、2つのA、またはAとBには属せません(つまり、多対多ではありません)。私の質問は、Yiiフレームワークモデルでこの関係をどのように説明するかに関するものです。たとえば、(A、B、C、D、...)HAS_ONE Tであり、Tは(A、B、C、D、..に属します。 。)。ビジネスのユースケースからすると、これはすべて理にかなっていますが、データベースに正しく設定されているかどうか、または設定されている場合は、関係を理解するためにYiiの「動作」を使用する必要があるかどうかはわかりません。 。@rwmnau私はあなたが何を意味するのか理解しています、私の説明が役立つことを願っています。

UML: UML図

これがDDL(自動生成)です。Tを参照するテーブルが3つ以上あると仮定してください。

-- -----------------------------------------------------
-- Table `mydb`.`T`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `mydb`.`T` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `mydb`.`S`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `mydb`.`S` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `thing` VARCHAR(45) NULL ,
  `t` INT NOT NULL ,
  PRIMARY KEY (`id`) ,
  INDEX `fk_S_T` (`id` ASC) ,
  CONSTRAINT `fk_S_T`
    FOREIGN KEY (`id` )
    REFERENCES `mydb`.`T` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `mydb`.`A`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `mydb`.`A` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `T` INT NOT NULL ,
  `stuff` VARCHAR(45) NULL ,
  `bar` VARCHAR(45) NULL ,
  `foo` VARCHAR(45) NULL ,
  PRIMARY KEY (`id`) ,
  INDEX `fk_A_T` (`T` ASC) ,
  CONSTRAINT `fk_A_T`
    FOREIGN KEY (`T` )
    REFERENCES `mydb`.`T` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `mydb`.`B`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `mydb`.`B` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `T` INT NOT NULL ,
  `stuff2` VARCHAR(45) NULL ,
  `foobar` VARCHAR(45) NULL ,
  `other` VARCHAR(45) NULL ,
  PRIMARY KEY (`id`) ,
  INDEX `fk_A_T` (`T` ASC) ,
  CONSTRAINT `fk_A_T`
    FOREIGN KEY (`T` )
    REFERENCES `mydb`.`T` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `mydb`.`C`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `mydb`.`C` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `T` INT NOT NULL ,
  `stuff3` VARCHAR(45) NULL ,
  `foobar2` VARCHAR(45) NULL ,
  `other4` VARCHAR(45) NULL ,
  PRIMARY KEY (`id`) ,
  INDEX `fk_A_T` (`T` ASC) ,
  CONSTRAINT `fk_A_T`
    FOREIGN KEY (`T` )
    REFERENCES `mydb`.`T` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;
4

4 に答える 4

1

問題の一部は、どのテーブルに関連しているかを区別する方法がないことです。

さらに、他の 3 つまたは 4 つのテーブルのいずれかに一致するレコードが 1 つしかない場合、これは通常の関係ではなく、通常の手法を使用してモデル化することはできません。トリガーはこれが真であることを確認できますが、id の列のみが含まれているため、10 のテーブル A の id と 10 のテーブル C の ID を一致させることができません (ルールに違反しています)。

ところで、列 ID に名前を付けるのは、通常、メンテナンスには適していません。PK のテーブル名で列に名前を付け、FK の Pk の正確な名前を使用すると、何が起こっているのかがより明確になります。

別の解決策は、中央のテーブルに ID の各タイプの列と、そのうちの 1 つだけが値を持つようにするためのトリガーを用意することですが、すべての ID が必要な場合にクエリを実行するのは面倒です。id と idtype の複合 PK は、タイプ内で繰り返しがないように機能しますが、繰り返しがまったくないようにするには、トリガーが必要です。

于 2010-05-07T19:41:44.723 に答える
1

This is a dilemma that comes up fairly regularly, and there is no perfect solution IMHO.

However I would recommend the following:

Combine the S and T table. I don't see any real need for the T table.

Invert the way the A/B/C tables relate to the S (formerly T) table. By this I mean remove the FK on the A/B/C side and create nullable FK columns on the S side. So now your S table has three additional nullable columns: A_ID, B_ID, C_ID.

Create a check constraint on the S table, ensuring that exactly one of these columns always has a value (or none of them has a value if that is allowed).

If having exactly one value is the rule, you can also create a unique constraint across these three columns to ensure that only one S can be related to an A/B/C.

If no value in any of these columns is allowed, the above rule will have to be enforced with a check constraint as well.

Update After Your Comment

Ok, then I would forget about inverting the relationships, and keep the FK on the A/B/C side. I would still enforce the uniqueness of usage using a check constraint, but it would need to cross tables and will likely look different for each flavor of SQL (e.g. SQL Server requires a UDF to go across tables in a check constraint). I still think you can nuke the T table.

Regarding the ORM side of things, I don't know yii at all, so can't speak to that. But if you enforce the relationship at the database level, how you implement it via code shouldn't matter, as the database is responsible for the integrity of the data (they will just look like vanilla relationships to the ORM). However, it may present a problem with trapping the specific error that comes up if at runtime the check constraint's rule is violated.

I should also mention that if there is a large (or even reasonably large) amount of data going into the tables in question, the approach I am recommending might not be the best, as your check constraint will have to check all 20 tables to enforce the rule.

于 2010-05-07T20:08:00.153 に答える
0

私は数週間前に同様の状況に直面しなければなりません(私自身のデータベースではありません。非常に特殊な状況でない限り、すべてのテーブルを1つに結合することを好みます)。
私が実装した解決策は次のとおりです。「T」モデルファイルで、関係()関数で次のようなことを行いました:

'id_1' => array(self::BELONGS_TO, 'A', 'id'),
'id_2' => array(self::BELONGS_TO, 'B', 'id'),
'id_3' => array(self::BELONGS_TO, 'C', 'id'),

これがお役に立てば幸いです。
よろしく。

于 2010-05-12T20:23:47.120 に答える
0

多対多の関係の場合は真ん中にテーブルが必要なだけで、そうではないように聞こえるので、心配する必要はありません。

あなたの質問は明確ではありません.Tは1つ以上のA、1つ以上のBなどに属することができますか? それとも、単一の T は各 AE に属し、他には属さないのでしょうか? これは、1 対 1 の関係 (各 T に正確に 1 つの AE がある) と 1 対多の関係 (各 AE に正確に 1 つの T があるが、T は多くの A、多くの B、および複数に属することができる) の違いです。すぐ)。これは理にかなっていますか?

また、あなたが求めているものを固めるのに役立つように、あなたの質問にいくつかの情報を追加してください.

于 2010-05-07T18:53:37.080 に答える