1

行がテーブルAに挿入された後、その行から他のテーブルBにいくつかの値を挿入するトリガーが必要ですが、テーブルBにそのような値の組み合わせを持つ行がまだ含まれていない場合に限ります。これが私が思いついたものです:

CREATE TRIGGER upd_manufactorer_in_category AFTER INSERT ON product
FOR EACH ROW 
BEGIN
  DECLARE id_category INT; 
  DECLARE id_manufacturer INT;
  DECLARE id_category_test INT; 

  SET id_category=NEW.id_category;
  SET id_manufacturer=NEW.id_manufacturer;

  SET id_category_test=(SELECT 'id_category'
                FROM category_has_manufacturer
                WHERE 'id_category'=id_category
                AND 'id_manufacturer'=id_manufacturer);

  IF id_category_test IS NULL
  THEN
    INSERT INTO category_has_manufacturer
    SET category_has_manufacturer.id_category = id_category, 
    category_has_manufacturer.id_manufacturer = id_manufacturer;
  END IF;
END

そしてそれは機能し、テーブルに行を挿入します。しかし、それが以前に存在したかどうかはチェックされないので、私は多くの重複を持っています。もちろん、DISTICTでこれを照会することはできますが、これは私がここで達成したいことではありません。一意の(id_category、id_manufacturer)ペアのみを持つテーブルが必要です。誰か助けてもらえますか?

4

1 に答える 1

1

両方を実行できる2つのことが役立ちます。

Devartが提案したように、最初に一意のインデックス/キーをテーブルに追加します。

2つ目は、これは、右結合と左結合を使用して、存在しないデータを取得できる優れた場所であるということです。私はあなたに理論を示すつもりです、そしてあなたはそれを練習としてあなたの答えに適用することができます。

ステップ1:

testというデータベースを作成します。

ステップ2:

新しく作成されたテストデータベースで、次の2つのテーブル作成スクリプトを実行します。

CREATE  TABLE `test`.`category_has_manufacturer_A` 
(
      `id_category` INT NOT NULL ,
      `id_manufacturer` INT NOT NULL ,
       PRIMARY KEY (
                     `id_category`, 
                     `id_manufacturer`
                   ) 
);

CREATE  TABLE `test`.`category_has_manufacturer_B` 
(
      `id_category` INT NOT NULL ,
      `id_manufacturer` INT NOT NULL ,
       PRIMARY KEY (
                     `id_category`, 
                     `id_manufacturer`
                   ) 
);

そのため、結合できる共通の列を持つ2つのテーブルがあります。

ステップ3

category_has_manufacturer_aテーブルにデータを追加します

INSERT INTO `test`.`category_has_manufacturer_a`
(
  `id_category`,
  `id_manufacturer`
)
VALUES
(
    1,
    1
);

かっこいいので、テーブルAには、テーブルBに追加したいデータがいくつかあります。

ステップ4:

2つのテーブルで内部結合を実行し、次のクエリを実行して結果を確認しましょう。

SELECT
   A.`id_category` AS A_ID_CATEGORY,
   A.`id_manufacturer` AS A_ID_MANAFACTURER,
   B.`id_category` AS B_ID_CATEGORY,
   B.`id_manufacturer` AS B_ID_MANAFACTURER
FROM category_has_manufacturer_a A  
INNER JOIN  category_has_manufacturer_b B
     ON A.`id_category` =B.`id_category`
     AND A.`id_manufacturer`=B.`id_manufacturer`

表A表Bの行が直接一致しなかったため、データは返されませんでした。これは、内部結合がJOIN条件に一致する行のみを返すためです。

ステップ5:

OUTERJOINSのパワーが明らかになりました。OUTER結合は、一致しない場合でもデータを返します。この場合、テーブルAテーブルBでLEFTOUTERJOINを実行します。表A左側のテーブルであるため、表Bのいずれとも一致しない場合でも、表Aからすべてのデータを返すように求めています。次のクエリを実行します。

SELECT
   A.`id_category` AS A_ID_CATEGORY,
   A.`id_manufacturer` AS A_ID_MANAFACTURER,
   B.`id_category` AS B_ID_CATEGORY,
   B.`id_manufacturer` AS B_ID_MANAFACTURER
FROM category_has_manufacturer_a A  
LEFT OUTER JOIN  category_has_manufacturer_b B
     ON A.`id_category` =B.`id_category`
     AND A.`id_manufacturer`=B.`id_manufacturer`

これにより、次のようなレコードセットが返されます。

A_ID_CATEGORY|A_ID_MANAFACTURER|B_ID_CATEGORY|B_ID_MANAFACTURER|
            1|                1|             |                 |

この結果は、テーブルAにテーブルBの行と一致しない行があることを明確に示しています。

ステップ6:

これで、ステップ5のSELECTステートメントを使用してINSERTステートメントを作成し、存在しないこれらの行を挿入できます。次のクエリを実行します。

 INSERT INTO category_has_manufacturer_b
 SELECT
   A.`id_category` AS A_ID_CATEGORY,
   A.`id_manufacturer` AS A_ID_MANAFACTURER

 FROM category_has_manufacturer_a A  
 LEFT OUTER JOIN  category_has_manufacturer_b B
     ON A.`id_category` =B.`id_category`
     AND A.`id_manufacturer`=B.`id_manufacturer`

挿入が次のクエリを実行したことを確認しましょう。

SELECT
 `category_has_manufacturer_b`.`id_category`,
 `category_has_manufacturer_b`.`id_manufacturer`
FROM `test`.`category_has_manufacturer_b`;

テーブルAの行がテーブルBに挿入された結果セットが表示されます。

ステップ7:

ここでは、テーブルAからテーブルBに新しい行のみを追加することを確認する最後の部分を追加します。まず、さらにデータを追加しましょう。次のクエリを実行します。

INSERT INTO `test`.`category_has_manufacturer_a`
(
   `id_category`,
   `id_manufacturer`
)
VALUES
(
    1,

    2
);

次に、左結合を使用してクエリを再度実行します。

SELECT
   A.`id_category` AS A_ID_CATEGORY,
   A.`id_manufacturer` AS A_ID_MANAFACTURER,
   B.`id_category` AS B_ID_CATEGORY,
   B.`id_manufacturer` AS B_ID_MANAFACTURER
FROM category_has_manufacturer_a A  
LEFT OUTER JOIN  category_has_manufacturer_b B
     ON A.`id_category` =B.`id_category`
     AND A.`id_manufacturer`=B.`id_manufacturer`

両方のテーブルで一致する行と、テーブルのみの新しい行を含む結果セットが表示されます。ここで挿入を実行すると、両方の行が挿入され、主キー違反が発生するか、場合によっては行が重複します。

上記のクエリを次のように変更して実行すると、次のようになります。

 SELECT
   A.`id_category` AS A_ID_CATEGORY,
   A.`id_manufacturer` AS A_ID_MANAFACTURER,
   B.`id_category` AS B_ID_CATEGORY,
   B.`id_manufacturer` AS B_ID_MANAFACTURER
FROM category_has_manufacturer_a A  
LEFT OUTER JOIN  category_has_manufacturer_b B
     ON A.`id_category` =B.`id_category`
     AND A.`id_manufacturer`=B.`id_manufacturer`
WHERE B.`id_category` IS NULL AND  B.`id_manufacturer` IS NULL

レコードセットには、表Aの新しいレコードのみが含まれます。

挿入ステートメントを次のように変更します。

INSERT INTO category_has_manufacturer_b
SELECT
   A.`id_category` AS A_ID_CATEGORY,
   A.`id_manufacturer` AS A_ID_MANAFACTURER,
   B.`id_category` AS B_ID_CATEGORY,
   B.`id_manufacturer` AS B_ID_MANAFACTURER
FROM category_has_manufacturer_a A  
LEFT OUTER JOIN  category_has_manufacturer_b B
     ON A.`id_category` =B.`id_category`
     AND A.`id_manufacturer`=B.`id_manufacturer`
WHERE B.`id_category` IS NULL AND  B.`id_manufacturer` IS NULL

このINSERTを実行すると、テーブルAからテーブルBに新しい行のみが挿入されます。

概要:LEFTおよびRIGHT JOINステートメントを使用して、2つのテーブルを比較し、1つから新しい行のみを返すことができます。これは、行が新しい場合に1つのテーブルから別のテーブルに追加しようとするときに優れた手法です。1行と複数行で同時に動作し、セットベースであるため(SQLはこれに優れています)、超高速です。

何が起こっているのかを理解し、これをトリガーに適用できることを願っています。

ヒント: トリガーでは、NEWテーブルにアクセスでき、これに参加して新しい行を決定できます。

楽しむ!

于 2012-12-14T08:30:34.630 に答える