ไม่สามารถแทรกค่าที่ชัดเจนสำหรับคอลัมน์ข้อมูลประจำตัวในตาราง 'ตาราง' เมื่อ IDENTITY_INSERT ถูกตั้งค่าเป็นปิด


361

ฉันมีข้อผิดพลาดด้านล่างเมื่อฉันรันสคริปต์ต่อไปนี้ มีข้อผิดพลาดเกี่ยวกับอะไรและจะแก้ไขได้อย่างไร

Insert table(OperationID,OpDescription,FilterID)
values (20,'Hierachy Update',1)

ข้อผิดพลาด:

เซิร์ฟเวอร์: ข่าวสารเกี่ยวกับ 544, ระดับ 16, สถานะ 1, บรรทัด 1

ไม่สามารถแทรกค่าที่ชัดเจนสำหรับคอลัมน์ข้อมูลประจำตัวในตาราง 'ตาราง' เมื่อ IDENTITY_INSERT ถูกตั้งค่าเป็นปิด


1
ซ้ำที่เป็นไปได้ของข้อผิดพลาด
Himanshu Ahuja

2
@HimanshuAhuja คำถามนี้ (1334012) อายุ 10 ปีที่คุณเชื่อมโยงเพียง 1 ถ้ามีอะไรใหม่กว่านั้นซ้ำกัน แต่ถ้ามองใกล้ ๆ คุณจะเห็นว่ามันแตกต่างกัน (อันใหม่กว่าระบุ IDENTITY_INSERT เป็น ON) โปรดลบธง / ความคิดเห็นของคุณ
jasie

@jasie จะทำเช่นนั้นในขณะที่ฉันจำไม่ได้เมื่อฉันโพสต์ธงนี้
Himanshu Ahuja

คำตอบ:


467

คุณกำลังแทรกค่าสำหรับOperationIdนั่นคือคอลัมน์ข้อมูลประจำตัว

คุณสามารถเปิดการแทรกตัวตนบนตารางเช่นนี้เพื่อให้คุณสามารถระบุค่าตัวตนของคุณเอง

SET IDENTITY_INSERT Table1 ON

INSERT INTO Table1
/*Note the column list is REQUIRED here, not optional*/
            (OperationID,
             OpDescription,
             FilterID)
VALUES      (20,
             'Hierachy Update',
             1)

SET IDENTITY_INSERT Table1 OFF 

14
+1 ตรง - เปิดตัวเลือกเพื่อให้แทรกอย่างชัดเจนบนแล้วใส่แล้วเปิดตัวเลือกOFFอีกครั้ง
marc_s

13
หากคุณต้องการเพิ่มมูลค่าของคุณในคอลัมน์ข้อมูลประจำตัวนี่คือคำตอบของคุณ แต่ในทางกลับกันบางคนได้ตั้งค่าคอลัมน์ให้เพิ่มขึ้นด้วยตัวเองเมื่อแทรก ในกรณีนั้นตารางจะติดตามหมายเลขว่างถัดไปและคุณไม่จำเป็นต้องสร้าง OperationID ด้วยตัวเอง สามารถดึงข้อมูลรหัสใหม่ได้ด้วย SELECT SCOPE_IDENTITY ()
Hakan Winther

15
การปฏิบัติที่เป็นอันตรายไม่แนะนำให้ใช้โดยไม่ต้องบอกว่าทำไมมันเป็นความคิดที่ไม่ดี คำตอบที่น่าสงสารมาก
HLGEM

7
คำตอบที่ดี แต่ให้แน่ใจว่าคุณรู้ว่าคุณกำลังทำอะไรอยู่ สำหรับฉันมันมีประโยชน์ที่จะเพาะฐานข้อมูลที่มีข้อมูลที่คีย์ต่างประเทศจำเป็นต้องตรงกับตารางที่แตกต่างกัน
Berty

2
@UlyssesAlves: ตัวเลือกนี้สามารถเท่านั้นที่จะเปิดสำหรับตารางฐานข้อมูลเดียวกว้าง - ดังนั้นถ้าคุณปล่อยมันลงบนโต๊ะหนึ่งคุณจะไม่สามารถที่จะเคยใช้มันสำหรับตารางอื่น นอกจากนี้: ไม่ใช่ตัวเลือกที่ควรเปิด - ตามค่าเริ่มต้นคุณควรปล่อยให้ SQL Server จัดการกับค่าตัวตน - นี่เป็นเพียงมาตรการสุดท้ายสำหรับกรณีที่เฉพาะเจาะจงมาก - ไม่ใช่ตัวเลือกที่มีวัตถุประสงค์ทั่วไปเพื่อเปิดหรือปิดที่ เวลาว่างของคุณ ...
marc_s

61

อย่าให้คุณค่ากับ OperationID เพราะจะถูกสร้างขึ้นโดยอัตโนมัติ ลองนี้:

Insert table(OpDescription,FilterID) values ('Hierachy Update',1)

5
นี่คือคำตอบที่ถูกต้องหากคุณต้องการสร้าง OperationID อัตโนมัติ
shaijut

46

เพียงแค่ถ้าคุณได้รับข้อผิดพลาดนี้บนเซิร์ฟเวอร์ SQL ให้เรียกใช้แบบสอบถามนี้

SET IDENTITY_INSERT tableName ON

สิ่งนี้ใช้งานได้เพียงตารางเดียวของฐานข้อมูล เช่นถ้าชื่อตารางเป็นนักเรียนแบบสอบถามจะมีลักษณะเช่นนี้ SET IDENTITY_INSERT student ON

หากคุณได้รับข้อผิดพลาดนี้ในเว็บแอปพลิเคชันของคุณหรือคุณใช้เฟรมเวิร์กเอนทิตีก่อนอื่นให้รันเคียวรีนี้บนเซิร์ฟเวอร์ SQL และอัพเดตโมเดลเอนทิตี.edmx fileของคุณ( ) และสร้างโครงการของคุณและข้อผิดพลาดนี้จะได้รับการแก้ไข


เป็นกรณีในเว็บแอป MVC ของฉันกับ EF และฉันเพิ่งลบแบบจำลองจาก. edmx และเพิ่มอีกครั้ง (คลิกขวาอัปเดตโมเดลจากฐานข้อมูล) และทำความสะอาดและสร้างโครงการที่เหมาะกับฉันแล้ว ขอบคุณ @Umang Patwa
Ishwor Khanal

42

ระมัดระวังการตั้งค่า IDENTITY_INSERT เป็นเปิด นี่เป็นแนวปฏิบัติที่ไม่ดีเว้นแต่ฐานข้อมูลจะอยู่ในโหมดการบำรุงรักษาและตั้งค่าเป็นผู้ใช้รายเดียว สิ่งนี้มีผลต่อการแทรกของคุณไม่เพียง แต่กับคนอื่นที่พยายามเข้าถึงตาราง

เหตุใดคุณจึงพยายามใส่ค่าลงในฟิลด์ตัวตน


5
ส่งผลในทางใด? นี่เป็นตัวเลือกระดับเซสชันไม่ใช่คุณสมบัติของตาราง
Martin Smith

5
การซิงค์ข้อมูลครั้งเดียวระหว่างสองฐานข้อมูลที่คุณต้องการรักษาความสัมพันธ์ ตัวอย่างเช่นฉันใช้มันเพื่อดึงสคีมาผลิตภัณฑ์ของฉันจากฐานข้อมูลหนึ่งไปยังอีก
NSjonas

1
@NSjonas นั่นจะเป็นการใช้ประโยชน์จากชุด Identity _insert table1 ON ฉันเคยเห็นคนที่ต้องการใช้สิ่งนี้เพื่อทำอะไรบางอย่างจากแอปพลิเคชันที่ควรทำด้วยการแทรกง่าย ๆ และอนุญาตให้มีการสร้างตัวตน
HLGEM

2
คำถามคือ "คุณสามารถระบุได้ว่ามันคืออะไรและจะแก้ไขได้อย่างไร?" คำตอบของคุณคือความคิดเห็นที่ทำให้เกิดคำเตือนและคำถามอื่นแทนที่จะเป็นคำตอบที่เหมาะสมที่จะแก้ไขปัญหา
คุณภาพ

ใช่ไม่ได้ใส่ค่าในคีย์หลัก
doflamingo

22

โดยทั่วไปมีวิธีการบันทึก INSERT 2 วิธีที่แตกต่างกันโดยไม่มีข้อผิดพลาด:

1) เมื่อตั้งค่า IDENTITY_INSERT แล้ว รหัสหลัก"ID" จะต้องไม่ปรากฏในปัจจุบัน

2) เมื่อตั้งค่า IDENTITY_INSERT รหัส"คีย์" หลักจะต้องมีอยู่ในปัจจุบัน

ตามตัวอย่างต่อไปนี้จากตารางเดียวกันที่สร้างด้วยคีย์หลักตัวตน:

CREATE TABLE [dbo].[Persons] (    
    ID INT IDENTITY(1,1) PRIMARY KEY,
    LastName VARCHAR(40) NOT NULL,
    FirstName VARCHAR(40)
);

1) ในตัวอย่างแรกคุณสามารถแทรกระเบียนใหม่ลงในตารางโดยไม่ได้รับข้อผิดพลาดเมื่อ IDENTITY_INSERT ปิดอยู่ คีย์หลัก"รหัส" ต้องไม่เป็นปัจจุบันจาก "INSERT INTO" งบและค่า ID ที่ไม่ซ้ำกันจะถูกเพิ่มโดยอัตโนมัติ: หากมี ID จาก INSERT ในกรณีนี้คุณจะได้รับข้อผิดพลาด "ไม่สามารถแทรกค่าที่ชัดเจนสำหรับการระบุคอลัมน์ในตาราง ... "

SET IDENTITY_INSERT [dbo].[Persons] OFF;
INSERT INTO [dbo].[Persons] (FirstName,LastName)
VALUES ('JANE','DOE'); 
INSERT INTO Persons (FirstName,LastName) 
VALUES ('JOE','BROWN');

ผลลัพธ์ของตาราง [dbo] [บุคคล] จะเป็น:

ID    LastName   FirstName
1     DOE        Jane
2     BROWN      JOE

2) ในตัวอย่างที่สองคุณสามารถแทรกระเบียนใหม่ลงในตารางโดยไม่ได้รับข้อผิดพลาดเมื่อ IDENTITY_INSERT เปิด คีย์หลัก"ID" ต้องแสดงอยู่ในคำสั่ง "INSERT INTO" ตราบใดที่ค่า ID ยังไม่มีอยู่ : หาก ID ไม่ได้อยู่ใน INSERT ในกรณีนี้คุณจะได้รับข้อผิดพลาด "ค่าที่ชัดเจนจะต้องเป็น ระบุไว้สำหรับตารางคอลัมน์ข้อมูลประจำตัว ... "

SET IDENTITY_INSERT [dbo].[Persons] ON;
INSERT INTO [dbo].[Persons] (ID,FirstName,LastName)
VALUES (5,'JOHN','WHITE'); 
INSERT INTO [dbo].[Persons] (ID,FirstName,LastName)
VALUES (3,'JACK','BLACK'); 

ผลลัพธ์ของตาราง [dbo] [บุคคล] จะเป็น:

ID    LastName   FirstName
1     DOE        Jane
2     BROWN      JOE
3     BLACK      JACK
5     WHITE      JOHN

2
บวกกับการอธิบายการทำงานของธง บันทึกวันของฉัน Superman
John

20

ในเอนทิตีของคุณสำหรับตารางนั้นให้เพิ่มแอDatabaseGeneratedททริบิวด้านบนคอลัมน์ที่มีการตั้งค่าการแทรกเอกลักษณ์

ตัวอย่าง:

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int TaskId { get; set; }

เป็นเรื่องจริง แต่ฉันต้องการคำตอบสำหรับ EF :-) ถึงกระนั้นมันก็ไม่เหมาะสมกับ OP ที่อาจไม่เคยใช้หรืออาจพบว่าเป็น EF
Auspex

ไม่ว่าในกรณีใดคำตอบนั้นไม่ถูกต้อง มีการระบุเอนทิตีของฉันด้วยDatabaseGeneratedOption.Identityและฉันยังคงได้รับข้อผิดพลาด มันเป็นความผิดของตัวเองฉันใส่หลอก ID ในแถวใหม่เพื่อแยกพวกเขาออกจากกันบนหน้าเว็บของฉันและฉันหวังว่าจะลบล้างพวกเขาก่อนที่insertจะเพียงพอ
Auspex

13

คุณก็สามารถใช้คำสั่งนี้ตัวอย่างเช่นถ้าชื่อตารางของคุณเป็นของโรงเรียน ก่อนที่จะแทรกตรวจสอบให้แน่ใจว่า identity_insert ตั้งค่าเป็น ONและหลังจากแทรกแบบสอบถามให้ปิด identity_insert

SET IDENTITY_INSERT School ON
/*
  insert query
  enter code here
*/
SET IDENTITY_INSERT School OFF

1
คุณสามารถขยายคำตอบของคุณเล็กน้อยเพื่อรวมคำอธิบายของคำสั่งทำไมมันได้ผลและมันมีผลอย่างไร
gareththegeek

@gareththegeek ใช่สำหรับคอลัมน์ข้อมูลประจำตัวคุณต้องทำให้แน่ใจว่าได้ทำการแทรกข้อมูล

6

หากคุณกำลังใช้ liquibase เพื่ออัปเดต SQL Server ของคุณคุณน่าจะลองใส่คีย์บันทึกลงในฟิลด์ autoIncrement โดยการลบคอลัมน์ออกจากการแทรกสคริปต์ของคุณควรจะทำงาน

<changeSet id="CREATE_GROUP_TABLE" >
    <createTable tableName="GROUP_D">
        <column name="GROUP_ID" type="INTEGER" autoIncrement="true">
            <constraints primaryKey="true"/>
        </column>
    </createTable>
</changeSet>

<changeSet id="INSERT_UNKNOWN_GROUP" >
    <insert tableName="GROUP_D">    

        <column name="GROUP_ID" valueNumeric="-1"/>
 ...
    </insert>
</changeSet>

4

มี OperationId ที่ระบุไว้ล่วงหน้าในการค้นหาของคุณซึ่งไม่ควรอยู่ที่นั่นเนื่องจากเป็นการเพิ่มอัตโนมัติ

Insert table(OperationID,OpDescription,FilterID)
values (20,'Hierachy Update',1)

ดังนั้นคำถามของคุณจะเป็น

Insert table(OpDescription,FilterID)
values ('Hierachy Update',1)

3

อีกสถานการณ์หนึ่งคือการตรวจสอบว่าคีย์หลักเป็นชื่อเดียวกันกับคลาสของคุณโดยที่ความแตกต่างเพียงอย่างเดียวคือคีย์หลักของคุณมี 'ID' ต่อท้ายหรือเพื่อระบุ [คีย์] บนคีย์หลักที่ไม่เกี่ยวข้องกับวิธีการ ชั้นมีชื่อ


2
  1. สิ่งนี้เกิดขึ้นเมื่อคุณมีคอลัมน์ (คีย์หลัก) ที่ไม่ได้ตั้งค่าเป็นตัวตนเป็นจริงใน SQL และคุณไม่ผ่านค่าที่ชัดเจนในระหว่างการแทรก จะใช้เวลาแถวแรกจากนั้นคุณจะไม่สามารถแทรกแถวที่สองข้อผิดพลาดจะปรากฏขึ้น สิ่งนี้สามารถแก้ไขได้โดยเพิ่มรหัสบรรทัดนี้[DatabaseGenerated(DatabaseGeneratedOption.Identity)]ในคอลัมน์ PrimaryKey ของคุณและตรวจสอบให้แน่ใจว่าได้ตั้งค่าเป็นประเภทข้อมูลint intหากคอลัมน์เป็นคีย์หลักและตั้งค่าเป็น IsIDentity เป็นจริงใน SQL ไม่จำเป็นต้องใช้รหัสบรรทัดนี้[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  2. สิ่งนี้จะเกิดขึ้นเมื่อคุณมีคอลัมน์ที่ไม่ใช่คีย์หลักใน SQL ที่ตั้งค่าเป็น Is Identity ให้เป็น True และใน EF ของคุณคุณไม่ได้เพิ่มบรรทัดของรหัสนี้ [DatabaseGenerated(DatabaseGeneratedOption.Identity)]

ขอบคุณนี่คือการแก้ไขที่ใช้เวลาหลายชั่วโมงในการค้นหา
Vishav Premlall

2

ทางออกที่ดีที่สุดคือการใช้คำอธิบายประกอบGeneratedValue(strategy = ...)คือ

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column ...
private int OperationID;

มันบอกว่าคอลัมน์นี้สร้างขึ้นโดยฐานข้อมูลโดยใช้กลยุทธ์การระบุตัวตนและคุณไม่จำเป็นต้องดูแล - ฐานข้อมูลจะทำ


1

หากคุณประสบปัญหานี้ขณะใช้ sql-server กับ sequelize-typescript npm ตรวจสอบให้แน่ใจว่าได้เพิ่มลง@AutoIncrementในคอลัมน์ ID:

  @PrimaryKey
  @AutoIncrement
  @Column
  id!: number;

0

และถ้าคุณใช้ Oracle SQL Developer เพื่อเชื่อมต่ออย่าลืมเพิ่ม / sqldev: stmt /

/ sqldev: stmt / set identity_insert TABLE on;


เห็นได้ชัดว่าไม่ใช่กรณีนี้คำถามมีแท็ก "sql-server"
DanielV

0

ฉันไม่แน่ใจว่าการใช้งานสำหรับ "แทรกตาราง" คืออะไร แต่ถ้าคุณแค่พยายามแทรกค่าบางค่าลอง:

Insert Into [tablename] (OpDescription,FilterID)
values ('Hierachy Update',1);

ฉันมีข้อความแสดงข้อผิดพลาดเหมือนกัน แต่ฉันคิดว่ามันน่าจะใช้ได้ ID ควรเพิ่มอัตโนมัติโดยอัตโนมัติตราบเท่าที่เป็นคีย์หลัก


0

ฉันแก้ไขปัญหานี้ด้วยการสร้างวัตถุใหม่ทุกครั้งที่ฉันต้องการเพิ่มอะไรลงในฐานข้อมูล


0

โปรดทราบว่าถ้าคุณกำลังจะปิดแต่ละบรรทัดกับ;ที่SET IDENTITY_INSERT mytable ONคำสั่งจะไม่ถือสำหรับบรรทัดต่อไปนี้

เช่น
แบบสอบถามเช่น

SET IDENTITY_INSERT mytable ON;
INSERT INTO mytable (VoucherID, name) VALUES (1, 'Cole');

ให้ข้อผิดพลาด
Cannot insert explicit value for identity column in table 'mytable' when IDENTITY_INSERT is set to OFF.

แต่แบบสอบถามเช่นนี้จะใช้งานได้:

SET IDENTITY_INSERT mytable ON
INSERT INTO mytable (VoucherID, name) VALUES (1, 'Cole')
SET IDENTITY_INSERT mytable OFF;

ดูเหมือนว่าSET IDENTITY_INSERTคำสั่งจะมีไว้สำหรับการทำธุรกรรมเท่านั้นและ;จะหมายถึงการสิ้นสุดของการทำธุรกรรม


-1

ปัญหาที่เพิ่มขึ้นจากการใช้ DBContext ที่ไม่ได้พิมพ์หรือ DBSet ถ้าคุณใช้ส่วนต่อประสานและใช้วิธีการบันทึกการเปลี่ยนแปลงด้วยวิธีทั่วไป

หากเป็นกรณีของคุณฉันขอเสนอให้พิมพ์ DBContex เป็นอย่างยิ่ง

MyDBContext.MyEntity.Add(mynewObject)

จากนั้น.Savechangesจะทำงาน


-1

เพียงลบตารางที่ลากไปยังไฟล์. dbml ของคุณแล้วลากอีกครั้ง จากนั้นคลีนโซลูชัน> สร้างโซลูชันใหม่> สร้างโซลูชัน

นั่นคือสิ่งที่ทำงานให้ฉัน

ฉันไม่ได้สร้างตารางด้วยตัวเองฉันใช้ VS และ SSMS ฉันติดตามลิงค์นี้เพื่อระบุตัวตน ASP.NET: https://docs.microsoft.com/en-us/aspnet/identity/overview/getting-started/ เพิ่ม-aspnet เอกลักษณ์ไปใช้ที่ว่างเปล่าหรือที่มีอยู่บนเว็บรูปแบบโครงการ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.