테이블의 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.