MySQL에서 자동 증가 필드를 사용하여 행을 복사하고 동일한 테이블에 삽입하는 방법은 무엇입니까?


233

MySQL의에서 나는있는 행을 복사하려고 자동 증가 column ID=1 및 삽입 을 가진 새로운 행으로 같은 테이블에 데이터를 column ID=2.

단일 쿼리로 어떻게 할 수 있습니까?

답변:


351

사용 INSERT ... SELECT:

insert into your_table (c1, c2, ...)
select c1, c2, ...
from your_table
where id = 1

를 c1, c2, ...제외한 모든 열은 어디에 있습니까 id? id를 2 로 명시 적으로 삽입하려면 INSERT 열 목록과 SELECT에 포함하십시오.

insert into your_table (id, c1, c2, ...)
select 2, c1, c2, ...
from your_table
where id = 1

id물론 두 번째 경우에는 2 의 가능한 복제본 을 처리해야합니다.


1
INFORMATION_SCHEMA를 사용하여 프로그래밍 방식으로 열 이름을 얻을 수 있습니다 ... 하위 쿼리 및 일부 문자열 함수로 사용할 수 있는지 궁금합니다. 흠 ...
— 이즈미르 라미레즈

1
@ Yzmir : 동적 SQL을 사용해야하며 일반적으로 저장 프로 시저를 작성해야합니다. 어쨌든 편리한 열 이름 목록을 가져야 할 때보 다 더 많은 문제가있는 것 같습니다.
— mu는 너무 짧다

6
저장 프로 시저로 이동하면 내 경험에 동의합니다. 다시 돌아 가지 않습니다. 이제 해당 데이터베이스와 결혼하여 변경하고 싶을 때마다 비용이 추가됩니다.
— 이즈미르 라미레즈

11
@ YzmirRamirez, 당신은 결혼이 본질적으로 나쁜 일처럼 들리게합니다. :)
— Falken 교수

1
복사 된 다른 모든 필드와 함께 열에 하나의 사용자 정의 값을 추가하는 방법은 무엇입니까?
— Manish Kumar

49

IMO는 가장 좋은 것은 SQL 문을 사용하여 해당 행을 복사하는 동시에 동시에 필요하고 변경하려는 열만 참조하는 것 같습니다.

CREATE TEMPORARY TABLE temp_table ENGINE=MEMORY

SELECT * FROM your_table WHERE id=1;
UPDATE temp_table SET id=NULL; /* Update other values at will. */

INSERT INTO your_table SELECT * FROM temp_table;
DROP TABLE temp_table;

av8n.com-SQL 레코드 복제 방법 도 참조하십시오.

혜택:

  • SQL 문 2는 복제 프로세스 중에 변경해야하는 필드 만 언급합니다. 그들은 다른 분야에 대해 알지 못하거나 걱정하지 않습니다. 다른 필드는 변경없이 그대로갑니다. 이는 SQL 문 작성, 읽기, 유지 보수 및 확장 성을 향상시킵니다.
  • 일반적인 MySQL 문만 사용됩니다. 다른 도구 나 프로그래밍 언어는 필요하지 않습니다.
  • 한 your_table번의 원자 조작으로 완전히 올바른 레코드가 삽입됩니다 .

3
이 멋진 트릭 (나는 그것을 좋아했지만 나에게는 효과가 없었습니다)은 TEXT / VARCHAR 열을 포함하는 테이블에서 작동하지 않습니다. 나는 그것을 시도하고 얻었다 : (1163) : 사용 된 테이블 유형은 BLOB / TEXT 열을 지원하지 않습니다. 물론 MySQL에서의 사용은 매우 제한적입니다! 미래에는 이러한 제한이 해제되거나 다른 DB 시스템에서 작동하지만 실제로는 제한되어 있습니다.
— Juergen

나는 임시 테이블을 영리하게 사용하는 것을 정말로 좋아합니다. 열이 많은 테이블에 유용합니다!
— Lasma

1
멋지게 보이지만 MySQL에서 첫 번째 쿼리를 실행하면을 얻습니다 Error Code: 1113. A table must have at least 1 column.
— 신체적

3
많은 열에 대한 최상의 답변. 그러나 SET id=NULL오류가 발생할 수 있습니다 Column 'id' cannot be null. UPDATE temp_table SET id = (SELECT MAX(id) + 1 as id FROM your_table);
— Modder

1
@physicalattraction 당신은 처음 두 줄이 하나의 진술인지 확인해야합니다.
— Samuurai

16

테이블이이라고 가정하십시오 user(id, user_name, user_email).

이 쿼리를 사용할 수 있습니다 :

INSERT INTO user (SELECT NULL,user_name, user_email FROM user WHERE id = 1)

29
당신은해야한다 항상 INSERT를 사용할 때 스키마가 변경 될 때, 그렇지 않으면 당신은 이상하고 흥미로운 버그를 얻을 것이다, 열 이름을 지정합니다.
— mu는 너무 짧다

2
정말 이상하고 재미 있습니다. : D
— sparkyShorts

sqlite와 함께 작동하지 않습니다. Result: near "SELECT": syntax error
— kyb

10

이것은 도움이되었으며 BLOB / TEXT 열을 지원합니다.

CREATE TEMPORARY TABLE temp_table
AS
SELECT * FROM source_table WHERE id=2;
UPDATE temp_table SET id=NULL WHERE id=2;
INSERT INTO source_table SELECT * FROM temp_table;
DROP TEMPORARY TABLE temp_table;
USE source_table;

이것은 다른 답변보다 어떤면에서 더 낫습니까?
— Smar

3
100 개의 필드가있는 테이블이 있으면 꽤 좋습니다. ID에 대해 null이 아닌 제약 조건을 제외하고는 실패합니다
— Loïc Faure-Lacroix

오류 코드 : 1136. 열 개수가 1 행의 값 개수와 일치하지 않습니다
— Oleksii Kyslytsyn

열이 100 개인 테이블이있는 경우 훨씬 좋습니다.
— Tyler S. Loeper 2013 년

몇 년 전에 이것이 parvus가 말한 것이 아닙니까?
— ToolmakerSteve

7

열 이름을 지정할 필요가없는 빠르고 깨끗한 솔루션을 위해 https://stackoverflow.com/a/23964285/292677에 설명 된대로 준비된 명령문을 사용할 수 있습니다.

이 작업을 자주 수행 할 수 있도록 복잡한 솔루션이 필요한 경우이 절차를 사용할 수 있습니다.

DELIMITER $$

CREATE PROCEDURE `duplicateRows`(_schemaName text, _tableName text, _whereClause text, _omitColumns text)
SQL SECURITY INVOKER
BEGIN
  SELECT IF(TRIM(_omitColumns) <> '', CONCAT('id', ',', TRIM(_omitColumns)), 'id') INTO @omitColumns;

  SELECT GROUP_CONCAT(COLUMN_NAME) FROM information_schema.columns 
  WHERE table_schema = _schemaName AND table_name = _tableName AND FIND_IN_SET(COLUMN_NAME,@omitColumns) = 0 ORDER BY ORDINAL_POSITION INTO @columns;

  SET @sql = CONCAT('INSERT INTO ', _tableName, '(', @columns, ')',
  'SELECT ', @columns, 
  ' FROM ', _schemaName, '.', _tableName, ' ',  _whereClause);

  PREPARE stmt1 FROM @sql;
  EXECUTE stmt1;
END

다음과 같이 실행할 수 있습니다.

CALL duplicateRows('database', 'table', 'WHERE condition = optional', 'omit_columns_optional');

예

duplicateRows('acl', 'users', 'WHERE id = 200'); -- will duplicate the row for the user with id 200
duplicateRows('acl', 'users', 'WHERE id = 200', 'created_ts'); -- same as above but will not copy the created_ts column value    
duplicateRows('acl', 'users', 'WHERE id = 200', 'created_ts,updated_ts'); -- same as above but also omits the updated_ts column
duplicateRows('acl', 'users'); -- will duplicate all records in the table

면책 조항 :이 솔루션은 많은 테이블에서 행을 반복적으로 복제하는 사람에게만 적합합니다. 불량 사용자의 손에 위험 할 수 있습니다.


3

열을 자동 증가시킬 값으로 '0'을 전달할 수도 있습니다. 레코드가 작성 될 때 올바른 값이 사용됩니다. 이것은 임시 테이블보다 훨씬 쉽습니다.

출처 : MySQL에서 행 복사 (TRiG의 첫 번째 솔루션에 대한 Lore의 두 번째 주석 참조)


1
이 방법은 NULL이 허용되지 않는 경우 최신 MySQL 버전에서 작동합니다.
— err

3

여기에 많은 훌륭한 답변이 있습니다. 다음은 개발중인 웹 응용 프로그램에 대해이 작업을 수행하기 위해 작성한 저장 프로 시저 샘플입니다.

-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON

-- Create Temporary Table
SELECT * INTO #tempTable FROM <YourTable> WHERE Id = Id

--To trigger the auto increment
UPDATE #tempTable SET Id = NULL 

--Update new data row in #tempTable here!

--Insert duplicate row with modified data back into your table
INSERT INTO <YourTable> SELECT * FROM #tempTable

-- Drop Temporary Table
DROP TABLE #tempTable

현재 버전의 MariaDB / MySQL 설정에서 id = null은 # 1048을 제공합니다. 'id'열은 null 일 수 없으며 id = 0으로 설정하면 작동합니다.
— shelbypereira

2
insert into MyTable(field1, field2, id_backup)
    select field1, field2, uniqueId from MyTable where uniqueId = @Id;

3
여기에 다른 답변보다 더 나은 방법은 무엇입니까?
— Smar

1
@smar IMO는 청소기 이해의
— Satbir 키라

2

MySQL Workbench를 사용할 수있는 경우 행을 마우스 오른쪽 단추로 클릭하고 '행 복사'를 선택한 다음 빈 행을 마우스 오른쪽 단추로 클릭하고 '행 붙여 넣기'를 선택한 다음 ID를 변경하여이를 수행 할 수 있습니다. '적용'을 클릭하십시오.

행을 복사하십시오.

여기에 이미지 설명을 입력하십시오

복사 한 행을 빈 행에 붙여 넣습니다.

여기에 이미지 설명을 입력하십시오

ID를 변경하십시오.

여기에 이미지 설명을 입력하십시오

대다:

여기에 이미지 설명을 입력하십시오


0

나는 같은 기능을 찾고 있었지만 MySQL을 사용하지 않습니다. 물론 기본 키 (id)를 제외한 모든 필드를 복사하고 싶었습니다. 이것은 스크립트 나 코드에서 사용되지 않는 원샷 쿼리입니다.

PL / SQL과 관련된 길을 찾았지만 다른 SQL IDE가 할 것이라고 확신합니다. 나는 기본을했다

SELECT * 
FROM mytable 
WHERE id=42;

그런 다음 찾을 수있는 SQL 파일로 내 보냅니다.

INSERT INTO table (col1, col2, col3, ... , col42) 
VALUES (1, 2, 3, ..., 42);

방금 편집하여 사용했습니다.

INSERT INTO table (col1, col2, col3, ... , col42) 
VALUES (mysequence.nextval, 2, 3, ..., 42);

0

mu가 너무 짧게 게시 된 변형을 사용하는 경향이 있습니다.

INSERT INTO something_log
SELECT NULL, s.*
FROM something AS s
WHERE s.id = 1;

테이블에 동일한 필드가있는 한 (로그 테이블의 자동 증분 제외), 잘 작동합니다.

가능하면 데이터베이스에 익숙하지 않은 다른 프로그래머가 쉽게 사용할 수 있도록 저장 프로 시저를 사용하므로 테이블에 새 필드를 추가 할 때마다 프로 시저로 돌아가서 업데이트해야하는 문제를 해결합니다.

또한 테이블에 새 필드를 추가하면 데이터베이스 쿼리를 업데이트하지 않고도 로그 테이블에 즉시 표시되기 시작합니다 (물론 필드를 명시 적으로 설정 한 경우가 아닌 한)

경고 : 필드 순서가 동일하게 유지되도록 두 테이블에 새 필드를 동시에 추가해야합니다. 그렇지 않으면 이상한 버그가 발생합니다. 데이터베이스 인터페이스를 작성하는 유일한 사람이고 매우 조심하면 잘 작동합니다. 그렇지 않으면 모든 필드의 이름을 지정하십시오.

참고 : 솔로 프로젝트에서 작업하지 않는 한 다른 프로젝트에서는 모든 필드 이름을 명시 적으로 나열하고 스키마가 변경되면 로그 문을 업데이트하는 것이 아닙니다. 이 지름길은 아마도 생산 시스템에서 발생할 수있는 장기 두통의 가치가 없을 것입니다.


0
`dbMyDataBase`에 삽입하십시오 .`tblMyTable` 
(
    `자동 증가`, 
    `열 2`, 
    `열 3`, 
    `열 4` 
) 

고르다 
    없는,  
    `열 2`, 
    `열 3`, 
    'CustomValue'AS Column4 
`dbMyDataBase`.`tblMyTable`에서 
`tblMyTable`.`Column2` = 'UniqueValueOfTheKey'위치 
; 
/ * mySQL 5.6 * /

3
좀 더 자세한 설명을 추가하거나 다른 답변으로 어떻게 확장되는지 살펴보십시오
— Azsgy

-1

SQL하려는 행을 덤프 한 다음 생성 된 SQL을 사용하여 ID 열을 줄이고 다시 가져 오십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.