Jak zaktualizować kolumnę tożsamości w SQL Server?

195

Mam bazę danych SQL Server i chcę zmienić kolumnę tożsamości, ponieważ zaczęła się od dużej liczby 10010i jest powiązana z inną tabelą, teraz mam 200 rekordów i chcę rozwiązać ten problem, zanim liczba rekordów wzrośnie.

Jak najlepiej zmienić lub zresetować tę kolumnę?

Abdulsalam Elsharif
źródło

Odpowiedzi:

269

Nie można zaktualizować kolumny tożsamości.

SQL Server nie pozwala na aktualizację kolumny tożsamości w przeciwieństwie do tego, co można zrobić z innymi kolumnami za pomocą instrukcji aktualizacji.

Chociaż istnieją pewne alternatywy, aby osiągnąć podobny rodzaj wymagań.

  • Kiedy wartość kolumny Tożsamość wymaga aktualizacji dla nowych rekordów

Użyj DBCC CHECKIDENT, który sprawdza bieżącą wartość tożsamości dla tabeli i jeśli to konieczne, zmienia wartość tożsamości.

DBCC CHECKIDENT('tableName', RESEED, NEW_RESEED_VALUE)
  • Kiedy wartość kolumny Tożsamość wymaga aktualizacji dla istniejących rekordów

Użyj IDENTITY_INSERT, który pozwala wstawić wartości jawne do kolumny tożsamości tabeli.

SET IDENTITY_INSERT YourTable {ON|OFF}

Przykład:

-- Set Identity insert on so that value can be inserted into this column
SET IDENTITY_INSERT YourTable ON
GO
-- Insert the record which you want to update with new value in the identity column
INSERT INTO YourTable(IdentityCol, otherCol) VALUES(13,'myValue')
GO
-- Delete the old row of which you have inserted a copy (above) (make sure about FK's)
DELETE FROM YourTable WHERE ID=3
GO
--Now set the idenetity_insert OFF to back to the previous track
SET IDENTITY_INSERT YourTable OFF
Sachin
źródło
6
DBCC Zresetuj następny nowy rekord, ale co chcę teraz zmienić istniejące rekordy.
Abdulsalam Elsharif
czy możesz podać przykład?
Abdulsalam Elsharif
38
@sachin to nie aktualizuje istniejącej TOŻSAMOŚCI, którą ręcznie wstawia
Phill Greggan
3
@PhillGreggan tak, jest to najlepsze możliwe rozwiązanie, aby to osiągnąć. Nie można zaktualizować kolumny Tożsamość podczas aktualizacji zwykłych.
Sachin
17
Ta zaakceptowana odpowiedź nie odpowiada na pytanie, jak zaktualizować kolumnę tożsamości (np UPDATE YourTable SET IdentityCol = 13.). SET IDENTITY_INSERT YourTable ONzezwala tylko na WSTAWKI, a nie na AKTUALIZACJE.
Ian Boyd
61

Jeśli masz właściwe pytanie, chcesz zrobić coś takiego

update table
set identity_column_name = some value

Pozwól, że powiem ci, że nie jest to łatwy proces i nie jest zalecane korzystanie z niego, ponieważ mogą być foreign keyz nim związane.

Ale oto kroki, aby to zrobić, weź back-upstolik

Krok 1- Wybierz widok projektu tabeli

wprowadź opis zdjęcia tutaj

Krok 2 - Wyłącz kolumnę tożsamości

wprowadź opis zdjęcia tutaj

Teraz możesz użyć updatezapytania.

Teraz redokrok 1 i krok 2 i Włącz kolumnę tożsamości

Odniesienie

Luv
źródło
1
Mam inny stół związany z tym stołem, myślę, że nie mogę tego zrobić
Abdulsalam Elsharif
4
Stąd stwierdzenie, że nie jest wskazane :)
Luv
3
@AbdusalamElsherif Ale zapytałeś, jak zmienić kolumnę tożsamości.
paparazzo
@luv przynajmniej odpowiedziałeś na zadane pytanie
Phill Greggan
Korzystam z tej procedury do ustawiania identyfikatora w mojej bazie danych programowania. Byłoby miło, gdyby istniało polecenie, które pozwoli mi to zrobić, ale to działa.
Jeff Davis,
56

Musisz

set identity_insert YourTable ON

Następnie usuń wiersz i włóż go z inną tożsamością.

Po zakończeniu wstawiania nie zapomnij wyłączyć tożsamości

set identity_insert YourTable OFF
RSP
źródło
Jest to o wiele łatwiejsze i bezpieczniejsze niż wyłączenie Tożsamości w kolumnie!
Protektor jeden
Jest to bezpieczniejsze i łatwiejsze w przypadku niewielkiej liczby rekordów, ale nie odpowiada poprawnie na pytanie. Wyłączenie tożsamości, choć bardziej niebezpieczne, a czasem niemożliwe, pozwala zaktualizować kolumnę tożsamości.
Matthew Hudson,
18
--before running this make sure Foreign key constraints have been removed that reference the ID. 

--set table to allow identity to be inserted
SET IDENTITY_INSERT yourTable ON;
GO
--insert everything into a temp table
SELECT * 
INTO #tmpYourTable
FROM yourTable

--clear your table
DELETE FROM yourTable
--insert back all the values with the updated ID column
INSERT INTO yourTable (IDCol, OtherCols)
SELECT ID+1 as updatedID --put any other update logic to the ID here
, OtherCols FROM #tmpYourTable
--drop the temp table
DROP TABLE #tmpYourTable
--put identity back to normal
SET IDENTITY_INSERT yourTable OFF;
GO
kuklei
źródło
1
Tylko wskazówka dotycząca wydajności, jeśli tabela jest bardzo duża, zamiast usuwać z tabeli, wykonaj Obcinanie tabeli yourTable. To jest natychmiastowe. Ostrożnie, nie ma odwrotu z obcinaniem, ponieważ nie jest ono rejestrowane.
kuklei
5

skopiuj tabelę do nowej tabeli bez kolumny tożsamości.

    select columns into newtable from yourtable

dodaj kolumnę tożsamości do newtable z nowym seedem i ustaw jako klucz podstawowy

    ALTER TABLE tableName ADD id MEDIUMINT NOT NULL AUTO_INCREMENT KEY
użytkownik4002899
źródło
3
DBCC CHECKIDENT(table_name, RESEED, value)

nazwa_tabeli = podaj tabelę, którą chcesz zresetować

wartość = wartość początkowa równa zero, aby rozpocząć kolumnę tożsamości od 1

Yasmeen Ansari
źródło
3
SET IDENTITY_INSERT dbo.TableName ON
INSERT INTO dbo.TableName 
(
    TableId, ColumnName1, ColumnName2, ColumnName3
)
VALUES
(
    TableId_Value, ColumnName1_Value, ColumnName2_Value, ColumnName3_Value
)

SET IDENTITY_INSERT dbo.TableName OFF

Korzystając z Identity_Insert, nie zapomnij podać nazw kolumn, ponieważ sql nie pozwoli na wstawienie bez ich podania

befree2j
źródło
2

Możesz także użyć SET IDENTITY INSERT, aby wstawić wartości do kolumny tożsamości.

Przykład:

SET IDENTITY_INSERT dbo.Tool ON
GO

Następnie możesz wstawić do kolumny tożsamości potrzebne wartości.

DaveShaw
źródło
1
ALTER TABLE tablename add newcolumn int
update tablename set newcolumn=existingcolumnname
ALTER TABLE tablename DROP COLUMN existingcolumnname;
EXEC sp_RENAME 'tablename.oldcolumn' , 'newcolumnname', 'COLUMN'
update tablename set newcolumnname=value where condition

Jednak powyższy kod działa tylko wtedy, gdy nie ma relacji klucz-klucz obcy

Jekin Kalariya
źródło
1

Kompletne rozwiązanie dla programistów C # za pomocą konstruktora poleceń

Przede wszystkim musisz znać te fakty:

  • W każdym razie nie można zmodyfikować kolumny tożsamości, dlatego należy usunąć wiersz i ponownie dodać nową tożsamość.
  • Nie możesz usunąć właściwości tożsamości z kolumny (musiałbyś ją usunąć do kolumny)
  • Niestandardowy konstruktor poleceń z .net zawsze pomija kolumnę tożsamości, więc nie można go użyć do tego celu.

Więc kiedy już to wiesz, musisz to zrobić. Albo zaprogramuj własną instrukcję SQL Insert, albo program, który posiadasz konstruktora poleceń insert. Lub użyj tego, który jestem zaprogramowany dla ciebie. Biorąc pod uwagę DataTable, generuje skrypt SQL Insert:

public static string BuildInsertSQLText ( DataTable table )
{
    StringBuilder sql = new StringBuilder(1000,5000000);
    StringBuilder values = new StringBuilder ( "VALUES (" );
    bool bFirst = true;
    bool bIdentity = false;
    string identityType = null;

    foreach(DataRow myRow in table.Rows) 
    {
        sql.Append( "\r\nINSERT INTO " + table.TableName + " (" );

        foreach ( DataColumn column in table.Columns )
        {
            if ( column.AutoIncrement )
            {
                bIdentity = true;

                switch ( column.DataType.Name )
                {
                    case "Int16":
                        identityType = "smallint";
                        break;
                    case "SByte":
                        identityType = "tinyint";
                        break;
                    case "Int64":
                        identityType = "bigint";
                        break;
                    case "Decimal":
                        identityType = "decimal";
                        break;
                    default:
                        identityType = "int";
                        break;
                }
            }
            else
            {
                if ( bFirst )
                    bFirst = false;
                else
                {
                    sql.Append ( ", " );
                    values.Append ( ", " );
                }
                sql.Append ("[");
                sql.Append ( column.ColumnName );
                sql.Append ("]");

                //values.Append (myRow[column.ColumnName].ToString() );

                if (myRow[column.ColumnName].ToString() == "True")
                    values.Append("1");
                else if (myRow[column.ColumnName].ToString() == "False")
                    values.Append("0");
                else if(myRow[column.ColumnName] == System.DBNull.Value)    
                    values.Append ("NULL");
                else if(column.DataType.ToString().Equals("System.String"))
                {
                    values.Append("'"+myRow[column.ColumnName].ToString()+"'");
                }
                else
                    values.Append (myRow[column.ColumnName].ToString());
                    //values.Append (column.DataType.ToString() );
            }
        }
        sql.Append ( ") " );
        sql.Append ( values.ToString () );
        sql.Append ( ")" );

        if ( bIdentity )
        {
            sql.Append ( "; SELECT CAST(scope_identity() AS " );
            sql.Append ( identityType );
            sql.Append ( ")" );
        }
        bFirst = true;
        sql.Append(";");
        values = new StringBuilder ( "VALUES (" );
    } //fin foreach
    return sql.ToString ();
}
Juan_Mallorca
źródło
0

Rozwiązałem ten problem, najpierw używając DBCC, a następnie wstawiania. Na przykład, jeśli twój stół to

Najpierw ustaw nową bieżącą wartość identyfikatora w tabeli jako NEW_RESEED_VALUE

MyTable {IDCol, colA, colB}

    DBCC CHECKIDENT('MyTable', RESEED, NEW_RESEED_VALUE)

wtedy możesz użyć

    insert into MyTable (colA, ColB) select colA, colB from MyTable

Spowodowałoby to zduplikowanie wszystkich rekordów, ale przy użyciu nowej wartości IDCol zaczynającej się od NEW_RESEED_VALUE. Następnie można usunąć zduplikowane wiersze o wyższej wartości identyfikatora po usunięciu / przeniesieniu odniesień do klucza obcego, jeśli takie istnieją.

Softec
źródło
1
Jest to przyzwoity pomysł, ale nowa_nazwa_wartości jest bieżącym nasieniem, a następna liczba, która zostanie użyta, będzie o 1 większa od tej wartości. Jeśli więc chcesz, aby następnym wstawionym wierszem była tożsamość 10, to NEW_RESEED_VALUE musi być ustawiona na 9.
LarryBud
0

Możesz utworzyć nową tabelę za pomocą następującego kodu.

SELECT IDENTITY (int, 1, 1) AS id, column1, column2
INTO dbo.NewTable
FROM dbo.OldTable

Następnie usuń starą bazę danych i zmień nazwę nowej bazy danych na nazwę starej bazy danych. Uwaga : kolumny 1 i 2 reprezentują wszystkie kolumny w starej tabeli, które chcesz zachować w nowej tabeli.

Sean H. Worthington
źródło
0

Jeśli chcesz zmienić wartość klucza podstawowego na inną liczbę (np. 123 -> 1123). Właściwość tożsamości blokuje zmianę wartości PK. Zestaw Identity_insert nie zadziała. Wykonanie operacji wstawiania / usuwania nie jest zalecane, jeśli masz kaskadowe usuwanie (chyba że wyłączysz sprawdzanie integralności referencyjnej).

Ten skrypt wyłączy tożsamość na PK:

***********************

sp_configure 'allow update', 1
go
reconfigure with override
go


update syscolumns set colstat = 0 --turn off bit 1 which indicates identity column
where id = object_id('table_name') and name = 'column_name'
go


exec sp_configure 'allow update', 0
go
reconfigure with override
go

***********************

Następnie możesz ustawić relacje, aby zaktualizowały odwołania do klucza obcego. W przeciwnym razie musisz wyłączyć wymuszanie relacji. Ten link SO pokazuje, jak: W jaki sposób ograniczenia klucza obcego można tymczasowo wyłączyć za pomocą T-SQL?

Teraz możesz zrobić swoje aktualizacje. Napisałem krótki skrypt, aby zapisać wszystkie moje aktualizacje SQL na podstawie tej samej nazwy kolumny (w moim przypadku musiałem zwiększyć CaseID o 1 000 000:

select 
'update ['+c.table_name+'] SET ['+Column_Name+']=['+Column_Name+']+1000000'
from Information_Schema.Columns as c
JOIN Information_Schema.Tables as t ON t.table_Name=c.table_name and t.Table_Schema=c.table_schema and t.table_type='BASE TABLE'
where Column_Name like 'CaseID' order by Ordinal_position

Na koniec włącz ponownie integralność referencyjną, a następnie ponownie włącz kolumnę Tożsamość na kluczu podstawowym.

Uwaga: Widzę, że niektórzy ludzie na te pytania pytają DLACZEGO. W moim przypadku muszę scalić dane z drugiej instancji produkcyjnej do głównej bazy danych, aby móc zamknąć drugą instancję. Potrzebuję tylko wszystkich danych PK / FK operacji, aby się nie kolidować. Metadane FK są identyczne.

Ken Forslund
źródło