테이블의 ID 열에 대한 명시 적 값은 열 목록이 사용되고 IDENTITY_INSERT가 ON 인 경우에만 지정할 수 있습니다.


187

이 쿼리를 수행하려고합니다.

INSERT INTO dbo.tbl_A_archive
  SELECT *
  FROM SERVER0031.DB.dbo.tbl_A

하지만 내가 달린 후에도

set identity_insert dbo.tbl_A_archive on

이 오류 메시지가 나타납니다

테이블 'dbo.tbl_A_archive'의 식별 컬럼에 대한 명시 적 값은 컬럼 목록이 사용되고 IDENTITY_INSERT가 ON 인 경우에만 지정할 수 있습니다.

tbl_A행과 너비가 큰 테이블입니다. 즉, 많은 열이 있습니다. 모든 열을 수동으로 입력하지 않아도됩니다. 이 기능을 작동 시키려면 어떻게해야합니까?


나는 이미 연결된 서버를 설정했습니다!
jhowe

4
문제가 아니었다 내가 테이블 스키마 변경 될 때까지 나는 "Y는 * 선택 X로 삽입"를 제외하고도이 문제가있어
FistOfFury

답변:


81

요약

열 목록을 사용하지 않으면 SQL Server에서 ID 열에 명시 적 값을 삽입 할 수 없습니다. 따라서 다음과 같은 옵션이 있습니다.

  1. 열 목록 만들기 (수동 또는 도구 사용, 아래 참조)

또는

  1. ID가 아닌tbl_A_archive 일반 열에 ID 열을 작성 하십시오. 테이블이 아카이브 테이블이고 항상 ID 열에 대한 명시 적 값을 지정하는 경우 ID 열이 필요한 이유는 무엇입니까? 대신 일반 int를 사용하십시오.

솔루션 1에 대한 세부 사항

대신에

SET IDENTITY_INSERT archive_table ON;

INSERT INTO archive_table
  SELECT *
  FROM source_table;

SET IDENTITY_INSERT archive_table OFF;

당신은 쓸 필요가

SET IDENTITY_INSERT archive_table ON;

INSERT INTO archive_table (field1, field2, ...)
  SELECT field1, field2, ...
  FROM source_table;

SET IDENTITY_INSERT archive_table OFF;

field1, field2, ...당신의 테이블에있는 모든 컬럼의 이름을 포함. 해당 열 목록을 자동 생성하려면 Dave의 답변 또는 Andomar의 답변을 살펴보십시오 .


솔루션 2에 대한 세부 사항

불행히도, ID int 열의 유형을 "identity int"열로 "변경"하는 것은 불가능합니다. 기본적으로 다음과 같은 옵션이 있습니다.

  • 아카이브 테이블에 아직 데이터가없는 경우 열을 삭제하고 ID가없는 새 열을 추가하십시오.

또는

  • SQL Server Management Studio를 사용 하여 보관 테이블에있는 ID 열의 Identity Specification/ (Is Identity)속성을 로 설정하십시오 No. 씬 뒤에는 테이블을 다시 작성하고 기존 데이터를 복사하는 스크립트가 작성되므로 Tools/ Options/ Designers/ Table and Database Designers/ 설정을 해제해야합니다 Prevent saving changes that require table re-creation.

또는


1
최종 해결책 : 열에 "IDENTITY (1, 1)"또는 이와 유사한 것이 있으면 임시로 제거해야합니다.
Aleksandr Khomenko

1
@AleksandrKhomenko : 그렇습니다. "정상적인 ( 정체되지 않은 ) int 열을 만드십시오" 라는 의미 입니다.
Heinzi

1
혼란을 드려 죄송합니다. 나는 실제로 자동 증가 속성도 제거해야한다는 것을 의미했습니다 . SQL-Server의 경우 "IDENTITY (1, 1)"을 호출합니다. 귀하의 답변은 전적으로 옳습니다. 그러나 MySQL과 오라클이 또 다른 명령이 있습니다 (그리고 비 명백한 도착에서 찾아보세요 w3schools.com/sql/sql_autoincrement.asp )
알렉산드르 Khomenko

2
이것은 상세하지 않다. 나는 그것이 어떤 사람들에게는 썩을지도 모른다는 것을 이해하지만 그것은 다른 사람들에게는 말도 안됩니다
DJ.

1
@ DJ : 나는 약간의 세부 사항을 추가했습니다.
Heinzi

332
SET IDENTITY_INSERT tableA ON

INSERT 문에 대한 열리스트를 작성해야합니다.

INSERT Into tableA ([id], [c2], [c3], [c4], [c5] ) 
SELECT [id], [c2], [c3], [c4], [c5] FROM tableB

"INSERT Into tableA SELECT ........"

SET IDENTITY_INSERT tableA OFF

17
+1 ... 쿼리의 SELECT 절에 명시 적 열만 필요합니다. 쿼리의 INSERT 절에 별표를 표시 할 수 있습니다.
MacGyver

8
... 대상에 ID 열이없고 소스 테이블에 ID 열이없는 경우
MacGyver

1
이 답변은 SET IDENTITY_INSERT
Marty

4
+1 매력처럼 작동합니다! 그러나 "조회의 INSERT 절에 별표를 표시 할 수 있습니다"는 작동하지 않습니다.
Shai Alon

1
select 절의 열이 대상 테이블과 일치하지 않으면이 오류가 발생했습니다. 이를 확인하면서 삽입물이 저에게
Jose

39

그냥 테이블을 마우스 오른쪽 버튼으로 클릭 - 당신은 SQL Server Management Studio를 사용하는 경우, 당신은 열 목록을 직접 입력 할 필요가 없습니다 개체 탐색기 를 선택 으로 스크립트 표 -> 에 SELECT -> 새 쿼리 편집기 창 .

그렇지 않은 경우 이와 유사한 쿼리가 시작점으로 도움이됩니다.

SELECT SUBSTRING(
    (SELECT ', ' + QUOTENAME(COLUMN_NAME)
        FROM INFORMATION_SCHEMA.COLUMNS
        WHERE TABLE_NAME = 'tbl_A'
        ORDER BY ORDINAL_POSITION
        FOR XML path('')),
    3,
    200000);

2
변수로 선택하여 동적 SQL 쿼리에서 사용할 수 있습니다. 당신은 내 하루를 구했습니다. 고마워요!
Pawel Cioch


와. 필자는 동적으로 쿼리를 작성하기 위해 필사적으로 이것을 찾고있었습니다. 이걸보고 놀랐습니다. 고마워 친구
Yasin Bilir

24

Heinzi의 답변에 동의하십시오. 첫 번째 두 번째 옵션의 경우 테이블에 쉼표로 구분 된 열 목록을 생성하는 쿼리가 있습니다.

select name + ', ' as [text()] 
from sys.columns 
where object_id = object_id('YourTable') 
for xml path('')

큰 테이블의 경우 많은 타이핑 작업을 저장할 수 있습니다. :)


@ 감사합니다, 정말 도움이됩니다. :)
Chirag Thakar

때로는 실용적인 솔루션이 필요합니다. 감사합니다!
Tobias Feil

15

"아카이브"테이블이 기본 테이블의 정확한 사본이되어야한다면 ID가 식별 열이라는 사실을 제거하는 것이 좋습니다. 그렇게하면 삽입 할 수 있습니다.

또는 다음 명령문으로 테이블에 대한 ID 삽입을 허용하고 허용하지 않을 수 있습니다.

SET IDENTITY_INSERT tbl_A_archive ON
--Your inserts here
SET IDENTITY_INSERT tbl_A_archive OFF

마지막으로 ID 열이 그대로 작동 해야하는 경우 언제든지 저장된 proc을 실행할 수 있습니다.

sp_columns tbl_A_archive 

그러면 테이블의 모든 열이 반환되어 쿼리에 잘라 붙여 넣을 수 있습니다. (이것은 거의 항상 *를 사용하는 것보다 낫습니다)


11

SQL 문의 경우 열 목록도 지정해야합니다. 예를 들어.

INSERT INTO tbl (idcol1,col2) VALUES ( value1,value2)

대신에

INSERT INTO tbl VALUES ( value1,value2)

2
OP의 진술은 그렇지 않다. INSERT INTO 뒤에 SELECT 문이 오는 경우 VALUES는 필요하지 않습니다. 답을 수정하거나 제거하십시오.
게리

4

둘 다 작동하지만 # 1을 사용하여 여전히 오류가 발생하면 # 2로 이동하십시오.

1)

SET IDENTITY_INSERT customers ON
GO
insert into dbo.tbl_A_archive(id, ...)
SELECT Id, ...
FROM SERVER0031.DB.dbo.tbl_A

2)

SET IDENTITY_INSERT customers ON
GO
insert into dbo.tbl_A_archive(id, ...)
VALUES(@Id,....)

4
OP가 여러 레코드를 삽입하는 경우 실제로 진행되지 않습니다. "tbl_A는 행과 너비가 큰 테이블입니다. 즉, 많은 열이 있습니다. 모든 열을 수동으로 입력하지 않아도됩니다."
Gary

4

이 질문에 언급 된 솔루션의 Select 문에 대한 모든 열 이름을 쉼표로 구분 된 목록에 채우려면 여기의 대부분의 응답보다 조금 덜 장황하므로 다음 옵션을 사용합니다. 그러나 대부분의 응답은 여전히 ​​완벽히 수용 가능합니다.

1)

SELECT column_name + ',' 
FROM   information_schema.columns 
WHERE  table_name = 'YourTable'

2) SQL Server SSMS가있는 경우 열을 만드는 가장 간단한 방법 일 것입니다.

1) 개체 탐색기에서 테이블로 이동하여 테이블 이름 왼쪽의 +를 클릭하거나 테이블 이름을 두 번 클릭하여 하위 목록을 엽니 다.

2) 열 하위 폴더를 기본 쿼리 영역으로 끌어서 전체 열 목록을 자동으로 붙여 넣습니다.


3

ID 열이있는 경우 삽입 할 열 이름을 지정해야합니다. 따라서 명령은 다음과 같습니다.

SET IDENTITY_INSERT DuplicateTable ON

INSERT Into DuplicateTable ([IdentityColumn], [Column2], [Column3], [Column4] ) 
SELECT [IdentityColumn], [Column2], [Column3], [Column4] FROM MainTable

SET IDENTITY_INSERT DuplicateTable OFF

테이블에 많은 열이있는 경우이 명령을 사용하여 해당 열 이름을 가져옵니다.

SELECT column_name + ','
FROM   information_schema.columns 
WHERE  table_name = 'TableName'
for xml path('')

(마지막 쉼표 ( ',')를 제거한 후) 과거 열 이름을 복사하십시오.


3

이 작동합니다. 방금 문제가 발생했습니다.

SET IDENTITY_INSERT dbo.tbl_A_archive ON;
INSERT INTO     dbo.tbl_A_archive (IdColumn,OtherColumn1,OtherColumn2,...)
SELECT  *
FROM        SERVER0031.DB.dbo.tbl_A;
SET IDENTITY_INSERT dbo.tbl_A_archive OFF;

불행히도 ID를 지정하는 레코드를 삽입하려면 ID 열을 포함하는 열 목록이 필요합니다. 그러나 SELECT에 열을 나열하지 않아도됩니다. @Dave Cluderay가 제안 했듯이 복사하여 붙여 넣을 수있는 형식이 지정된 목록이 생성됩니다 (200000 자 미만인 경우).

인스턴스 간을 전환하기 때문에 USE를 추가했습니다.

USE PES
SELECT SUBSTRING(
    (SELECT ', ' + QUOTENAME(COLUMN_NAME)
        FROM INFORMATION_SCHEMA.COLUMNS
        WHERE TABLE_NAME = 'Provider'
        ORDER BY ORDINAL_POSITION
        FOR XML path('')),
    3,
    200000);

3
SET IDENTITY_INSERT tableA ON

INSERT Into tableA ([id], [c2], [c3], [c4], [c5] ) 
SELECT [id], [c2], [c3], [c4], [c5] FROM tableB

이건 아니야

INSERT INTO tableA
SELECT * FROM tableB

SET IDENTITY_INSERT tableA OFF

2

이 코드 스 니펫은 ID 기본 키 열이 ON 일 때 테이블에 삽입하는 방법을 보여줍니다.

SET IDENTITY_INSERT [dbo].[Roles] ON
GO
insert into Roles (Id,Name) values(1,'Admin')
GO
insert into Roles (Id,Name) values(2,'User')
GO
SET IDENTITY_INSERT [dbo].[Roles] OFF
GO

1

저장 프로 시저를 통해 한 테이블에서 다른 테이블로 값을 삽입하려는 경우. 나는 이것이것을 사용 했는데, 후자는 Andomar의 대답과 거의 같습니다.

CREATE procedure [dbo].[RealTableMergeFromTemp]
    with execute as owner
AS
BEGIN
BEGIN TRANSACTION RealTableDataMerge
SET XACT_ABORT ON

    DECLARE @columnNameList nvarchar(MAX) =
     STUFF((select ',' + a.name
      from sys.all_columns a
      join sys.tables t on a.object_id = t.object_id 
       where t.object_id = object_id('[dbo].[RealTable]') 
    order by a.column_id
    for xml path ('')
    ),1,1,'')

    DECLARE @SQLCMD nvarchar(MAX) =N'INSERT INTO [dbo].[RealTable] (' + @columnNameList + N') SELECT * FROM [#Temp]'

    SET IDENTITY_INSERT [dbo].[RealTable] ON;
    exec(@sqlcmd)
    SET IDENTITY_INSERT [dbo].[RealTable] OFF

COMMIT TRANSACTION RealTableDataMerge
END

GO

0

자동 증분 속성이있는 하나 이상의 열이 있거나 해당 속성의 값이 제약 조건으로 계산됩니다. 해당 열을 수정하려고합니다.

이를 해결하는 두 가지 방법이 있습니다. 1) 다른 열을 명시 적으로 언급하고 해당 값만 설정하면 PrimaryKey 또는 자동 증분 열 값이 자동으로 설정됩니다.

2) INDENTITY_INSERT를 켠 다음 삽입 쿼리를 실행하여 IDENTITY_INSERT를 끌 수 있습니다.

제안 : 첫 단계는보다 적합하고 효율적인 접근 방법이므로 첫 번째 단계를 따르십시오.

자세한 내용은 SQL-helper에 대한이 기사를 읽으십시오 .


0

레코드를 선택하는 테이블의 열 이름, 데이터 유형 및 순서가 대상 테이블과 정확히 일치하는지 확인하십시오. 대상 테이블에 첫 번째 열로 식별 열이 있고 소스 테이블에는없는 점만 다릅니다.

"INSERT INTO table_Dest SELECT * FROM table_source_linked_server_excel"을 실행할 때 비슷한 문제가 발생했습니다. 테이블에는 115 개의 열이 있습니다.

Excel (연결 된 서버로)에서 데이터베이스의 테이블로 데이터를로드하는 두 개의 테이블이 있습니다. 데이터베이스 테이블에서 소스 Excel에없는 'id'라는 ID 열을 추가했습니다. 한 테이블에서 쿼리가 성공적으로 실행되고 다른 테이블에서 "테이블의 ID 열에 대한 명시 적 값은 열 목록이 사용되고 IDENTITY_INSERT가 ON SQL Server 인 경우에만 지정할 수 있습니다"라는 오류가 발생합니다. 시나리오가 두 쿼리 모두에 대해 정확히 동일했기 때문에 이것은 당혹 스럽습니다. 그래서 이것에 대해 조사하고 내가 찾은 것은 INSERT INTO 오류가 발생한 쿼리에서 .. SELECT * :

  1. 값이 정확하지만 소스 테이블의 일부 열 이름이 수정되었습니다.
  2. SELECT *에 의해 선택된 실제 데이터 열 외에 몇 가지 추가 열이있었습니다. 소스 Excel 테이블 (링크 된 서버 아래)에서 "스크립트 테이블을> 선택 대상> 새 쿼리 창"옵션을 사용하여이를 발견했습니다. 데이터가없는 Excel의 마지막 열 바로 뒤에 숨겨진 열이 하나있었습니다. 소스 Excel 테이블에서 해당 열을 삭제하고 저장했습니다.

위의 두 가지 사항을 변경 한 후 INSERT INTO ... SELECT *에 대한 쿼리가 성공적으로 실행되었습니다. 대상 테이블의 ID 열이 예상대로 삽입 된 각 행에 대한 ID 값을 생성했습니다.

따라서 대상 테이블에 소스 테이블에없는 ID 열이있을 수 있지만 소스와 대상의 이름, 데이터 유형 및 열 순서가 정확히 동일한 경우 INSERT INTO .. ​​SELECT *가 성공적으로 실행됩니다.

그것이 누군가를 돕기를 바랍니다.


-1

이 오류는 테이블 정의의 열 수와 삽입 쿼리의 열 수의 불일치로 인해 발생한다고 생각합니다. 또한 열의 길이는 입력 된 값으로 생략됩니다. 따라서이 문제를 해결하기 위해 테이블 ​​정의를 검토하십시오.


나를 위해 일했습니다 : 디자인에서 테이블에 열을 추가하는 것을 잊었습니다. 다른 답변을 시도하기 전에 먼저 확인해야합니다.
Exel Gamboa
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.