MySQL에서 한 행을 복사하여 같은 테이블에 삽입할 수 있습니까?
insert into table select * from table where primarykey=1
같은 테이블에 삽입할 행을 하나만 복사하고 싶습니다(즉, 테이블의 기존 행을 복제합니다). 그러나 이 테이블에는 열이 너무 많기 때문에 "선택" 뒤에 모든 열을 나열할 필요가 없습니다.
하지만 이렇게 하면 다음과 같은 오류가 발생합니다.
키 1에 대해 'xxx' 항목이 중복됩니다.
복사하려는 레코드의 임시 컨테이너와 같은 열을 가진 다른 테이블을 만들면 이 문제를 해결할 수 있습니다.
create table oldtable_temp like oldtable;
insert into oldtable_temp select * from oldtable where key=1;
update oldtable_tem set key=2;
insert into oldtable select * from oldtable where key=2;
이 문제를 해결할 수 있는 더 간단한 방법은 없나요?
레너드 챌린지스의 기술을 몇 가지 변경해서 사용했습니다.
CREATE TEMPORARY TABLE tmptable_1 SELECT * FROM table WHERE primarykey = 1;
UPDATE tmptable_1 SET primarykey = NULL;
INSERT INTO table SELECT * FROM tmptable_1;
DROP TEMPORARY TABLE IF EXISTS tmptable_1;
임시 테이블로서 레코드가 여러 개 있는 것은 아니므로 프라이머리 키에 대해 걱정할 필요가 없습니다.null로 설정하면 MySQL에서 값 자체를 선택할 수 있으므로 중복을 만들 위험이 없습니다.
삽입할 행이 1개뿐임을 확실히 하고 싶다면 INSERT INTO 행 끝에 LIMIT 1을 추가할 수 있습니다.
프라이머리 키 값(이 경우는 1)도 임시 테이블명에 추가했습니다.
2014년 7월 7일 갱신 - 제 답변에 근거한 Grim...의 답변은 아래의 솔루션보다 개선되므로 더 나은 솔루션이므로 그것을 사용하는 것이 좋습니다.
다음 구문을 사용하여 모든 열을 나열하지 않고도 이 작업을 수행할 수 있습니다.
CREATE TEMPORARY TABLE tmptable SELECT * FROM table WHERE primarykey = 1;
UPDATE tmptable SET primarykey = 2 WHERE primarykey = 1;
INSERT INTO table SELECT * FROM tmptable WHERE primarykey = 2;
다른 방법으로 프라이머리 키를 변경할 수도 있습니다.
에 새 primarykey
primarykey
AUTO_INCREMENT
★★★★★★★★★★★★★★★★★★★★★★★★★★★
INSERT INTO table (col1, col2, col3, ...)
SELECT col1, col2, col3, ... FROM table
WHERE primarykey = 1
서...어디에col1, col2, col3, ...
테이블 내의 모든 컬럼이 다음 컬럼을 제외합니다. primarykey
.
이이 if 가 아니면...가 AUTO_INCREMENT
에서 새 할 수 .primarykey
슷합니니다다
INSERT INTO table (primarykey, col2, col3, ...)
SELECT 567, col2, col3, ... FROM table
WHERE primarykey = 1
서...어디에567
는 새로운 입니다.primarykey
.
첫 번째 쿼리에서는 열을 지정하기만 하면 됩니다.그러면 삽입된 기본 키를 제외할 수 있습니다.그러면 테이블에 있는 기본 키가 자동으로 생성되어 엔트리의 새 기본 키가 생성됩니다.
예를 들어 다음과 같이 변경합니다.
insert into table select * from table where primarykey=1
이를 위해:
INSERT INTO table (col1, col2, col3)
SELECT col1, col2, col3
FROM table
WHERE primarykey = 1
INSERT 또는 쿼리의 SELECT 부분에 대한 열 목록에는 기본 키 열을 포함하지 마십시오.
테이블을 덤프하여 insert 명령을 찾아 편집할 수도 있습니다.
mysqldump -umyuser -p mydatabase --skip-extended-insert mytable > outfile.sql
--skip-extended-insert
행 1 、 1 、 령 1 insert 、 를 、 개 합 니 다 다 다 1 1 。그런 다음 즐겨찾는 텍스트 편집기에서 행을 찾아 명령을 추출하고 기본 키를 "기본값"으로 변경할 수 있습니다.
이것은, 어느 정도의 창조성으로 달성할 수 있습니다.
SET @sql = CONCAT('INSERT INTO <table> SELECT null,
', (SELECT GROUP_CONCAT(COLUMN_NAME)
FROM information_schema.columns
WHERE table_schema = '<database>'
AND table_name = '<table>'
AND column_name NOT IN ('id')), '
from <table> WHERE id = <id>');
PREPARE stmt1 FROM @sql;
EXECUTE stmt1;
그러면 새 행이 선택한 행의 ID 대신 자동으로 증분 ID를 가져옵니다.
이 순서에서는, 다음의 것을 전제로 하고 있습니다.
- _syslog_table이 없습니다.
- 기본 키는 int입니다.
- 테이블을 작성할 수 있는 액세스 권한이 있습니다.
물론 완벽하지는 않지만, (대부분의) 경우에 효과가 있을 수 있습니다.
DELIMITER $$
CREATE PROCEDURE DUPLICATE_ROW(copytable VARCHAR(255), primarykey VARCHAR(255), copyid INT, out newid INT)
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @error=1;
SET @temptable = '_duplicate_temp_table';
SET @sql_text = CONCAT('CREATE TABLE ', @temptable, ' LIKE ', copytable);
PREPARE stmt FROM @sql_text;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @sql_text = CONCAT('INSERT INTO ', @temptable, ' SELECT * FROM ', copytable, ' where ', primarykey,'=', copyid);
PREPARE stmt FROM @sql_text;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @sql_text = CONCAT('SELECT max(', primarykey, ')+1 FROM ', copytable, ' INTO @newid');
PREPARE stmt FROM @sql_text;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @sql_text = CONCAT('UPDATE ', @temptable, ' SET ', primarykey, '=@newid');
PREPARE stmt FROM @sql_text;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @sql_text = CONCAT('INSERT INTO ', copytable, ' SELECT * FROM ', @temptable, '');
PREPARE stmt FROM @sql_text;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @sql_text = CONCAT('DROP TABLE ', @temptable);
PREPARE stmt FROM @sql_text;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SELECT @newid INTO newid;
END $$
DELIMITER ;
CALL DUPLICATE_ROW('table', 'primarykey', 1, @duplicate_id);
SELECT @duplicate_id;
테이블의 기본 키 필드가 자동 증분 필드인 경우 열과 함께 쿼리를 사용할 수 있습니다. 테이블 「」은 다음과 같습니다.test_tbl
에는 3개의 .id, name, age
id
증분입니다. 다음 할 수 .따라서 다음 쿼리를 사용하여 행을 복제할 수 있습니다.
INSERT INTO `test_tbl` (`name`,`age`) SELECT `name`,`age` FROM `test_tbl`;
이 쿼리는 모든 행을 복제합니다.
테이블의 기본 키 필드가 자동 증분 필드가 아닌 경우 다음 방법을 사용할 수 있습니다.
INSERT INTO `test_tbl` (`id`,`name`,`age`)
SELECT 20,`name`,`age` FROM `test_tbl` WHERE id = 19;
.id=19
할 수 .id=20
.
그림 기술을 조금 바꿔서 사용했습니다.이 쿼리를 찾는 사용자가 기본 키 문제로 인해 단순한 쿼리를 수행할 수 없는 경우:
INSERT INTO table SELECT * FROM table WHERE primakey=1;
MySql 설치 5.6.26에서는 키를 null로 할 수 없으며 다음과 같은 오류가 발생합니다.
#1048 - Column 'primakey' cannot be null
따라서 임시 테이블을 작성한 후 기본 키를 nullable로 변경합니다.
CREATE TEMPORARY TABLE tmptable_1 SELECT * FROM table WHERE primarykey = 1;
ALTER TABLE tmptable_1 MODIFY primarykey int(12) null;
UPDATE tmptable_1 SET primarykey = NULL;
INSERT INTO table SELECT * FROM tmptable_1;
DROP TEMPORARY TABLE IF EXISTS tmptable_1;
업데이트 필드 및 자동 증분 값을 사용하여 행 복제
CREATE TEMPORARY TABLE `temp` SELECT * FROM `testing` WHERE id = 14;
UPDATE `temp` SET id = (SELECT id FROM testing ORDER by id DESC LIMIT 1
)+1, user_id = 252 ,policy_no = "mysdddd12" where id = 14;
INSERT INTO `testing` SELECT * FROM `temp`;
DROP TEMPORARY TABLE IF EXISTS `temp`;
Koha 데이터베이스에서 바코드 열에 'C' 접두사가 붙은 중복 항목을 삽입했습니다.
INSERT INTO items (`biblionumber`, `biblioitemnumber`, `barcode`, `dateaccessioned` ) SELECT `biblionumber`, `biblioitemnumber`, CONCAT('C',`barcode`), `dateaccessioned` FROM `items` WHERE barcode='14832';
다음 중 일부는 이 사이트에서 수집되었습니다.이것은 임의의 수의 필드가 있는 테이블에서 레코드를 복제하기 위해 수행한 작업입니다.
또한 표의 선두에 AI 필드가 있다고 가정합니다.
function duplicateRow( $id = 1 ){
dbLink();//my db connection
$qColumnNames = mysql_query("SHOW COLUMNS FROM table") or die("mysql error");
$numColumns = mysql_num_rows($qColumnNames);
for ($x = 0;$x < $numColumns;$x++){
$colname[] = mysql_fetch_row($qColumnNames);
}
$sql = "SELECT * FROM table WHERE tableId = '$id'";
$row = mysql_fetch_row(mysql_query($sql));
$sql = "INSERT INTO table SET ";
for($i=1;$i<count($colname)-4;$i++){//i set to 1 to preclude the id field
//we set count($colname)-4 to avoid the last 4 fields (good for our implementation)
$sql .= "`".$colname[$i][0]."` = '".$row[$i]. "', ";
}
$sql .= " CreateTime = NOW()";// we need the new record to have a new timestamp
mysql_query($sql);
$sql = "SELECT MAX(tableId) FROM table";
$res = mysql_query($sql);
$row = mysql_fetch_row($res);
return $row[0];//gives the new ID from auto incrementing
}
늦은 감이 있지만, 비슷한 해결책이 있습니다.
INSERT INTO `orders` SELECT MAX(`order_id`)+1,`container_id`, `order_date`, `receive_date`, `timestamp` FROM `orders` WHERE `order_id` = 1
이렇게 하면 임시 테이블 등을 작성할 필요가 없습니다.에, 「 」는 「 」를 참조해 .Max(PK)+1
을 사용법
(구문을 잊어버리고) 이 질문의 해답을 찾으러 왔다가 스스로 질문을 하게 되었습니다.가끔 일이 잘 풀리니까 재밌네요
안부 전해요
프라이머리 키가 [Auto Increment]의 경우는 프라이머리 키를 제외한 각 필드를 지정합니다.
INSERT INTO table(field1,field2,field3) SELECT (field1,field2,field3) FROM table WHERE primarykey=1
@레오나드 챌린지스다른 솔루션과는 다른 솔루션으로는 동작하지 않았기 때문입니다.제거했습니다.WHERE
과 '''SET primaryKey = 0
테이블에서 으로 primaryKeyMy를 시킵니다.SQL 프라이머리 키
CREATE TEMPORARY TABLE tmptable SELECT * FROM myTable;
UPDATE tmptable SET primaryKey = 0;
INSERT INTO myTable SELECT * FROM tmptable;
이것은 물론 테이블의 모든 행을 복제합니다.
아래를 사용하겠습니다.
insert into ORDER_ITEM select * from ORDER_ITEM where ITEM_NUMBER =123;
저는 이렇게 해야 했고, 이것이 저의 수동 솔루션이었습니다.
- phpmyadmin에서 복사할 행을 선택합니다.
- 쿼리 결과 작업 하단의 '내보내기'를 클릭합니다.
- 다음 페이지에서 '파일로 저장'을 선택한 후 '실행'을 클릭합니다.
- 텍스트 편집기를 사용하여 내보낸 파일을 열고 기본 필드의 값을 찾은 다음 고유한 값으로 변경합니다.
- phpmyadmin으로 돌아가서 'Import' 탭을 클릭하여 브라우즈에서 .sql 파일을 Import할 파일을 찾은 후 'Go'를 클릭하면 중복된 행을 삽입해야 합니다.
PRIMAY 필드가 무엇인지 모를 경우 phpmyadmin 페이지를 다시 보고 Structure 탭을 클릭하면 페이지 하단의 "Indexes" 아래에 "Field"에 "PRIMAY" 값이 있는 "Field"가 표시됩니다.
꽤 먼 길이지만, 마크업을 처리하고 싶지 않고 한 줄만 복제하면 됩니다.
위에 나타낸 이 솔루션은 선택한 행에서도 완벽하게 작동합니다.예를 들어 nice2work 프로젝트의 데먼스트레이션을 만들고 있는데, 이것이 완벽하게 동작합니다.
CREATE TEMPORARY TABLE tmptable SELECT * FROM myTable WHERE id=500;
UPDATE tmptable SET id = 0;
UPDATE some fields I need to change
INSERT INTO myTable SELECT * FROM tmptable;
DROP TABLE tmptable;
// You can use this same also directly into your code like (PHP Style)
$sql = "CREATE TEMPORARY TABLE tmptable SELECT * FROM myTable WHERE id=500;
UPDATE tmptable SET id = 0;
UPDATE some fields I need to change
INSERT INTO myTable SELECT * FROM tmptable;DROP TABLE tmptable;";
네크로포스트에게 미안하지만, 이것이 구글에서 찾은 것이고, 도움이 되지만 문제가 있다는 것을 알았기 때문에, 이것을 파헤치는 다른 사람에게 중요한 수정에 기여하고 싶었다.
우선 MySQL이 아닌 SQL Server를 사용하지만 비슷하게 동작해야 한다고 생각합니다.Leonard Challis의 솔루션이 가장 단순하고 요구를 충족시키기 위해 사용했지만, 여기에는 문제가 있습니다. PK를 가져다가 1만 늘리면 해당 행이 추가된 후 다른 레코드를 추가하면 어떻게 됩니까?PK의 자동 인크리먼트를 시스템이 처리하도록 하는 것이 최선이라고 판단하고, 다음을 실시했습니다.
SELECT * INTO #tmpTable FROM Table WHERE primarykey = 1
--Optionally you can modify one or more fields here like this:
--UPDATE #tmpTable SET somefield = newData
ALTER TABLE #tmpTable DROP COLUMN TicketUpdateID
INSERT INTO Tickets SELECT * FROM #tmpTable
DROP TABLE #tmpTable
MySQL에서도 동일하게 동작한다고 생각합니다만, 테스트할 수 없습니다.죄송합니다.
오래된 질문인 것은 알지만, 여기 다른 해결책이 있습니다.
프라이머리 키가 자동 증분이라고 가정하고 메인테이블의 행을 복제하여 새로운 메인테이블 ID를 사용하여 링크 테이블 데이터의 복사본을 만듭니다.
:
- FROM - SHOW COLUMNS FROM - ★tablename
(:; (: 필드)
- 설명 - ★★★tablename
(<필드>)
- column_name where = 'SELECT column_name FROM information_select.WHERE table_name = 'tablename'(파일: colum=ame)
//First, copy main_table row
$ColumnHdr='';
$Query="SHOW COLUMNS FROM `main_table`;";
$Result=Wrappedmysql_query($Query,$link,__FILE__,__LINE__);
while($Row=mysql_fetch_array($Result))
{
if($Row['Field']=='MainTableID') //skip main table id in column list
continue;
$ColumnHdr.=",`" . $Row['Field'] . "`";
}
$Query="INSERT INTO `main_table` (" . substr($ColumnHdr,1) . ")
(SELECT " . substr($ColumnHdr,1) . " FROM `main_table`
WHERE `MainTableID`=" . $OldMainTableID . ");";
$Result=Wrappedmysql_query($Query,$link,__FILE__,__LINE__);
$NewMainTableID=mysql_insert_id($link);
//Change the name (assumes a 30 char field)
$Query="UPDATE `main_table` SET `Title`=CONCAT(SUBSTRING(`Title`,1,25),' Copy') WHERE `MainTableID`=" . $NewMainTableID . ";";
$Result=Wrappedmysql_query($Query,$link,__FILE__,__LINE__);
//now copy in the linked tables
$TableArr=array("main_table_link1","main_table_link2","main_table_link3");
foreach($TableArr as $TableArrK=>$TableArrV)
{
$ColumnHdr='';
$Query="SHOW COLUMNS FROM `" . $TableArrV . "`;";
$Result=Wrappedmysql_query($Query,$link,__FILE__,__LINE__);
while($Row=mysql_fetch_array($Result))
{
if($Row['Field']=='MainTableID') //skip main table id in column list, re-added in query
continue;
if($Row['Field']=='dbID') //skip auto-increment,primary key in linked table
continue;
$ColumnHdr.=",`" . $Row['Field'] . "`";
}
$Query="INSERT INTO `" . $TableArrV . "` (`MainTableID`," . substr($ColumnHdr,1) . ")
(SELECT " . $NewMainTableID . "," . substr($ColumnHdr,1) . " FROM `" . $TableArrV . "`
WHERE `MainTableID`=" . $OldMainTableID . ");";
$Result=Wrappedmysql_query($Query,$link,__FILE__,__LINE__);
}
PHP 코드의 일부를 투고하고 싶었을 뿐입니다.컬럼을 수집하는 방법이 이전 예보다 코드가 조금 더 깨끗하다고 생각하기 때문입니다.또한 필드를 쉽게 변경하는 방법도 보여 줍니다(이 경우 문자열을 추가합니다).그러나 일부 하위 레코드를 복사하려는 경우 외부 키 필드를 새로 추가된 레코드로 바꿀 수도 있습니다.
// Read columns, unset the PK (always the first field in my case)
$stmt = $conn->prepare('SHOW COLUMNS FROM template');
$stmt->execute();
$columns = $stmt->fetchAll();
$columns = array_map(function ($element) { return $element['Field']; }, $columns);
unset($columns[0]);
// Insert record in the database. Add string COPY to the name field.
$sql = "INSERT INTO `template` (".implode(",", $columns).")";
if ($key = array_search('name', $columns))
$columns[$key] = "CONCAT(name, ' COPY')";
$sql .= " SELECT ".implode(",", $columns)." FROM `template` WHERE `id` = ".$id;
$stmt = $conn->prepare($sql);
$stmt->execute();
테이블을 작성하다
CREATE TABLE `sample_table` (
`sample_id` INT(10) unsigned NOT NULL AUTO_INCREMENT,
`sample_name` VARCHAR(255) NOT NULL,
`sample_col_1` TINYINT(1) NOT NULL,
`sample_col_2` TINYINT(2) NOT NULL,
PRIMARY KEY (`sample_id`),
UNIQUE KEY `sample_id` (`sample_id`)
) ENGINE='InnoDB' DEFAULT CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
행을 삽입합니다.
INSERT INTO `sample_table`
VALUES(NULL, 'sample name', 1, 2);
위의 행 삽입 복제
INSERT INTO `sample_table`
SELECT
NULL AS `sample_id`, -- new AUTO_INCREMENT PRIMARY KEY from MySQL
'new dummy entry' AS `sample_name`, -- new UNIQUE KEY from you
`sample_col_1`, -- col from old row
`sample_col_2` -- col from old row
FROM `sample_table`
WHERE `sample_id` = 1;
시험
SELECT * FROM `sample_table`;
여기 이 사이트에서 온라인으로 찾은 답변이 있습니다.상기 방법을 설명합니다.1 답변은 페이지 하단에 있습니다.기본적으로 복사할 행을 메모리에 저장된 임시 테이블에 복사합니다.그런 다음 업데이트를 사용하여 기본 키 번호를 변경합니다.그런 다음 대상 테이블에 다시 삽입합니다.그런 다음 테이블을 떨어뜨립니다.
코드는 다음과 같습니다.
TABLE create create create create create create create create create create create create create
rescueteam
MEMORY SELECT * = engine engine engine*fitnessreport4
rID=1;#1로 하다rescueteam
set rID = RHERE WHERE RID = 1 ; #1 행 set set set set set set set set set set set set set set set set set set set set set set set set.★★★에 삽입fitnessreport4
* FROM 택 * selectrescueteam
;# TABLE 1 입니다.rescueteam
# 이 빈 세트 0# MySQL)를
을 지정합니다.
임시 테이블 구조팀을 만들었습니다.원래 테이블 피트니스 리포트4에서 행을 복사했습니다.그런 다음 임시 테이블 행의 기본 키를 null로 설정하면 중복 키 오류가 발생하지 않고 원래 테이블에 복사할 수 있습니다.어제 저녁에 이 코드를 시도했는데 작동했어요.
이것은 "그림..."의 답변에 대한 추가 해결책입니다. 기본 키가 null로 되어 있다는 지적이 있었습니다.안 된다는 댓글도 있어요.솔루션에 대한 코멘트도 있습니다.어떤 해결책도 효과가 없었습니다.InnoDB 테이블이 있는 MariaDB가 있습니다.
무효로 하다NULL 대신 0을 사용하면 프라이머리 키에 중복된 값 오류가 발생하였습니다. SET SQL_SAFE_UPDATES = 0;
역시 작동하지 않았다.
Primary Key를 UNIQURE로 변경했을 경우, 「Grim...」의 솔루션은 기능했습니다.
max233은 적어도 자동 증가의 경우 올바른 궤도에 올랐습니다.단, ALTER TABLE은 사용하지 마십시오.임시 테이블의 auto-increment 필드를 NULL로 설정하기만 하면 됩니다.그러면 오류가 발생하지만 임시 테이블의 모든 필드에 대한 다음 INSERT가 실행되고 NULL 자동 필드가 원하는 값을 가져옵니다.
위의 답변과 SO에 관한 다른 답변에서 도출한 결과, 저는 하나의 레코드를 복제하기 위한 최종 코드로 이 점을 알게 되었습니다.
CREATE TEMPORARY TABLE temptable SELECT * FROM things WHERE Thing_ID = 10000345;
UPDATE temptable SET Thing_ID = 0;
INSERT INTO things SELECT * FROM temptable;
DROP TEMPORARY TABLE IF EXISTS temptable;
Primary 키 값 설정 Thing_ID가 = 0인 것은 NULL을 허용하도록 유혹적인 키를 변경한 다음 PARMY 키를 NULL로 설정하는 것보다 짧으며, 내 경우 MySQL에서 작동합니다.
언급URL : https://stackoverflow.com/questions/4039748/in-mysql-can-i-copy-one-row-to-insert-into-the-same-table
'programing' 카테고리의 다른 글
MySQL datetime 필드 및 여름 시간 - "추가" 시간은 어떻게 참조합니까? (0) | 2022.10.06 |
---|---|
Larabel에서의 MariaDB JSON 지원 (0) | 2022.10.06 |
연결 배열에 항목 추가 (0) | 2022.10.05 |
웹 팩의 "public Path"는 무엇을 합니까? (0) | 2022.10.05 |
C/C++에서 가장 적합한 암호화 라이브러리는 무엇입니까? (0) | 2022.10.05 |