복붙노트

[SQL] 하나의 문 내에서의 MySQL의 자동 증가 값에 액세스 할 수 있습니까?

SQL

하나의 문 내에서의 MySQL의 자동 증가 값에 액세스 할 수 있습니까?

나는 사용자의 테이블을 포함하는 MySQL 데이터베이스가 있습니다. 테이블의 기본 키는 자동 증가 필드로 설정되어 '사용자 ID'입니다.

내가 뭘하려는 테이블이 자동 증가가 다른 필드, 'default_assignment'에서 '사용자 ID'필드에서 생성되는 것과 동일한 값을 사용하는 것입니다에 나는 새 사용자를 삽입 할 때입니다.

EG

이 같은 성명 싶습니다

INSERT INTO users ('username','default_assignment') VALUES ('barry', value_of_auto_increment_field())

사용자 I '배리'를 만들도록 상기 '사용자 ID'는 (16) (예를 들어)로서 발생하지만 역시 'default_assignment가'16의 값이 동일 할.

이 기쁘게 달성 할 수있는 방법이 있습니까?

감사!

최신 정보:

답장 주셔서 감사합니다. default_assignment 필드는 중복되지 않습니다. default_assigment는 사용자 테이블에서 사용자를 참조 할 수 있습니다. 사용자를 생성 할 때 나는 이미, 그러나 그것은 동일한 사용자로 설정해야 경우가 따라서, 내 질문이있다는 default_assignment 등 다른 사용자의 선택을 할 수있는 형태를 갖는다.

최신 정보:

좋아, 나는 일이 얻을 수 없습니다 여전히 업데이트 트리거 제안에서 시도했지만했습니다. 여기에 내가 만든 트리거는 다음과 같습니다

CREATE TRIGGER default_assignment_self BEFORE INSERT ON `users`  
FOR EACH ROW BEGIN
SET NEW.default_assignment = NEW.userid;
END;

default_assignment는 항상 0으로 설정되어 있지만 새 사용자를 삽입 할 때.

내가 수동으로 다음 사용자 ID를 설정하면 default_assignment는 사용자 ID로 설정 얻을 않습니다.

트리거가 적용됩니다 후 따라서 자동 할당 생성 과정은 분명히 발생합니다.

해결법

  1. ==============================

    1.거기에 다른 테이블을 만들 필요가 없습니다, 및 최대 ()이 테이블의 AUTO_INCREMENT 값에 따라 문제가있는 것,이 작업을 수행 :

    거기에 다른 테이블을 만들 필요가 없습니다, 및 최대 ()이 테이블의 AUTO_INCREMENT 값에 따라 문제가있는 것,이 작업을 수행 :

    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을 할 수 = (선택 ...)

    (*) 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 ) ) );
    
  2. ==============================

    2.이 시도

    이 시도

    INSERT INTO users (default_assignment) VALUES (LAST_INSERT_ID()+1);
    
  3. ==============================

    3.그 LAST_INSERT_ID ()를 보는 것은이 경우에하지 작업, 그래, 트리거는 작업을 수행 할 수있는 유일한 방법이 될 것입니다 것입니다.

    그 LAST_INSERT_ID ()를 보는 것은이 경우에하지 작업, 그래, 트리거는 작업을 수행 할 수있는 유일한 방법이 될 것입니다 것입니다.

    그래도 난 내 자신에게 물어 않는다 : 당신은이 기능을 어떻게해야합니까? 왜 두 번 사용자 ID를 저장합니까? 개인적으로, 나는이 같은 중복 데이터를 저장 싫어 난 아마 그 불길한 default_assignment 열 NULL을하고 default_assignment가 NULL 인 경우 내 응용 프로그램 코드에서 사용자 ID를 사용하여 응용 프로그램 코드에서이 문제를 해결 것입니다.

  4. ==============================

    4.사실 난 그냥 위에서 제시 한 것과 같은 일을하려고 노력했다. 그러나 행이 실제로 커밋되기 전에 MySQL이 삽입 된 ID를 생성 doesent 보인다. NEW.userid는 항상 전에 삽입 트리거에 0을 반환합니다 그래서.

    사실 난 그냥 위에서 제시 한 것과 같은 일을하려고 노력했다. 그러나 행이 실제로 커밋되기 전에 MySQL이 삽입 된 ID를 생성 doesent 보인다. NEW.userid는 항상 전에 삽입 트리거에 0을 반환합니다 그래서.

    당신이 AFTER의 INSERT 쿼리에서 값을 업데이트하지 못할 이후가하는 BEFORE 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
    

    이 forums.mysql.com/read.php?99,186171,186241#msg-186241에서 복사되었지만 임은 아직 링크를 게시 할 수 없습니다.

  5. ==============================

    5.는 그게 자기에게 다음 수를 계산하고 필요한 분야에 그것을 넣어하는 것입니다 별도의 테이블없이이 문제를 해결할 것입니다 발견했다.

    는 그게 자기에게 다음 수를 계산하고 필요한 분야에 그것을 넣어하는 것입니다 별도의 테이블없이이 문제를 해결할 것입니다 발견했다.

    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;
    
  6. ==============================

    6.Resegue 말했듯이 기본적으로 솔루션입니다. 당신은 하나 개의 문장에서 그것을 원하는 경우에, 당신은 방법 아래 중 하나를 사용합니다 :

    Resegue 말했듯이 기본적으로 솔루션입니다. 당신은 하나 개의 문장에서 그것을 원하는 경우에, 당신은 방법 아래 중 하나를 사용합니다 :

    1. 하나의 긴 문장 :

    INSERT INTO `t_name`(field) VALUES((SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='t_name'))
    

    또는 번호와 텍스트 :

    INSERT INTO `t_name`(field) VALUES(CONCAT('Item No. ',CONVERT((SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='t_name') USING utf8)))
    

    PHP에서 더 명확하게 보이는 :

    $pre_name='Item No. ';
    $auto_inc_id_qry = "(SELECT AUTO_INCREMENT FROM information_schema.TABLES
        WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='$table')";
    $new_name_qry = "CONCAT('$pre_name',CONVERT($auto_inc_id_qry USING utf8))";
    mysql_query("INSERT INTO `$table`(title) VALUES($new_name_qry)");
    

    2. 사용 기능 : (아직 테스트하지)

    CREATE FUNCTION next_auto_inc(table TINYTEXT) RETURNS INT
    BEGIN
    DECLARE next_id INT;
    SELECT AUTO_INCREMENT FROM information_schema.TABLES
        WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=table INTO next_id;
    RETURN next_id;
    END
    
    INSERT INTO users ('username','default_assignment')
        VALUES ('barry', next_auto_inc('users'))
    
  7. ==============================

    7.

    $ret = $mysqli->query("SELECT Auto_increment FROM information_schema.tables WHERE table_schema = DATABASE() ");l
    while ($row = mysqli_fetch_array($ret)) {
        $user_id=$row['Auto_increment'];
    }
    
  8. ==============================

    8.당신은 안정적으로 간단한 하위 쿼리를 사용하여이 작업을 수행 할 수 있습니다 :

    당신은 안정적으로 간단한 하위 쿼리를 사용하여이 작업을 수행 할 수 있습니다 :

    INSERT INTO users ('username','default_assignment')
        SELECT 'barry', Auto_increment FROM information_schema.tables WHERE TABLE_NAME='users'
    
  9. ==============================

    9.나는 10 개 동시 스레드 삽입을하고 함께 위의 트리거 아이디어를 테스트하고 나는 ~ 25000 삽입 후 2 ~ 3 중복의 이상 1,000가지 경우를 얻었다.

    나는 10 개 동시 스레드 삽입을하고 함께 위의 트리거 아이디어를 테스트하고 나는 ~ 25000 삽입 후 2 ~ 3 중복의 이상 1,000가지 경우를 얻었다.

    DROP TABLE IF EXISTS test_table CASCADE;
    
    CREATE TABLE `test_table` (
      `id`             INT         NOT NULL  AUTO_INCREMENT,
      `update_me`      VARCHAR(36),
      `otherdata`      VARCHAR(36) NOT NULL,
    
      PRIMARY KEY (`id`)
    )
      ENGINE = InnoDB
      DEFAULT CHARSET = utf8
      COMMENT 'test table for trigger testing';
    
    delimiter $$
    
    DROP TRIGGER IF EXISTS setnum_test_table;
    $$
    CREATE TRIGGER setnum_test_table
    BEFORE INSERT ON test_table FOR EACH ROW
    -- SET OLD.update_me = CONCAT(NEW.id, 'xyz');
    
    BEGIN
       DECLARE next_id INT;
       SET next_id = (SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='test_table' LOCK IN SHARE MODE );
    --    SET NEW.update_me = CONCAT(next_id, 'qrst');
        SET NEW.update_me = next_id;
    END
    
    $$
    
    delimiter ;
    
    -- SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='test_table'
    
    INSERT INTO test_table (otherdata) VALUES ('hi mom2');
    
    SELECT count(*) FROM test_table;
    SELECT * FROM test_table;
    
    -- select count(*) from (
    select * from (
    SELECT count(*) as cnt ,update_me FROM test_table group by update_me) q1
    where cnt > 1
    order by cnt desc
    

    나는 10 사용 :

    while true ; do echo "INSERT INTO test_table (otherdata) VALUES ('hi mom2');" | mysql --user xyz testdb ; done &
    

    그리고 중복 볼 수있는 마지막 쿼리를 실행

    출력 예 : '3', '4217' '3', '13491' '2', '10037' '2', '14658' '2', '5080' '2', '14201' ...

    참고 'LOCK IN SHARE MODE는'아무 것도 변경하지 않았다. 와 같은 속도에 대한에서 준 중복없이. MySQL의 AUTO_INCREMENT는 포스트 그레스 'next_val ()와 같은 작업을하지 않는 및 동시성 안전하지 않습니다 것 같다.

  10. ==============================

    10.이 게시물은 2010 년부터 알지만, 나는 좋은 해결책을 찾을 수 없습니다. 나는 카운터를 보유하고 별도의 테이블을 만들어이 문제를 해결했습니다. 나는 열에 대한 고유 식별자를 생성해야 할 때 난 그냥 저장된 프로 시저를 호출

    이 게시물은 2010 년부터 알지만, 나는 좋은 해결책을 찾을 수 없습니다. 나는 카운터를 보유하고 별도의 테이블을 만들어이 문제를 해결했습니다. 나는 열에 대한 고유 식별자를 생성해야 할 때 난 그냥 저장된 프로 시저를 호출

    CREATE DEFINER=`root`@`localhost` PROCEDURE `IncrementCounter`(in id varchar(255))
    BEGIN
    declare x int;
    -- begin;
    start transaction;
    -- Get the last counter (=teller) and mark record for update.
    select Counter+1 from tabel.Counter where CounterId=id into x for update;
    -- check if given counter exists and increment value, otherwise create it.
    if x is null then
        set x = 1;
        insert into tabel.Counters(CounterId, Counter) values(id, x);
    else
        update tabel.Counters set Counter = x where CounterId = id;
    end if;
    -- select the new value and commit the transaction
    select x;
    commit;
    END
    

    '업데이트'문은 카운터 테이블의 행을 잠급니다. 이 피합니다 중복은 여러 스레드에 의해 만들어지고있다.

  11. from https://stackoverflow.com/questions/469009/can-you-access-the-auto-increment-value-in-mysql-within-one-statement by cc-by-sa and MIT license