Як оновити стовпчик посвідчення особи на SQL сервері?


196

У мене база даних SQL Server, і я хочу змінити стовпчик ідентичності, тому що він почався з великої кількості 10010 і пов'язаний з іншою таблицею, тепер у мене є 200 записів, і я хочу виправити цю проблему до того, як записи збільшаться.

Який найкращий спосіб змінити чи скинути цей стовпець?

Відповіді:


270

Не можна оновити стовпчик посвідчення.

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

Хоча існують деякі альтернативи для досягнення подібних вимог.

  • Коли значення стовпця 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 це не оновлення існуючої ідентичності, це вставляється вручну
Філл Грегган

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
У мене є ще одна таблиця, пов’язана з цією таблицею, я не можу цього зробити
Abdulsalam Elsharif

4
Отже, заява не бажана :)
Luv

3
@AbdusalamElsherif Але ви запитали, як змінити стовпець посвідчення.
папараццо

@luv принаймні ви відповіли на питання, яке було задано
Філл Грегган

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

56

Тобі потрібно

set identity_insert YourTable ON

Потім видаліть рядок і знову вставте його з іншою особою.

Після того як ви зробили вставку, не забудьте вимкнути ідентифікатор_встановлення

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
Просто порада щодо продуктивності, якщо таблиця дуже велика, замість того, щоб видаляти таблицю, зробіть таблицю обрізання. Це миттєво. Але будьте обережні, жодного повороту назад зі скороченням, оскільки він не входив у систему.
kuklei


5

скопіюйте свою таблицю в нову таблицю без стовпця особи.

    select columns into newtable from yourtable

додайте стовпець ідентифікації до нової таблиці з новим насінням та зробіть це як основний ключ

    ALTER TABLE tableName ADD id MEDIUMINT NOT NULL AUTO_INCREMENT KEY

3
DBCC CHECKIDENT(table_name, RESEED, value)

table_name = дайте таблиці, для якої потрібно скинути значення

value = початкове значення дорівнює нулю, щоб почати стовпець ідентичності з 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 Insert, або програму, в якій ви є власником вбудовування команд вставки. Або скористайтеся цим, який я вам запрограмував. Дано таблицю даних, генерує сценарій вставки SQL:

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, а потім за допомогою вставки. Наприклад, якщо ваш стіл

Спочатку встановіть нове поточне значення ідентифікатора в таблиці як 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. Після цього ви можете видалити дублюючі рядки вищої вартості ідентифікатора, як тільки ви видалили / перемістили свої посилання на зовнішній ключ, якщо такі є.


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

Потім видаліть старий db і перейменуйте новий db на ім'я старого db. Примітка : цей стовпчик1 і стовпчик2 представляють усі стовпці вашої старої таблиці, які ви хочете зберегти у своїй новій таблиці.


0

Якщо спеціально потрібно змінити значення первинного ключа на інше число (наприклад, 123 -> 1123). Блоки властивості ідентичності змінюють значення ПК. Встановити 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 в первинному ключі.

Примітка. Я бачу, що деякі люди на ці питання задають ЧОМУ. У моєму випадку я повинен об'єднати дані з другого виробничого екземпляра в основний БД, щоб я міг вимкнути другий екземпляр. Мені просто потрібні всі дані ПК / ФК операцій, щоб вони не стикалися. Метадані ФК однакові.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.