29

シナリオ:

2 つの外部キーを参照するテーブルがあり、これらの外部キーの一意の組み合わせごとに、独自の auto_increment 列があります。これら 3 つの組み合わせを使用して行を一意として識別するのに役立つ複合キーを実装する必要があります (1 つの外部キーと 1 つの auto_increment 列、および一意でない値を持つもう 1 つの列)。

テーブル:

CREATE  TABLE `issue_log` (
`sr_no` INT NOT NULL AUTO_INCREMENT ,
  `app_id` INT NOT NULL ,
  `test_id` INT NOT NULL ,
  `issue_name` VARCHAR(255) NOT NULL ,
primary key (app_id, test_id,sr_no)
);

もちろん、私のクエリには何か問題があるはずです。そのため、スローされるエラーは次のとおりです。

エラー 1075: テーブル定義が正しくありません。自動列は 1 つしか存在できず、キーとして定義する必要があります

私が達成しようとしていること:

アプリケーション テーブル (主キーとして app_id を持つ) があり、各アプリケーションには解決すべき問題のセットがあり、各アプリケーションには複数のテストがあります (つまり、test_id 列)。

つまり、テーブル内のデータは次のようになります。

ここに画像の説明を入力

データベース エンジンは InnoDB です。私はこれをできるだけ簡単に達成したいと考えています(つまり、可能であればトリガー/手順を避けます-これは他の質問の同様のケースで提案されました)。

4

6 に答える 6

35

MySQL で InnoDB テーブルに対して自動的にこれを行うことはできません。トリガーまたはプロシージャを使用するか、MyISAM などの別の DB エンジンを使用する必要があります。自動インクリメントは、単一の主キーに対してのみ実行できます。

次のようなものが機能するはずです

DELIMITER $$

CREATE TRIGGER xxx BEFORE INSERT ON issue_log
FOR EACH ROW BEGIN
    SET NEW.sr_no = (
       SELECT IFNULL(MAX(sr_no), 0) + 1
       FROM issue_log
       WHERE app_id  = NEW.app_id
         AND test_id = NEW.test_id
    );
END $$

DELIMITER ;
于 2013-08-08T07:21:17.843 に答える
5

列のインクリメント要件を完全には理解していませんが、( , )test_idの一意の組み合わせごとに再開する ~autoincrement シーケンスが必要な場合は、同じテーブルに対して INSERT ... SELECT FROM を次のように実行できます。app_idtest_id

mysql> INSERT INTO `issue_log` (`sr_no`, `app_id`, `test_id`, `issue_name`) SELECT
           IFNULL(MAX(`sr_no`), 0) + 1 /* next sequence number */,
           3 /* desired app_id */,
           1 /* desired test_id */,
           'Name of new row'
           FROM `issue_log` /* specify the table name as well */
       WHERE `app_id` = 3 AND `test_id` = 1 /* same values as in inserted columns */

これは、AUTO_INCREMENT 列が宣言されていないテーブル定義を想定しています。基本的に IFNULL(MAX()) + 1 句を使用して自動インクリメントの動作をエミュレートしていますが、組み込みの自動インクリメントとは異なり、手動エミュレーションは任意の列で機能します。

INSERT ... SELECT は単一のクエリであるため、操作の原子性が保証されることに注意してください。InnoDB は適切なインデックスをギャップロックし、競合しないシーケンスを生成しながら、多くの同時プロセスがこの種のクエリを実行できます。

于 2015-02-18T12:16:45.203 に答える