2017-02-19 14 views
0

私は以下の問題があります: すべての作者には、この名前のnエイリアスがあります。すべてのエイリアスはソースからのものです。各エイリアスにはm個のソースがあります。例MySQL ON DUPLICATEを別のテーブルに挿入する

AUTHOR| ALIAS | SOURCE 
------------------------- 
Will| Willy |George 
Will| Bill | Jenny 
William| Will| Francis 
William| Bill| Maya 

のために私は著者と彼の名前、彼の別名のすべてのための1つに1つのテーブルがあります。

CREATE TABLE alias (
    authors_id INT NOT NULL, 
    alias VARCHAR(150) NOT NULL, 
    id INT NOT NULL AUTO_INCREMENT 
    PRIMARY KEY (author_id,alias); 

をidが外部キーとして機能します。ここで はソース

CREATE TABLE alias_source (
    id INT NOT NULL AUTO_INCREMENT 
    source VARCHAR(150) NOT NULL, 
    alias_id INT NOT NULL, 
    PRIMARY KEY (id) 
    FOREIGN KEY (alias_id) REFERENCES alias(id); 

ための第二のテーブルだ今、私は 著者、別名、ソースがalias_sourceに挿入されていることを別名にソースを挿入したときのための文を挿入してMySQLを必要とします。 重複別名では、新しいソースのみが追加されます。

答えて

0

SQLのINSERT文は、1つの表にのみ挿入でき、その1つの表の列のみをリストできます。 source列は、alias表の列ではないため、INSERT文に含めることはできません。

トリガーを使用すると、セカンダリテーブルに挿入することができますが、トリガーは挿入する値を知る必要があります。この場合、トリガーにはsourceの値を取得する方法がありません。

これは、2つのINSERT文ではるかに簡単な作業です。

INSERT IGNORE INTO alias SET author_id = ?, alias = ?; 
INSERT INTO alias_source ... 

しかし、あなたのalias表が自動インクリメント列idを持っているので、あなたが問題を持っていますが、この列がキーの一部ではありません。 InnoDBでは、自動増分カラムをキーの最初のカラムにする必要があります。

alias_sourceテーブルには、alias(id)を参照する外部キーがありますが、これは許可されていません。外部キーは、親テーブルのキーを参照する必要があります。一意キーまたは主キーを参照し、キーのすべての列を参照する必要があります(そうでなければ、親テーブル内の複数の行を参照する可能性のある子テーブル内の行が得られ、意味をなさない)。

aliasテーブルに自動インクリメント列を使用する場合は、プライマリキーにして、他の列に2次UNIQUE制約を設定します。

CREATE TABLE alias (
    id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    authors_id INT NOT NULL, 
    alias VARCHAR(150) NOT NULL, 
    UNIQUE KEY (author_id,alias)); 

次に、挿入後にidを照会してください。新しい行を挿入した場合でも行が既に存在していても、選択した著者とエイリアスを持つ行にはidが表示されます。あなたのコメントでフォローアップの質問を再

INSERT IGNORE INTO alias SET author_id = ?, alias = ?; 
SELECT id FROM alias WHERE author_id = ? AND alias = ? INTO @id; 
INSERT INTO alias_source SET alias_id = @id, source = ?; 

良いアイデアが、それはあなたがそれがないと思うかもしれように動作しません。 id=idのダミーセットを実行し、セッション変数を副作用として設定することができます。

mysql> insert into alias set author_id=1, alias='alias' 
    on duplicate key update id = @id:=id; 

mysql> select @id; 
+------+ 
| @id | 
+------+ 
| NULL | 
+------+ 

なぜ、セッション変数をIDに設定しなかったのですか?この挿入物はではなく、で重複していたため、新しい行でした。したがって、idの値は、IODKUが実行された時点で自動インクリメントによってまだ生成されていませんでした。

あなたはその後重複していることを行に対して同じIODKUを行う場合は、副作用の値を取得するので、id値は以前、行に追加されました:

mysql> insert into alias set author_id=1, alias='alias' 
    on duplicate key update id = @id:=id; 

mysql> select @id; 
+------+ 
| @id | 
+------+ 
| 1 | 
+------+ 

とにかく@idがNULLかどうかを確認するにはアプリケーションコードを書かなければならず、@idがNULLの場合はSELECT idというクエリを実行する必要があります。

これは、上記のようにINSERT IGNOREの後に標準アクションとしてSELECT idを実行するだけでは複雑に思えます。

+0

回答ありがとう@ bill!しかし、ON DUPLICATE KEYを使用して重複IDを@idに格納することは可能ですか? 2番目のステートメントをスキップするには? –

関連する問題