SQL 테이블의 레코드를 복사하지만 새 행의 고유 ID를 바꾸는 방법은 무엇입니까?


123

이 질문 은 내가 필요로하는 것에 가깝지만 내 시나리오는 약간 다릅니다. 원본 테이블과 대상 테이블이 동일하고 기본 키는 고유 식별자 (guid)입니다. 내가 이것을 시도 할 때 :

insert into MyTable
    select * from MyTable where uniqueId = @Id;

기본 키를 복사하려고하기 때문에 분명히 기본 키 제약 조건 위반이 발생합니다. 사실, 저는 기본 키를 전혀 복사하고 싶지 않습니다. 차라리 새로 만들고 싶습니다. 또한 특정 필드를 선택적으로 복사하고 나머지는 null로두고 싶습니다. 문제를 더 복잡하게 만들기 위해 원본 레코드의 기본 키를 가져와 복사본의 다른 필드 (PreviousId 필드)에 삽입해야합니다.

나는 이것에 대한 쉬운 해결책이 있다고 확신합니다. 나는 그것이 무엇인지 알기에 충분한 TSQL을 모릅니다.

답변:


186

이 시도:


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

지정되지 않은 모든 필드는 기본값 (정의되지 않은 경우 일반적으로 NULL)을 받아야합니다.


2
대박. 매력처럼 작동했습니다. 한번 써보면 너무 뻔 했어요. 감사!!
Kilhoffer

1
열이 거의없는 경우 작동합니다. 열이 20 개 또는 30 개라고 말한 경우에도이 방법을 사용할 수 있지만 어렵습니다. 또한 열을 추가하고 해당 데이터도 복사하고 싶을 때마다이 스크립트에 열을 추가해야합니다. 가장 좋은 방법은 sys 테이블을 사용하여 동적으로 삽입을 생성하는 것입니다.
Jeyara

93

좋아, 나는 그것이 오래된 문제라는 것을 알고 있지만 어쨌든 내 대답을 게시합니다.

이 솔루션이 마음에 듭니다. ID 열만 지정하면됩니다.

SELECT * INTO TempTable FROM MyTable_T WHERE id = 1;
ALTER TABLE TempTable DROP COLUMN id;
INSERT INTO MyTable_T SELECT * FROM TempTable;
DROP TABLE TempTable;

"id"-열은 식별 열이며 내가 지정해야하는 유일한 열입니다. 어쨌든 다른 방법보다 낫습니다. :-)

SQL Server를 사용합니다. 행 1과 2에 " CREATE TABLE"및 " UPDATE TABLE" 를 사용할 수 있습니다 . 음, 그가 원하는 답을 실제로 제공하지 않은 것을 보았습니다. 그는 ID를 다른 열에도 복사하고 싶었습니다. 그러나이 솔루션은 새로운 자동 ID로 복사본을 만드는 데 유용합니다.

Michael Dibbets의 아이디어로 솔루션을 편집합니다.

use MyDatabase; 
SELECT * INTO #TempTable FROM [MyTable] WHERE [IndexField] = :id;
ALTER TABLE #TempTable DROP COLUMN [IndexField]; 
INSERT INTO [MyTable] SELECT * FROM #TempTable; 
DROP TABLE #TempTable;

둘 이상의 열을 ","로 구분하여 삭제할 수 있습니다. : id는 복사하려는 행의 ID로 바꿔야합니다. MyDatabase, MyTable 및 IndexField는 물론 이름으로 바꿔야합니다.


1
이것은 까다 롭습니다. 3 행의 INSERT INTO 중에 올바른 ID를 올바른 행에 복사하고 있는지 어떻게 확인할 수 있습니까?
Erno 2013-02-22

id-column은 내 테이블의 ID 열이므로 값에 대해서는 신경 쓰지 않습니다. "이전"레코드와 동일한 값을 가진 새 레코드를 원합니다.
Jonas

9
의 경우 TempTable사용하는 것이 더 낫지 #TempTable않습니까? 그래서 진정한 임시 테이블입니까?
Jess

3
나는 이것을 다음 형식 use MyDatabase; SELECT * INTO #TempTable FROM [TABLE] WHERE [indexfield] = :id; ALTER TABLE #TempTable DROP COLUMN [indexfield]; INSERT INTO [TABLE] SELECT * FROM #TempTable; DROP TABLE #TempTable;으로 사용하고 있습니다. 이렇게하면 간헐적 인 파일을 디스크에 쓰는 데 지체없이 최대한 빨리 정리됩니다.
Tschallacka

3
당신은 또한 사용할 수 있습니다 $identity당신은 하드 코드에 사용자의 ID 열 이름 싶지 않은 경우
팩터 미스틱

12

나는 당신이 모든 열 이름을 쓰지 않으려 고 노력하고 있다고 생각합니다. SQL Management Studio를 사용하는 경우 테이블과 Script As Insert를 쉽게 마우스 오른쪽 단추로 클릭합니다. 그러면 해당 출력을 사용하여 쿼리를 생성 할 수 있습니다.


10

ID 필드를 제외한 모든 필드를 지정하십시오.

INSERT INTO MyTable (FIELD2, FIELD3, ..., FIELD529, PreviousId)
SELECT FIELD2, NULL, ..., FIELD529, FIELD1
FROM MyTable
WHERE FIELD1 = @Id;

6

다른 개발자가 주기적으로 추가 한 열이있는 테이블에서 단일 스크립트를 사용하려는 동일한 문제가 있습니다. 뿐만 아니라 고객이 모두 현재 버전을 최신 상태로 유지하지 못할 수 있으므로 다양한 버전의 데이터베이스를 지원하고 있습니다.

Jonas의 솔루션을 가져와 약간 수정했습니다. 이렇게하면 행의 복사본을 만든 다음 원래 소스 테이블에 다시 추가하기 전에 기본 키를 변경할 수 있습니다. 이것은 또한 열에 NULL 값을 허용하지 않고 INSERT에 각 열 이름을 지정하지 않아도되는 테이블 작업에 매우 유용합니다.

이 코드는 'ABC'행을 'XYZ'로 복사합니다.

SELECT * INTO #TempRow FROM SourceTable WHERE KeyColumn = 'ABC';
UPDATE #TempRow SET KeyColumn = 'XYZ';
INSERT INTO SourceTable SELECT * FROM #TempRow;
DELETE #TempRow;

삭제가 끝나면 임시 테이블을 삭제하십시오.

DROP TABLE #TempRow;

4

내 대답이 파티에 늦었 음을 압니다. 그러나 내가 해결 한 방식은 모든 답변과 약간 다릅니다.

상황이 발생하여 몇 개의 열을 제외하고 테이블의 행을 복제해야합니다. 그 소수는 새로운 가치를 갖게 될 것입니다. 이 프로세스는 향후 테이블 변경을 자동으로 지원해야합니다. 이는 열 이름을 지정하지 않고 레코드를 복제 함을 의미합니다.

내 접근 방식은

  1. Sys.Columns를 쿼리하여 테이블의 전체 열 목록을 가져오고 where 절에서 건너 뛸 열 이름을 포함합니다.
  2. 열 이름으로 CSV로 변환하십시오.
  3. 빌드 선택 ... 이것을 기반으로 스크립트에 삽입합니다.


declare @columnsToCopyValues varchar(max), @query varchar(max)
SET @columnsToCopyValues = ''

--Get all the columns execpt Identity columns and Other columns to be excluded. Say IndentityColumn, Column1, Column2 Select @columnsToCopyValues = @columnsToCopyValues + [name] + ', ' from sys.columns c where c.object_id = OBJECT_ID('YourTableName') and name not in ('IndentityColumn','Column1','Column2') Select @columnsToCopyValues = SUBSTRING(@columnsToCopyValues, 0, LEN(@columnsToCopyValues)) print @columnsToCopyValues

Select @query = CONCAT('insert into YourTableName (',@columnsToCopyValues,', Column1, Column2) select ', @columnsToCopyValues, ',''Value1'',''Value2'',', ' from YourTableName where IndentityColumn =''' , @searchVariable,'''')

print @query exec (@query)


2
insert into MyTable (uniqueId, column1, column2, referencedUniqueId)
select NewGuid(), // don't know this syntax, sorry
  column1,
  column2,
  uniqueId,
from MyTable where uniqueId = @Id

1

"key"가 PK 필드이고 자동 숫자 인 경우.

insert into MyTable (field1, field2, field3, parentkey)
select field1, field2, null, key from MyTable where uniqueId = @Id

원래 레코드에서 field1 및 field2를 복사하여 새 레코드를 생성합니다.


1

내 테이블에는 100 개의 필드가 있으며 작업을 수행하려면 쿼리가 필요했습니다. 이제 몇 가지 기본 조건부 논리로 원하는 수의 필드를 전환 할 수 있으며 순서 위치에 대해 걱정하지 않아도됩니다.

  1. 아래 테이블 이름을 테이블 이름으로 바꿉니다.

    SQLcolums = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE (TABLE_NAME = 'TABLE-NAME')"
    
    Set GetColumns = Conn.Execute(SQLcolums)
    Do WHILE not GetColumns.eof
    
    colName = GetColumns("COLUMN_NAME")
  2. 원래 ID 필드 이름을 PK 필드 이름으로 바꿉니다.

    IF colName = "ORIGINAL-IDENTITY-FIELD-NAME" THEN ' ASSUMING THAT YOUR PRIMARY KEY IS THE FIRST FIELD DONT WORRY ABOUT COMMAS AND SPACES
        columnListSOURCE = colName 
        columnListTARGET = "[PreviousId field name]"
    ELSE
        columnListSOURCE = columnListSOURCE & colName
        columnListTARGET = columnListTARGET & colName
    END IF
    
    GetColumns.movenext
    
    loop
    
    GetColumns.close    
  3. 테이블 이름을 다시 바꾸십시오 (목표 테이블 이름과 소스 테이블 이름 모두). where조건 수정

    SQL = "INSERT INTO TARGET-TABLE-NAME (" & columnListTARGET & ") SELECT " & columnListSOURCE & " FROM SOURCE-TABLE-NAME WHERE (FIELDNAME = FIELDVALUE)" 
    Conn.Execute(SQL)

0

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

INSERT INTO DENI/FRIEN01P 
SELECT 
   RCRDID+112,
   PROFESION,
   NAME,
   SURNAME,
   AGE, 
   RCRDTYP, 
   RCRDLCU, 
   RCRDLCT, 
   RCRDLCD 
FROM 
   FRIEN01P      

112 대신 DENI / FRIEN01P 테이블에 최대 ID 수를 입력해야합니다.


0

다음은 ASP classic을 사용하여 수행 한 방법이며 위의 답변으로는 제대로 작동하지 못했으며 시스템의 제품을 새 product_id로 복사 할 수 있기를 원했고 다음과 같은 경우에도 작동 할 수 있어야했습니다. 테이블에 더 많은 열을 추가하십시오.

Cn.Execute("CREATE TEMPORARY TABLE temprow AS SELECT * FROM product WHERE product_id = '12345'")
Cn.Execute("UPDATE temprow SET product_id = '34567'")
Cn.Execute("INSERT INTO product SELECT * FROM temprow")
Cn.Execute("DELETE temprow")
Cn.Execute("DROP TABLE temprow")

이것을 완료하기 위해 5 개의 별도 SQL 명령을 실행할 필요가 없다고 생각합니다. 또한 두 번째 명령에서 제품 ID가 34567이어야한다고 결정하는 사람은 누구입니까?
Jeyara

34567은 단지 예입니다. 변수 또는 원하는대로 설정할 수 있습니다. ASP Classic에서이 작업을 수행하는 더 좋은 방법이 있으면 알려주십시오. :)
Daniel Nordh

저장 프로 시저를 작성하여이 모든 것을 한 줄로 실행할 수 있습니다. 또한 일반적으로 PK는 자동 증가 값이었습니다. 따라서 자신에게 할당하는 것은 좋은 생각이 아닙니다.
Jeyara

절차를 어떻게 작성 하시겠습니까? 저를 깨달으십시오. PK? 상품 ID를 의미하는 경우 당사 시스템에서는 판매하는 상점을 기준으로 상품 ID를 사용합니다. 예를 들어 장난감 상점은 모두 상품 번호가 30으로 시작하고 스포츠 상점은 60으로 시작합니다. 또한 공간을 절약하여 예를 들어 동일한 종류의 다른 항목 옆에 기사 ID를 가질 수 있습니다. 말했듯이 이것은 우리 시스템에서 작동하는 내 솔루션이었습니다. 변수를 설정하는 방법은 그다지 중요하지 않으며 대부분의 프로그래머는 변수와 시스템에 무엇이 작동하는지 이해할 것입니다.
Daniel Nordh

PK는 기본 키를 나타냅니다. 귀하의 경우에는 '12345'입니다. 방법을 모르는 경우 Classic ASP에서 stored proc을 사용하는 방법 은 stackoverflow.com/questions/21561657/… 을 참조하십시오 . 이를 위해 모든 것을 하나의 저장된 proc으로 옮기고 '12345'를 매개 변수로 전달하십시오. 당신이하는 방식은 작동하지만 매개 변수가있는 스크립트가 요즘 권장됩니다.
Jeyara
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.