ProgramingTip

MySQL 테이블에 여러 행을 삽입하고 새 ID를 지불해야합니까?

bestdevel 2020. 11. 2. 08:09
반응형

MySQL 테이블에 여러 행을 삽입하고 새 ID를 지불해야합니까?


일반적으로 MySQL 테이블에 행을 삽입하고 last_insert_id다시 있습니다. 하지만 이제는 테이블에 많은 행을 대량으로 삽입하고 ID 배열을 가져오고 싶습니다. 내가 어떻게 할 수 있는지 아는 사람이 있습니까?

동일하게 준비 할 것입니다. 임시 테이블에 새 ID를 삽입하고 싶지 않습니다. ID 배열을 되찾고 싶습니다.

대량 삽입에서 lastInsertId를 검색 할 수 있습니까?

last_insert_id ()를 사용하는 MySQL 다중 행 삽입 선택 문


이전에 존재하는 곳에서입니다. 최신 버전의 MySQL에서 InnoDB를 사용하는 경우 LAST_INSERT_ID()사용하여 ID 목록을 찾을 수 있습니다 ROW_COUNT().

InnoDB innodb_autoinc_lock_mode대량 삽입을 수행 할 때 AUTO INCREMENT에 대한 순차 번호를 보장합니다. 단, 0 (일반) 또는 1 (연속)로 설정되어 있습니다. 결과적으로 추가 하여 첫 번째 ID LAST_INSERT_ID()마지막 ID를 얻을 수 있습니다 ROW_COUNT()-1.


내가 할 수있는 유일한 방법은 삽입 된 각 행 집합 (guid)에 대해 고유 한 식별자를 저장하는 방법은 한 다음 행 ID를 선택하는 것입니다. 예 :

INSERT INTO t1
(SELECT col1,col2,col3,'3aee88e2-a981-1027-a396-84f02afe7c70' FROM a_very_large_table);
COMMIT;

SELECT id FROM t1 
WHERE guid='3aee88e2-a981-1027-a396-84f02afe7c70';

다음을 사용하여 데이터베이스에 GUID를 생성 할 수 있습니다. uuid()


두 개의 개의 열 uid, col1이있는 temptable이라는 테이블이 안심 가정합니다. 여기서 uid는 자동 증가 필드입니다. 전면 된 모든 ID가 반환됩니다. 결과 집합을 반복하고 ID를 얻을 수 있습니다. 나는 모든 것이 오래된 게시물이며이 솔루션이 경우에 작동하지 않을 수 있습니다. 그러나 다른 사람들에게는 그럴 수있는 것이 있습니다.

# lock the table
lock tables temptable write;

#bulk insert the rows;
insert into temptable(col1) values(1),(2),(3),(4);

#get the value of first inserted row. when bulk inserting last_insert_id() #should give the value of first inserted row from bulk op.
set @first_id = last_insert_id();

#now select the auto increment field whose value is greater than equal to #the first row. Remember since you have write lock on that table other #sessions can't write to it. This resultset should have all the inserted #id's
select uid from temptable where uid >=@first_id;

#now that you are done don't forget to unlock the table.
unlock tables;

이 작업을 완벽하게 수행 한 애플리케이션의 트랜잭션 ID 또는 애플리케이션의 항목 ID를 처리해야합니다.

모든 삽입이 성공 (!)된다고 가정하고 작동 할 수있는 한 가지 방법은 다음과 같다.

그런 다음 lastid (대량 삽입의 첫 번째 삽입 된 ID)로 시작하여 영향을받는 행 수에 대한 루프로 삽입 된 ID를 수 있습니다. 작동하게 작동하는지 확인했습니다. 예를 들어 HeidiSQL이 ROW_COUNT ()에 대한 올바른 값을 반환하지 마십시오. 아마도 그것은 우리가 요청하지 않는 임의의 작업을 수행하는 엉터리 GUI이기 때문일 것입니다. 그러나 둘 중 하나에서 완벽하게 맞습니다. 명령 줄 또는 PHP mysqli-

START TRANSACTION;
BEGIN;
INSERT into test (b) VALUES ('1'),('2'),('3');
SELECT LAST_INSERT_ID() AS lastid,ROW_COUNT() AS rowcount;
COMMIT;

PHP에서는 다음과 같습니다 (local_sqle는 mysqli_query에 대한 호출, local_sqlec은 mysqli_query에 대한 호출 + 결과 집합을 PHP 배열로 변환).

local_sqle("START TRANSACTION;
BEGIN;
INSERT into test (b) VALUES ('1'),('2'),('3');");
$r=local_sqlec("SELECT LAST_INSERT_ID() AS lastid,ROW_COUNT() AS rowcount;");
local_sqle("
COMMIT;");
$i=0;
echo "last id =".($r[0]['lastid'])."<br>";
echo "Row count =".($r[0]['rowcount'])."<br>";

while($i<$r[0]['rowcount']){
    echo "inserted id =".($r[0]['lastid']+$i)."<br>";
    $i++;
}

쿼리가 분리 된 이유는 내 자신의 함수를 사용하여 내 결과를 얻지 못하기 때문입니다. 표준 함수를 사용하여이 작업을 수행하면 하나의 문에 다시 넣은 다음 필요한 결과를 검색 할 수 있습니다 (결과 번호 여야 함). 2-둘 이상의 결과 집합 / 쿼리를 처리하는 확장을 사용한다고 가정합니다.


자동 증가 값이 항목을 1 씩 증가시킬 것이라고 확신 할 수 없으며 DB에 Master // Master 복제가 있고 auto_increment 중복 제외를 해결하려면 큰 문제가있을 것입니다. AI는 +1 대신 +2가되며, 마스터가 하나 더 있으면 +3이됩니다. 그래서 AUTO_INCREMENT가 1을 올리는 것과 같은 릴레이는 프로젝트를 죽이는 것입니다.

나는 그것을 할 수있는 몇 가지 좋은 옵션 만 보입니다.

이 SQL 스 니펫은 여러 마스터에 문제가 없으며 삽입 된 레코드 만 필요할 때까지 좋은 결과를 제공합니다. 트랜잭션이없는 여러 요청에서 다른 삽입 레코드를 포착 할 수 있습니다.

START TRANSACTION;
SELECT max(id) into @maxLastId FROM `main_table`;
INSERT INTO `main_table` (`value`) VALUES ('first'), ('second') ON DUPLICATE KEY UPDATE `value` = VALUES(`value`);
SELECT `id` FROM `main_table` WHERE id > @maxLastId OR @maxLastId IS NULL;
COMMIT;

(DUPLICATE KEY UPDATE에 의해 업데이트 된 레코드가 필요한 경우) 데이터베이스를 약간 리팩터링해야하며 SQL은 다음과 같이 보일 것입니다 (트랜잭션에 안전하고 하나의 연결 내에 트랜잭션이 없음).

#START TRANSACTION    
INSERT INTO bulk_inserts VALUES (null);
SET @blukTransactionId = LAST_INSERT_ID();
SELECT  @blukTransactionId, LAST_INSERT_ID();
INSERT INTO `main_table` (`value`, `transaction_id`) VALUES ('first', @blukTransactionId), ('second', @blukTransactionId) ON DUPLICATE KEY UPDATE `value` = VALUES(`value`), `transaction_id` = VALUES(`transaction_id`);
SELECT  @blukTransactionId, LAST_INSERT_ID();
SELECT id FROM `main_table` WHERE `transaction_id` = @blukTransactionId;
#COMMIT

두 경우 모두 다국적에 안전합니다. 첫 번째는 삽입 된 레코드 만 표시하고 두 번째는 업데이트 된 모든 레코드를 제공합니다.

또한 이러한 옵션은 INSERT IGNORE ...에서도 작동합니다.


$query = "INSERT INTO TABLE (ID,NAME,EMAIL) VALUES (NULL,VALUE1, VALUE2)";
$idArray = array();
foreach($array as $key) {
 mysql_query($query);
 array_push($idArray, mysql_insert_id());
}
print_r($idArray);

참고 URL : https://stackoverflow.com/questions/7333524/how-can-i-insert-many-rows-into-a-mysql-table-and-return-the-new-ids

반응형