2017-02-19 7 views
1

Table with multiple incrementing columns which doesn't reuse deleted column valuesを実装しようとしています。この投稿にはすでにHow auto-increment within a subset of the table MYSQLが返信されているとタグ付けされていましたが、参照された投稿はサブセットの増分キーを複製できるため、記載された要件を満たしませんでした。最初の記事では、コメントが与えられました。同じテーブルでUPDATEとSELECTをトリガして、エラー1235(42000)

Create a table that will store last AI numbers per type. Use a trigger to increment it on every insert and copy to the original table. – Paul Spiegel

私は、これは素晴らしいアイデアだと思ったし、それを実装しました。

-- MySQL Script generated by MySQL Workbench 
-- 02/19/17 08:53:34 
-- Model: New Model Version: 1.0 
SET @[email protected]@UNIQUE_CHECKS, UNIQUE_CHECKS=0; 
SET @[email protected]@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0; 
SET @[email protected]@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES'; 

-- ----------------------------------------------------- 
-- Schema mydb 
-- ----------------------------------------------------- 
CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ; 
USE `mydb` ; 

-- ----------------------------------------------------- 
-- Table `mydb`.`t1` 
-- ----------------------------------------------------- 
CREATE TABLE IF NOT EXISTS `mydb`.`t1` (
    `pk1` INT NOT NULL, 
    `pk2` INT NOT NULL, 
    `id2` INT NOT NULL DEFAULT 0, 
    PRIMARY KEY (`pk1`, `pk2`)) 
ENGINE = InnoDB; 


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


SET [email protected]_SQL_MODE; 
SET [email protected]_FOREIGN_KEY_CHECKS; 
SET [email protected]_UNIQUE_CHECKS; 
USE `mydb`; 

DELIMITER $$ 
USE `mydb`$$ 
CREATE TRIGGER `t2_BINS` BEFORE INSERT ON `t2` FOR EACH ROW 
begin 
UPDATE t1 SET id2=id2+1 WHERE pk1=NEW.pk1 AND pk2=NEW.pk2; 
SET NEW.id2=(SELECT id2 FROM t1 WHERE pk1=NEW.pk1 AND pk2=NEW.pk2); 
end$$ 


DELIMITER ; 

スクリプトを実行して、しかし、私は次のエラーが表示されます

ERROR 1235 (42000) at line 68: This version of MySQL doesn't yet support 'multiple triggers with the same action time and event for one table' 

私は、MySQL 5.5.54を使用しています。そうすることができる新しいバージョンがありますか?

これを行うための回避策はありますか?

答えて

1

おそらく、1つのテーブルに2つのBEFORE INSERTトリガーが定義されています。少なくとも、それはエラーメッセージの内容です。 this demoに第2のトリガのコメントを解除し、あなたは、第二の間違いは間違った表にトリガーが定義されていることである同じエラーメッセージ

This version of MySQL doesn't yet support 'multiple triggers 
with the same action time and event for one table' 

を取得します(または、あなたが引き金にテーブルを混同しています)。あなたのトリガーはt2ですが、t1NEW.pk1)の列にアクセスしようとしています。だから、次のエラーメッセージになるだろう:

Unknown column 'pk1' in 'NEW' 

http://sqlfiddle.com/#!9/1515abb(。コメントを解除し、トリガ内の行)

をしかし - でも、ロジックが正しく見えない、という固定。あなたが意図しているかもしれないものの作業バージョンは次のようになります。

CREATE TABLE IF NOT EXISTS `t1` (
    `pk1` INT NOT NULL, 
    `pk2` INT NOT NULL DEFAULT 0, 
    PRIMARY KEY (`pk1`, `pk2`)) 
ENGINE = InnoDB; 

CREATE TABLE IF NOT EXISTS `t2` (
    `pk1` INT NOT NULL, 
    `last_pk2` INT NOT NULL, 
    PRIMARY KEY (`pk1`)) 
ENGINE = InnoDB; 

DELIMITER // 

CREATE TRIGGER `t1_BINS` BEFORE INSERT ON `t1` FOR EACH ROW 
begin 
    UPDATE t2 SET last_pk2=last_pk2 + 1 WHERE pk1=NEW.pk1; 
    SET NEW.pk2=(SELECT last_pk2 FROM t2 WHERE pk1=NEW.pk1); 
end// 

DELIMITER ; 

あなたがdemoで見ることができるように、2番目の挿入はpk2を指定しませんが、それは結果に増加しています。

t2に登録されていないpk1の値を挿入すると、これは失敗します。 (demoの最後の行のコメントを外します)この場合、新しい行をt2に挿入する必要があります。

CREATE TRIGGER `t1_BINS` BEFORE INSERT ON `t1` FOR EACH ROW 
begin 
    INSERT INTO t2 (pk1, last_pk2) values (NEW.pk1, 1) 
    ON DUPLICATE KEY UPDATE last_pk2 = last_pk2 + 1; 
    SET NEW.pk2=(SELECT last_pk2 FROM t2 WHERE pk1=NEW.pk1); 
end// 

http://sqlfiddle.com/#!9/79eeea/1

今、最後のステップは、それは同時実行を保存することです:pk1ので、私たちはINSERT .. ON DUPLICATE KEY UPDATE ..構文を使用することができますt2でPRIMARY KEYです。 2つの同時スレッド/セッションがt2.last_pk2の同じ値を読み取るのを防ぐ必要があります。したがって、書き込みと読み取りは1つのステートメントで行う必要があります。我々はそれを行うために、セッション変数またはLAST_INSERT_ID()を使用することができます。

CREATE TRIGGER `t1_BINS` BEFORE INSERT ON `t1` FOR EACH ROW 
begin 
    INSERT INTO t2 (pk1, last_pk2) values (NEW.pk1, @last_pk2 := 1) 
    ON DUPLICATE KEY UPDATE last_pk2 = @last_pk2 := (last_pk2 + 1); 
    SET NEW.pk2 = @last_pk2; 
end// 

http://sqlfiddle.com/#!9/dc235a/1

CREATE TRIGGER `t1_BINS` BEFORE INSERT ON `t1` FOR EACH ROW 
begin 
    INSERT INTO t2 (pk1, last_pk2) values (NEW.pk1, LAST_INSERT_ID(1)) 
    ON DUPLICATE KEY UPDATE last_pk2 = LAST_INSERT_ID(last_pk2 + 1); 
    SET NEW.pk2 = LAST_INSERT_ID(); 
end// 

http://sqlfiddle.com/#!9/86ed740/1

関連する問題