2011-06-30 22 views
3

最初 - 私はここ数日、これについての答えを運のない状態で探してきました。意味私は答えを見て、それらを試して、まだエラーを取得します。私は、コードを見ると私が気分が悪くなるという点に迫っています。だから、どんな助けでも大歓迎です。MySQL - 更新カスケード(複数のテーブル)

私は3つのテーブルCLIENT、PROJECTS、PROJECT_NOTESを持っています。プロジェクトは1つのクライアントにのみ割り当てることができますが、クライアントは複数のプロジェクトを持つことができます。プロジェクトは複数の音符を持つことができますが、その音符は1つのプロジェクトにのみ割り当てることができます。

私が探しているのは、私がクライアントを「ゴミ箱」にして、そのクライアントに関連付けられているすべてのプロジェクトが「ゴミ箱」になってしまうことです。その後、ゴミ箱に入れられたプロジェクトのプロジェクトメモもすべて「ゴミ箱」になります。

私はまた、プロジェクトを「ゴミ箱」にして、関連するすべてのプロジェクトノートを「ごみ箱」にすることもできます。

私は外部キーを使用し、更新カスケードを使用する必要があると想定しています。私は私の主キーが設定されている方法で何かをねじっていると思う - しかし、これは私に間違っているかもしれないので私には新しいものです。

問題なくテーブルを作成できます。私は問題なく、すべてのテーブルにデータを挿入できます。ただし、CLIENTまたはPROJECTSテーブルのいずれかで更新クエリを実行すると、CLIENT以外のテーブルにデータを挿入できなくなります。ここで

は、テーブルを作成するために使用されるコードです:

CREATE TABLE clients (
    clientID INT UNSIGNED NOT NULL AUTO_INCREMENT, 
    companyName VARCHAR(128), 
    clientTrash TINYINT(1) UNSIGNED NOT NULL DEFAULT '0', 
    PRIMARY KEY (clientID, clientTrash), 
    INDEX (companyName) 
)ENGINE=INNODB; 


CREATE TABLE projects (
    projectID INT UNSIGNED NOT NULL AUTO_INCREMENT, 
    clientID INT UNSIGNED NOT NULL, 
    projectTitle VARCHAR(128), 
    projectTrash TINYINT(1) UNSIGNED NOT NULL DEFAULT '0', 
    PRIMARY KEY (projectID, projectTrash), 
    INDEX (projectTitle), 
    FOREIGN KEY (clientID, projectTrash) REFERENCES clients (clientID, clientTrash) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE 
)ENGINE=INNODB; 


CREATE TABLE project_notes (
    projectNoteID INT UNSIGNED NOT NULL AUTO_INCREMENT, 
    projectID INT UNSIGNED NOT NULL, 
    note TEXT, 
    projectNoteTrash TINYINT(1) UNSIGNED NOT NULL DEFAULT '0', 
    PRIMARY KEY (projectNoteID, projectNoteTrash), 
    FOREIGN KEY (projectID, projectNoteTrash) REFERENCES projects (projectID, projectTrash) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE 
)ENGINE=INNODB; 

(うまくいけば、そのコードが正しくフォーマットされた - それはここに掲示する私の最初の時間です)。

オンデマンドカスケードを使用するよりも(より簡単な)方法がある場合はお知らせください。また、何かすべての助けに感謝します。

追加する忘れた場合:CLIENTテーブルでclientTrash = 1を設定するための更新クエリを実行した後。 は、子行を追加または更新できません:。私はプロジェクトに値を挿入すると、エラー#1452で終わるようにするよ外部キー制約が失敗する(_clientmanageprojects、CONSTRAINT projects_ibfk_1 FOREIGN KEY(clientIDprojectTrash)は、clientIDclientsを参照しますclientTrash

+0

「コードを見れば何度も病気になっています。 –

+0

それは機能しましたか?これがあなたが必要とするものなら、私は興味があります。 (ああ、upvoteにも気をつけません;)) – Inca

答えて

1

あなたの鍵をid + trashとして設定すると、id + trashでid + not_trashedのアイテムを2つ持つことができます。

プライマリ/外部キーからゴミ箱を取り除くと、編集の問題が解決するはずです。

私は(このビットについて間違っている可能性があります)何が起こっているかは、何かがゴミ箱になったときに、主キーが変わって外来キーの関係が壊れることです。 012(ID:4はゴミ箱:0)はB(ID:17、ゴミ箱:0、外国人(ID:4:ゴミ箱:0))に接続されています。
Aが「ゴミ箱」になっているときに主キーが現在(ID:4ゴミ箱:1)です。
Bはまだ(id:17、trashed:0、foreign(id:4:trashed:0))です。
Bの外部(id:4:trashed:0)は存在しなくなりました(または存在しなくなりました)。

これを行うもう1つの方法は、ストアドプロシージャまたはトランザクションを、一連の小さな手順で実行する実装で設定することです。

+0

実際、更新はここでうまくいっています。すべてのごみは1に設定されており、制約が働きます。データを挿入することもできます。ただし、正しく設定されたデータである必要があります。そのため、クライアントがゴミ箱になっている場合は、ごみ箱のプロジェクトとゴミ箱を作成することしかできません。ゴミ箱のデフォルト値は0なので、これは簡単に忘れるかもしれません。 – Inca

+0

Ok。あなたはそれがかなり長いことを明確にしたいかもしれません。それはあなたが修正しようとしていることについて混乱しています。 – evan

+0

申し訳ありませんが、私は質問を短くしようとしましたが、そうする際に重要な情報がなくなり、混乱しました。 @インカはそれを理解しているように見えて、試してみるための解決策を投げたので、私はそこから始めます。それ以外の場合は、私は追加のヘルプが必要な場合は、質問を短縮しようとします。私のコードで何が起こっているのかを明確にしてくれてありがとう。非常に感謝しています。 – MySQLHatesMe

1

"trash = 1"の設定を下にカスケードするトリガーを使用して、これがあなたの望むものだと思います。クライアントがゴミ箱に移動された場合、プロジェクトとメモも移動します。ただし、ゴミ箱からクライアントを復活させると、メモは自動的には復元されず、クライアントがいないときにプロジェクトをtrahsに移動することができます。

(これは更新を処理するだけですが、ごみ箱に入れられていないプロジェクトを挿入しないようにする必要がありますが、それでもまだ苦労しています。

DELIMITER // 
CREATE TRIGGER trgClientToTrash 
    AFTER UPDATE ON clients 
    FOR EACH ROW 
    BEGIN 
     IF NEW.clientTrash = 1 THEN 
      UPDATE projects SET projects.projectTrash = NEW.clientTrash 
          WHERE projects.clientID = NEW.clientID; 
     END IF; 
    END; 
// 

編集

追加する:挿入トリガー

delimiter // 

create trigger insProjectTrash 
    before insert on projects 
    for each row 
    begin 
     declare trash numeric; 
     select greatest(clientTrash, new.projectTrash) into trash 
       from clients where clientID = new.clientID; 
     set new.projectTrash = trash; 
    end; 
// 

これは、プロジェクトのメモを挿入し、類似しているはずのプロジェクトを更新するに変換し、プロジェクトを挿入し、クライアントの更新を処理します。

+0

私はトリガーがこれに行く方法かもしれないと思ったが、100%確実ではなかった。そのルートに行く前に、私が始めたアプローチが修正されているかどうかを確かめました。ありがとうございました@inca - 私は時間があるときにメソッドを試してみましょう。 – MySQLHatesMe

3

参照整合性(外部キー、カスケード更新、カスケード削除)の使用と適用について混乱していると思います。カスケードの更新と削除は、関連するテーブルの参照整合性を維持する方法であるため、親/主の主キーの変更は従属/子の行までカスケードされ、親IDが変更されても関係は壊れません。ところで、参照整合性は、MySQLでInnoDBエンジンを使用する場合にのみ適用されます。

あなたが本当に望むのは、エンティティの状態を従属エンティティにカスケードするビジネスルールを実施する方法です。データベースレベルで使用するツールは、行が挿入、更新、または削除されるたびに実行される特別な種類のストアドルーチンであるトリガーです。 clientsprojectsテーブルにAFTER UPDATEトリガーを設定して、ゴミ箱ステータスをカスケードすることができます。

デザインとアーキテクチャの観点からは、この種の動作は通常、データベースレベルではなくビジネスロジックコードで処理されます。

+0

私はこれがまさにON DELETEという外部キーのためだと思っていました。親がなくても "子"のレコードが残っていないことを永久に無駄に消費していました。 – Hubro

+0

@Codemonkeyあなたは 'ON DELETE'について正しいですが、OPの質問は、フィールドの変更をカスケードすることです。実際には親の行を削除するのではありません。 – Xint0

関連する問題