Определение составного ключа с автоинкремент в MySQL

сценарий:

У меня есть таблица, которая ссылается на два внешних ключа, и для каждой уникальной комбинации этих внешних ключей имеет свой собственный столбец auto_increment. Мне нужно реализовать составной ключ, который поможет определить строку как уникальную, используя комбинацию этих трех (один внешний ключ и один столбец auto_increment и один другой столбец с не уникальными значениями)

стол:

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: неверное определение таблицы; может быть только один авто колонки и он должен быть определен как ключ

чего я пытаюсь достичь:

У меня есть таблица приложений (с app_id в качестве первичного ключа), каждое приложение имеет набор проблем, которые необходимо решить, и каждое приложение имеет несколько тестов (поэтому test_id col) В sr_no коль должно увеличиваться для уникальных app_id и test_id.

т. е. данные в таблице должны выглядеть так:

enter image description here

компонент database engine-InnoDB. Я хочу достичь этого с максимально возможной простотой (т. е. избегать триггеров/процедур, если это возможно - что было предложено для аналогичных случаев по другим вопросам).

4 ответов


вы не можете заставить MySQL сделать это для вас автоматически для таблиц InnoDB - вам нужно будет использовать триггер или процедуру или пользователь другой механизм БД, такой как MyISAM. Автоматическое увеличение может быть сделано только для одного первичного ключа.

что-то вроде следующего должно работать

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, где prefix=данный-префикс.

http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html


можно использовать уникальный составной ключ sr_no,app_id & test_id. Вы не можете использовать incremental в 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 скрипку чтобы продемонстрировать (удалить # в строке 22 схемы и перестроить схему )


Я не полностью понимаю ваше требование инкремента на test_id столбец, но если вы хотите последовательность ~autoincrement, которая перезапускается при каждой уникальной комбинации (app_id, test_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, но ручная эмуляция работает на произвольных столбцах, в отличие от встроенного автоинкремента.

обратите внимание, что вставка ... SELECT, являющийся одним запросом, обеспечивает атомарность операции. InnoDB заблокирует соответствующий индекс, и многие параллельные процессы могут выполнять такой запрос, все еще создавая не конфликтующие последовательности.