シナリオ:
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 col)があります。sr_nocolは、一意のapp_idおよびtest_idに対して増加する必要があります。
つまり、表のデータは次のようになります。
データベースエンジンはInnoDBです。私はこれをできるだけ簡単に実現したいと考えています(つまり、可能であればトリガー/手順を避けます-これは他の質問の類似のケースで提案されました)。
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 ;
これは、myISAMおよびBDBエンジンで実行できます。 InnoDBはこれをサポートしていません。 MySQL 5.0リファレンスマニュアルからの引用。
MyISAMおよびBDBテーブルの場合、複数列インデックスのセカンダリ列にAUTO_INCREMENTを指定できます。この場合、AUTO_INCREMENT列の生成値は、MAX(auto_increment_column)+ 1 WHERE prefix = given-prefixとして計算されます。
http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html
test_id
列の増分要件を完全に理解していませんが、(app_id
、test_id
)の一意の組み合わせごとに再起動する〜autoincrementシーケンスが必要な場合は、次のように、INSERT ... SELECT FROM同じテーブル:
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は適切なインデックスをギャップロックし、競合しないシーケンスを生成しながら、多くの同時プロセスがこの種のクエリを実行できます。
sr_no
、app_id
&test_id
には nique 複合キーを使用できます。これは一意ではないため、sr_no
ではインクリメンタルを使用できません。
CREATE TABLE IF NOT EXISTS `issue_log` (
`sr_no` int(11) NOT NULL,
`app_id` int(11) NOT NULL,
`test_id` int(11) NOT NULL,
`issue_name` varchar(255) NOT NULL,
UNIQUE KEY `app_id` (`app_id`,`test_id`,`sr_no`)
) ENGINE=InnoDB ;
sql fiddle の一意制約違反をコメントアウトして示しています(スキーマの22行目の#を削除してスキーマを再構築します)