[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.거기에 다른 테이블을 만들 필요가 없습니다, 및 최대 ()이 테이블의 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.이 시도
이 시도
INSERT INTO users (default_assignment) VALUES (LAST_INSERT_ID()+1);
-
==============================
3.그 LAST_INSERT_ID ()를 보는 것은이 경우에하지 작업, 그래, 트리거는 작업을 수행 할 수있는 유일한 방법이 될 것입니다 것입니다.
그 LAST_INSERT_ID ()를 보는 것은이 경우에하지 작업, 그래, 트리거는 작업을 수행 할 수있는 유일한 방법이 될 것입니다 것입니다.
그래도 난 내 자신에게 물어 않는다 : 당신은이 기능을 어떻게해야합니까? 왜 두 번 사용자 ID를 저장합니까? 개인적으로, 나는이 같은 중복 데이터를 저장 싫어 난 아마 그 불길한 default_assignment 열 NULL을하고 default_assignment가 NULL 인 경우 내 응용 프로그램 코드에서 사용자 ID를 사용하여 응용 프로그램 코드에서이 문제를 해결 것입니다.
-
==============================
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.는 그게 자기에게 다음 수를 계산하고 필요한 분야에 그것을 넣어하는 것입니다 별도의 테이블없이이 문제를 해결할 것입니다 발견했다.
는 그게 자기에게 다음 수를 계산하고 필요한 분야에 그것을 넣어하는 것입니다 별도의 테이블없이이 문제를 해결할 것입니다 발견했다.
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.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.
$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.당신은 안정적으로 간단한 하위 쿼리를 사용하여이 작업을 수행 할 수 있습니다 :
당신은 안정적으로 간단한 하위 쿼리를 사용하여이 작업을 수행 할 수 있습니다 :
INSERT INTO users ('username','default_assignment') SELECT 'barry', Auto_increment FROM information_schema.tables WHERE TABLE_NAME='users'
-
==============================
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.이 게시물은 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
'업데이트'문은 카운터 테이블의 행을 잠급니다. 이 피합니다 중복은 여러 스레드에 의해 만들어지고있다.
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
'SQL' 카테고리의 다른 글
[SQL] 2008 SQL Server의 SS : 00 : MM : 어떻게 HH의 정수 (시간)을 변환하는? (0) | 2020.04.08 |
---|---|
[SQL] 피벗 2000 SQL Server를 사용하여 (0) | 2020.04.07 |
[SQL] 하나의 레코드에 대한 제약은 기본값으로 표시 (0) | 2020.04.07 |
[SQL] case 문 및 DECODE 동등한 있습니까? (0) | 2020.04.07 |
[SQL] PostgreSQL는 테이블 함수에서 주문 / 제한 파라미터 (0) | 2020.04.07 |