Действительно ли можно ли получить доступ к автоматическому инкрементному значению в MySQL в одном операторе?

22
задан dee-see 21 August 2011 в 22:05
поделиться

4 ответа

нет необходимости создавать еще одну таблицу, а max() будет иметь проблемы в связи с автоинкрементным значением таблицы, сделайте так:

CREATE TRIGGER trigger_name BEFORE INSERT ON tbl FOR EACH ROW
BEGIN
   DECLARE next_id INT;
   SET next_id = (SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='tbl');
   SET NEW.field=next_id;
END

Я объявляю переменную next_id, потому что обычно она будет использоваться как-то иначе(*), но вы могли бы сделать прямо new.field=(select ...)

(*) To auto-name an image:
SET NEW.field = CONCAT('image_', next_id, '.gif');
(*) To create a hash:
SET NEW.field = CONCAT( MD5( next_id ) , MD5( FLOOR( RAND( ) *10000000 ) ) );
34
ответ дан 29 November 2019 в 04:37
поделиться

видя, что last_insert_id() не работал бы в этом случае, да, триггер будет единственным способом выполнить это.

я действительно спрашиваю меня хотя: Для чего Вы нуждаетесь в этой функциональности? Почему Вы храните пользовательский идентификатор дважды? Лично, мне не нравится хранить избыточные данные как это, и я, вероятно, решил бы это в коде приложения путем создания, что зловещий default_assignment столбец NULL и использование идентификатора пользователя в моем коде приложения, если бы default_assignment было ПУСТЫМ.

2
ответ дан pilif 29 November 2019 в 04:37
поделиться

На самом деле я просто пытался сделать то же самое, что было предложено выше. Но кажется, что Mysql doesent генерирует вставленный идентификатор до того, как строка действительно будет зафиксирована. Таким образом, NEW.userid всегда будет возвращать 0 в триггере Before insert.

Вышеупомянутое также не будет работать, если это не триггер BEFORE INSERT, поскольку вы не можете обновлять значения в запросе AFTER INSERT.

Из сообщения на форуме Mysql. кажется, единственный способ справиться с этим - использовать дополнительную таблицу в качестве последовательности. Чтобы ваш триггер мог получать значения из внешнего источника.

CREATE TABLE `lritstsequence` (
  `idsequence` int(11) NOT NULL auto_increment,
  PRIMARY KEY  (`idsequence`)
) ENGINE=InnoDB;

CREATE TABLE `lritst` (
`id` int(10) unsigned NOT NULL auto_increment,
`bp_nr` decimal(10,0) default '0',
`descr` varchar(128) default NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `dir1` (`bp_nr`)
) ENGINE=InnoDB;

DELIMITER $$

DROP TRIGGER /*!50032 IF EXISTS */ `lritst_bi_set_bp_nr`$$

CREATE TRIGGER `lritst_bi_set_bp_nr` BEFORE INSERT ON `lritst`
FOR EACH ROW
BEGIN
    DECLARE secuencia INT;
    INSERT INTO lritstsequence (idsequence) VALUES (NULL);
    SET secuencia = LAST_INSERT_ID();
    SET NEW.id = secuencia;
    SET NEW.bp_nr = secuencia;
END;$$

DELIMITER ;

INSERT INTO lritst (descr) VALUES ('test1');
INSERT INTO lritst (descr) VALUES ('test2');
INSERT INTO lritst (descr) VALUES ('test3');

SELECT * FROM lritst;

Result:

    id   bp_nr  descr 
------  ------  ------
     1       1  test1 
     2       2  test2 
     3       3  test3

Это скопировано с форумов.

2
ответ дан 29 November 2019 в 04:37
поделиться

Единственное, что я обнаружил, что решило бы эту проблему без дополнительной таблицы, - это вычислить себе следующее число и поместить его в обязательные поля.

CREATE TABLE `Temp` (
  `id` int(11) NOT NULL auto_increment,
  `value` varchar(255) ,
  PRIMARY KEY  (`idsequence`)
) ENGINE=InnoDB;


CREATE TRIGGER temp_before_insert BEFORE INSERT ON `Temp`
FOR EACH ROW 
BEGIN
    DECLARE m INT;

    SELECT IFNULL(MAX(id), 0) + 1 INTO m FROM Temp;
    SET NEW.value = m;
    -- NOT NEEDED but to be save that no other record can be inserted in the meanwhile
    SET NEW.id = m;   
END;
2
ответ дан 29 November 2019 в 04:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: