Nie można wstawić wyraźnej wartości dla kolumny tożsamości w tabeli „table”, gdy IDENTITY_INSERT jest ustawiony na OFF

361

Występuje następujący błąd podczas wykonywania następującego skryptu. Na czym polega błąd i jak go rozwiązać?

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

Błąd:

Serwer: Msg 544, poziom 16, stan 1, wiersz 1

Nie można wstawić wyraźnej wartości dla kolumny tożsamości w tabeli „table”, gdy IDENTITY_INSERT jest ustawiony na OFF.

Martin Clayton
źródło
2
@HimanshuAhuja To pytanie (1334012) ma 10 lat, to pytanie, które połączyłeś tylko 1. Jeśli coś, to nowsze jest duplikatem. Ale przy bliższym przyjrzeniu się zauważysz, że się różnią (nowszy określa IDENTITY_INSERT jako ON). Usuń flagę / komentarz.
jasie
@jasie zrobi to, bo nie pamiętam, kiedy zamieściłem tę flagę
Himanshu Ahuja

Odpowiedzi:

467

Wstawiasz wartości, OperationIdponieważ jest to kolumna tożsamości.

Możesz włączyć wstawianie tożsamości w tabeli w ten sposób, aby określić własne wartości tożsamości.

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 
pjp
źródło
14
+1 dokładnie - włącz opcję, aby umożliwić wyraźne wstawki ON , a następnie włóż i włącz opcję OFF ponownie
marc_s
13
Jeśli naprawdę chcesz dodać swoją wartość do kolumny tożsamości, to jest twoja odpowiedź, ale z drugiej strony ktoś ustawił, by kolumna sama się zwiększała przy wstawianiu. W takim przypadku tabela będzie śledzić następny bezpłatny numer i nie musisz samodzielnie generować identyfikatora operacji. Nowy identyfikator można pobrać za pomocą SELECT SCOPE_IDENTITY ().
Hakan Winther
15
Niebezpieczna praktyka, nie zaleca się korzystania z niej bez zastrzeżeń, dlaczego jest to zły pomysł. Bardzo zła odpowiedź.
HLGEM
7
dobra odpowiedź, ale upewnij się, że wiesz, co robisz. Dla mnie przydatne jest zaszczepienie bazy danych danymi, w których klucze obce muszą się zgadzać w różnych tabelach
Berty
2
@UlyssesAlves: tę opcję można włączyć tylko dla jednej tabeli dla całej bazy danych - więc jeśli pozostawisz ją dla jednej tabeli, nigdy nie będziesz mógł jej użyć dla innej tabeli. Ponadto: nie jest to opcja, którą należy pozostawić włączoną - domyślnie należy pozwolić programowi SQL Server obsługiwać wartości tożsamości - jest to przeznaczone wyłącznie jako środek ostateczny w bardzo szczególnych przypadkach - nie jest to opcja ogólnego przeznaczenia, która może zostać włączona lub wyłączona twój wolny czas ...
marc_s
61

nie przypisuj wartości do OperationID, ponieważ zostanie on wygenerowany automatycznie. Spróbuj tego:

Insert table(OpDescription,FilterID) values ('Hierachy Update',1)
Wael Dalloul
źródło
5
to poprawna odpowiedź, jeśli chcesz automatycznie wygenerować OperationID
shaijut
46

Po prostu jeśli otrzymujesz ten błąd na serwerze SQL, uruchom to zapytanie

SET IDENTITY_INSERT tableName ON

działa tylko jedna tabela danych, np. jeśli nazwa tabeli to student, zapytanie wygląda następująco SET IDENTITY_INSERT student ON

Jeśli pojawia się ten błąd w aplikacji internetowej lub używasz struktury encji, najpierw uruchom to zapytanie na serwerze SQL i zaktualizuj model encji ( .edmx file) i skompiluj projekt, a ten błąd zostanie rozwiązany

Umang Patwa
źródło
Tak było w mojej aplikacji internetowej MVC z EF i właśnie usunąłem model z .edmx i ponownie dodałem (prawym przyciskiem myszy Aktualizuj model z bazy danych) oraz wyczyściłem i odbudowałem projekt, który potem działał dla mnie. Dziękuję @Umang Patwa
Ishwor Khanal
42

Zachowaj ostrożność przy ustawianiu IDENTITY_INSERT na ON. Jest to zła praktyka, chyba że baza danych znajduje się w trybie konserwacji i nie jest ustawiona na jednego użytkownika. Wpływa to nie tylko na twoją wstawkę, ale także na wszystkich, którzy próbują uzyskać dostęp do tabeli.

Dlaczego próbujesz umieścić wartość w polu tożsamości?

HLGEM
źródło
5
Wpływa w jaki sposób? Jest to opcja na poziomie sesji, a nie właściwość tabeli.
Martin Smith
5
Jednorazowa synchronizacja danych między dwiema bazami danych, w których chcesz zachować relacje. Na przykład użyłem go do przeciągnięcia mojego schematu produktu z jednej bazy danych do innej
NSjonas
1
@NSjonas, to byłoby dobre wykorzystanie ustawienia WŁĄCZENIA tabeli Tożsamość _wstaw1. Widziałem ludzi, którzy chcieli użyć tego do zrobienia czegoś z aplikacji, co powinno być zrobione za pomocą prostej wstawki i umożliwienia wygenerowania tożsamości.
HLGEM,
2
Pytanie brzmi: „Czy możesz określić, co to jest i jak można to rozwiązać?” Twoja odpowiedź to komentarz, który wywołuje ostrzeżenie i kolejne pytanie zamiast właściwej odpowiedzi, która rozwiązuje problem.
Quality Catalyst
tak, nie wstawiaj wartości do klucza podstawowego.
doflamingo
22

Istnieją zasadniczo 2 różne sposoby WSTAWIANIA rekordów bez błędu:

1) Gdy IDENTITY_INSERT jest ustawiony na OFF. KLUCZ PODSTAWOWY „ID” NIE MOŻE BYĆ OBECNY

2) Gdy IDENTITY_INSERT jest włączony. KLUCZ PODSTAWOWY „ID” MUSI BYĆ OBECNY

Zgodnie z poniższym przykładem z tej samej tabeli utworzonej przy użyciu klucza podstawowego tożsamości:

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

1) W pierwszym przykładzie możesz wstawić nowe rekordy do tabeli bez wyświetlania błędu, gdy IDENTITY_INSERT jest WYŁĄCZONY. Klucz podstawowy „ID” nie może być obecny ze sprawozdania „insert into” i unikalna wartość ID zostanie dodany automatycznie: . Jeśli w tym przypadku jest obecny identyfikator z INSERT, pojawi się błąd „Nie można wstawić wyraźnej wartości dla kolumny identyfikacyjnej w tabeli ...”

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

WYNIK TABELI [dbo]. [Osoby] to:

ID    LastName   FirstName
1     DOE        Jane
2     BROWN      JOE

2) W drugim przykładzie możesz wstawić nowe rekordy do tabeli bez wyświetlania błędu, gdy IDENTITY_INSERT jest włączony. KLUCZ PODSTAWOWY „ID” MUSI BYĆ OBECNY w instrukcjach „INSERT INTO”, o ile wartość ID jeszcze nie istnieje : Jeśli w tym przypadku identyfikator NIE jest obecny w INSERT, pojawi się błąd „Wartość jawna musi być określono dla tabeli kolumn tożsamości ... ”

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'); 

WYNIK TABELI [dbo]. [Osoby] to:

ID    LastName   FirstName
1     DOE        Jane
2     BROWN      JOE
3     BLACK      JACK
5     WHITE      JOHN
Specjalista ds. Kontroli jakości
źródło
2
Plus jeden za wyjaśnienie, jak działa flaga. Uratowałem mój dzień Superman
John
20

W swojej encji dla tej tabeli dodaj DatabaseGenerated atrybut nad kolumną, dla której ustawiono wstawianie tożsamości:

Przykład:

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int TaskId { get; set; }
użytkownik902490
źródło
Cóż, to prawda, ale naprawdę chciałem znaleźć odpowiedź dla EF :-) Mimo to, OP nie jest odpowiednie dla OP, który mógł nigdy nie użyć EF, a może nawet go spotkać.
Auspex,
W każdym razie odpowiedź jest błędna. Mój byt jest już określony za pomocą DatabaseGeneratedOption.Identityi nadal pojawia się błąd. To moja wina, że ​​umieszczam pseudo-identyfikatory w nowych wierszach, aby odróżnić je od siebie na mojej stronie internetowej, i mam nadzieję, że po prostu je wyzeruję, zanim insertbędzie wystarczające.
Auspex,
13

możesz po prostu użyć tego oświadczenia, na przykład, jeśli nazwa twojej tabeli to School . Przed włożeniem make pewien IDENTITY_INSERT jest ustawiony na ON i po insert zapytań kolej IDENTITY_INSERT OFF

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

źródło
1
Czy mógłbyś nieco rozwinąć swoją odpowiedź, aby zawierać wyjaśnienie polecenia, dlaczego działa i jaki ma efekt?
gareththegeek
@gareththegeek tak, to dla kolumny tożsamości musisz upewnić się, że jest włączony, aby wstawić dane.
6

Jeśli używasz Liquibase do aktualizacji SQL Server, prawdopodobnie próbujesz wstawić klucz rekordu w polu autoIncrement. Po usunięciu kolumny ze wstawki skrypt powinien zostać uruchomiony.

<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>
iowatiger08
źródło
4

W zapytaniu znajduje się wcześniej wspomniana operacja, której nie powinno być, ponieważ jest ona automatycznie zwiększana

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

więc twoje zapytanie będzie

Insert table(OpDescription,FilterID)
values ('Hierachy Update',1)
Onkar_M18
źródło
3

Inną sytuacją jest sprawdzenie, czy klucz podstawowy ma taką samą nazwę jak w przypadku klas, gdzie jedyną różnicą jest to, że klucz podstawowy ma dołączony „identyfikator” lub określenie [klucza] na kluczach podstawowych, które nie są związane ze sposobem klasa ma nazwę.

salemsky95
źródło
2
  1. Dzieje się tak, gdy masz kolumnę (Klucz podstawowy), która nie jest ustawiona na wartość True to SQL w wartości True i nie przekazujesz jej jawnej wartości podczas wstawiania. Zajmie to pierwszy wiersz, a następnie nie będzie można wstawić drugiego wiersza, pojawi się błąd. Można to poprawić, dodając ten wiersz kodu [DatabaseGenerated(DatabaseGeneratedOption.Identity)]w kolumnie PrimaryKey i upewnij się, że jest ustawiony na typ danych int . Jeśli kolumna jest kluczem podstawowym i dla SQL ustawiona jest wartość IsIDentity na true, nie ma potrzeby stosowania tego wiersza kodu[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  2. dzieje się tak również wtedy, gdy masz kolumnę, która nie jest kluczem podstawowym, w SQL ustawionym na Is Identity na true, aw EF nie dodałeś tego wiersza kodu [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
Siphamandla Hero Ngwenya
źródło
Dzięki, że to była poprawka, której spędziłem godziny szukając.
Vishav Premlall
2

Najlepszym rozwiązaniem jest użycie adnotacji GeneratedValue(strategy = ...), tj

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

mówi, że ta kolumna jest generowana przez bazę danych przy użyciu strategii TOŻSAMOŚCI i nie musisz się tym zajmować - baza danych to zrobi.

Tomasz Dzięcielewski
źródło
1

Jeśli masz ten problem podczas korzystania z serwera SQL z npm sequelize-maszynopisu, dodaj @AutoIncrementkolumnę identyfikatora:

  @PrimaryKey
  @AutoIncrement
  @Column
  id!: number;
Kate Kasinskaya
źródło
0

A jeśli używasz Oracle SQL Developer do łączenia, pamiętaj, aby dodać / sqldev: stmt /

/ sqldev: stmt / set TABELA_własności na;

Hao Deng
źródło
Oczywiście tak nie jest, pytanie ma tag „sql-server”
DanielV
0

Nie jestem pewien, do czego służy „Wstaw tabelę”, ale jeśli próbujesz tylko wstawić niektóre wartości, spróbuj:

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

Pojawił się ten sam komunikat o błędzie, ale myślę, że to powinno zadziałać. Identyfikator powinien automatycznie zwiększać automatycznie, o ile jest to klucz podstawowy.

Mateusz
źródło
0

Rozwiązałem ten problem, tworząc nowy obiekt za każdym razem, gdy chcę coś dodać do bazy danych.

Naresh Bisht
źródło
0

Zauważ, że jeśli zamykasz każdą linię ;, SET IDENTITY_INSERT mytable ONpolecenie nie zostanie wstrzymane dla następujących linii.

tj.
zapytanie podobne

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

Podaje błąd
Cannot insert explicit value for identity column in table 'mytable' when IDENTITY_INSERT is set to OFF.

Ale takie zapytanie będzie działać:

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

Wygląda na to, że SET IDENTITY_INSERTpolecenie dotyczy tylko transakcji i ;będzie oznaczać koniec transakcji.

cryanbhu
źródło
-1

Problem wynikający z używania nietypowego DBContext lub DBSet, jeśli używasz interfejsu i implementujesz metodę zapisywania zmian w sposób ogólny

Jeśli tak jest w twoim przypadku, proponuję na przykład mocno wpisać DBContex

MyDBContext.MyEntity.Add(mynewObject)

wtedy .Savechangesbędzie działać

Mostafa Basha
źródło