Как обновить Identity Column в SQL Server?


196

У меня есть база данных SQL Server, и я хочу изменить столбец идентификаторов, поскольку он начинался с большого числа 10010и связан с другой таблицей, теперь у меня есть 200 записей, и я хочу исправить эту проблему до того, как записи увеличатся.

Каков наилучший способ изменить или сбросить этот столбец?

Ответы:


270

Вы не можете обновить личность столбца.

SQL Server не позволяет обновлять столбец идентификаторов в отличие от того, что вы можете сделать с другими столбцами с помощью оператора update.

Хотя есть несколько альтернатив для достижения подобного рода требований.

  • Когда значение столбца Identity необходимо обновить для новых записей

Используйте DBCC CHECKIDENT, который проверяет текущее значение идентификатора для таблицы и, если необходимо, изменяет значение идентификатора.

DBCC CHECKIDENT('tableName', RESEED, NEW_RESEED_VALUE)
  • Когда значение столбца Identity необходимо обновить для существующих записей

Используйте IDENTITY_INSERT, который позволяет вставлять явные значения в столбец идентификаторов таблицы.

SET IDENTITY_INSERT YourTable {ON|OFF}

Пример:

-- 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

6
DBCC Сброс следующей новой записи, но то, что я хочу сейчас, чтобы изменить существующие записи.
Абдулсалам Эльшариф

Можете ли вы привести пример, пожалуйста?
Абдулсалам Эльшариф

38
@sachin это не обновление существующей IDENTITY, это вставка вручную
Фил Грегган

3
@PhillGreggan да, это лучшее из возможных решений для достижения этой цели. Вы не можете обновить столбец Identity при обновлении обычных.
Сачин

17
Этот принятый ответ не отвечает на вопрос, как обновить столбец идентификации (например, UPDATE YourTable SET IdentityCol = 13). SET IDENTITY_INSERT YourTable ONразрешены только ВСТАВКИ, но не ОБНОВЛЕНИЯ.
Ян Бойд

62

Если ваш вопрос правильно, вы хотите сделать что-то вроде

update table
set identity_column_name = some value

Позвольте мне сказать вам, что это не простой процесс, и его не рекомендуется использовать, так как могут быть некоторые foreign keyсвязанные с ним.

Но вот шаги, чтобы сделать это, пожалуйста, возьмите back-upза стол

Шаг 1 - Выберите вид дизайна таблицы

введите описание изображения здесь

Шаг 2 - Выключите столбец идентификации

введите описание изображения здесь

Теперь вы можете использовать updateзапрос.

Теперь redoшаг 1 и шаг 2 и включите столбец идентификации

Ссылка


1
У меня есть еще одна таблица, связанная с этой таблицей, но я не могу этого сделать
Абдулсалам Эльшариф,

4
Отсюда и заявление не рекомендуется :)
Luv

3
@AbdusalamElsherif Но вы спросили, как изменить столбец идентификации.
Папараццо

@luv, по крайней мере, вы ответили на заданный вопрос
Филл Грегган

Я использую эту процедуру для установки идентификатора в моей базе данных разработки. Было бы неплохо, если бы была команда, которая позволяла бы мне это делать, но это работает.
Джефф Дэвис

56

Тебе надо

set identity_insert YourTable ON

Затем удалите строку и вставьте ее с другим именем.

После того, как вы сделали вставку, не забудьте выключить identity_insert

set identity_insert YourTable OFF

Это намного проще и безопаснее, чем отключение идентификации для колонки!
Один защитник

Это безопаснее и проще для небольшого количества записей, но не дает правильного ответа на вопрос. Отключение идентификации, хотя и более опасное, а иногда и невозможное, позволяет обновить столбец идентификации.
Мэтью Хадсон

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

1
Просто совет по производительности, если таблица очень большая, вместо удаления таблицы сделайте таблицу усеченных таблиц yourTable. Это мгновенно. Однако, будьте осторожны, не возвращайтесь с усечением, поскольку оно не зарегистрировано.
kuklei


5

скопируйте вашу таблицу в новую таблицу без идентификатора столбца.

    select columns into newtable from yourtable

добавить столбец идентификаторов в newtable с новым семенем и сделать его первичным ключом

    ALTER TABLE tableName ADD id MEDIUMINT NOT NULL AUTO_INCREMENT KEY

3
DBCC CHECKIDENT(table_name, RESEED, value)

table_name = дать таблицу, которую вы хотите сбросить значение

значение = начальное значение, равное нулю, для начала столбца идентификаторов с 1


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

При использовании Identity_Insert не забудьте включить имена столбцов, потому что sql не позволит вам вставить без указания их


2

Вы также можете использовать, SET IDENTITY INSERTчтобы позволить вам вставлять значения в столбец идентификаторов.

Пример:

SET IDENTITY_INSERT dbo.Tool ON
GO

И тогда вы можете вставить в столбец идентичности нужные вам значения.


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

Однако приведенный выше код работает, только если нет отношения первичного-внешнего ключа


1

Комплексное решение для программистов на C # с использованием компоновщика команд

Прежде всего, вы должны знать следующие факты:

  • В любом случае вы не можете изменить столбец идентификаторов, поэтому вам нужно удалить строку и заново добавить ее с новым идентификатором.
  • Вы не можете удалить свойство удостоверения из столбца (вам придется удалить в столбец)
  • Пользовательский построитель команд из .net всегда пропускает столбец идентификаторов, поэтому его нельзя использовать для этой цели.

Итак, однажды узнав об этом, вы должны это сделать. Либо запрограммируйте свой собственный оператор вставки SQL, либо запрограммируйте собственный построитель команд вставки. Или используйте тот, который я запрограммировал для вас. При наличии DataTable генерирует скрипт 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 ();
}

0

Я решил эту проблему сначала с помощью DBCC, а затем с помощью вставки. Например, если ваша таблица

Сначала установите новое текущее значение ID в таблице как NEW_RESEED_VALUE

MyTable {IDCol, colA, colB}

    DBCC CHECKIDENT('MyTable', RESEED, NEW_RESEED_VALUE)

тогда вы можете использовать

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

Это будет дублировать все ваши записи, но с использованием нового значения IDCol, начиная с NEW_RESEED_VALUE. Затем вы можете удалить дубликаты строк с более высоким значением ID, как только вы удалили / переместили ссылки на их внешние ключи, если таковые имеются.


1
Это хорошая идея, но New_reseed_value является текущим начальным числом, и следующее число, которое будет использоваться, будет на 1 больше, чем это значение. Так что если вы хотите, чтобы следующая вставленная строка была идентичной 10, то для NEW_RESEED_VALUE должно быть установлено значение 9.
LarryBud

0

Вы можете создать новую таблицу, используя следующий код.

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

Затем удалите старую базу данных и переименуйте новую базу данных в имя старой базы данных. Обратите внимание : что column1 и column2 представляют все столбцы в вашей старой таблице, которые вы хотите сохранить в новой таблице.


0

Если вам необходимо изменить значение первичного ключа на другое число (например, 123 -> 1123). Свойство identity блокирует изменение значения PK. Установить Identity_insert не будет работать. Делать вставку / удаление не рекомендуется, если у вас есть каскадное удаление (если вы не отключите проверку ссылочной целостности).

Этот скрипт отключит идентификацию на ПК:

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

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

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

Далее вы можете установить отношения, чтобы они обновляли ссылки на внешние ключи. Или же вам нужно отключить соблюдение отношений. Эта ссылка SO показывает, как: Как можно временно отключить ограничения внешнего ключа с помощью T-SQL?

Теперь вы можете делать свои обновления. Я написал короткий скрипт для написания всех моих обновлений SQL на основе того же имени столбца (в моем случае мне нужно было увеличить CaseID на 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

Наконец, снова включите ссылочную целостность, а затем снова включите столбец Identity на первичном ключе.

Примечание: я вижу, что некоторые люди на эти вопросы спрашивают, ПОЧЕМУ. В моем случае мне нужно объединить данные из второго производственного экземпляра в основную БД, чтобы я мог закрыть второй экземпляр. Мне просто нужно, чтобы все PK / FKs данных операций не сталкивались. Метаданные ФК идентичны.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.