Sql как изменить значение identity

Столбцы identity отличный способ автоматизировать заполнение целочисленного столбца различными числами при каждой вставке новой строки.

Вставка значений identity вручную

По умолчанию невозможно вставить вручную значение непосредственно в столбец identity, но значения identity могут быть введены вручную, если включить сессионную опцию. Чтобы выяснить, что произойдет при попытке вставить значение identity без включения свойства Identity Insert, выполните код в листинге 1.

Листинг 1: Попытка вставить значение identity

CREATE TABLE Widget(WidgetID INT NOT NULL IDENTITY, 
WidgetName NVARCHAR(50), WidgetDesc NVARCHAR(200));
INSERT INTO Widget
VALUES (110,'MyNewWidget','New widget to test insert');

Вставка значения 110 в столбец identity, наряду со значениями остальных столбцов, в таблицу Widget вернет ошибку, показанную ниже:

В сообщении об ошибке ясно говорится, что вы не можете явно вставлять значение identity, если не указываете список столбцов в операторе INSERT, и свойство IDENTITY_INSERT для таблицы Widget не установлено в ON.

Свойство IDENTITY_INSERT является сессионным, и оно управляет тем, может ли вставляться значение identity или нет. По умолчанию значение этого свойство равно OFF, но оно может быть включено для таблицы Widget с помощью кода в листинге 2.

Листинг 2: Включение свойства IDENTITY_INSERT

SET IDENTITY_INSERT Widget ON;

После включения свойства IDENTITY_INSERT для таблицы Widget можно выполнить код в листинге 3 и не получить ошибки.

Листинг 3: Код со списком столбцов, требуемым для вставки значения identity

INSERT INTO Widget(WidgetID,WidgetName,WidgetDesc) 
VALUES (110,'MyNewWidget','New widget to test insert');

Только одна таблица в сессии может иметь включенным свойство INDENTITY_INSERT в одно и то же время. Если вам потребуется вставить значения identity более чем в одну таблицу, вам сначала нужно выключить свойство INDENTITY_INSERT для первой таблицы, используя код в листинге 4, до включения свойства INDENTITY_INSERT для другой таблицы.

Листинг 4: Выключение сессионного свойства INDENTITY_INSERT

SET IDENTITY_INSERT Widget OFF;

Следует соблюдать осторожность при вставке значений identity вручную. SQL Server не требует от значений identity уникальности. По этой причине вам нужно позаботиться при вставке значений identity вручную, чтобы не вставить значение identity, которое уже существует.

Избежать дублирующих значений identity

Дубликаты значений identity могут возникнуть в таблице при вставке значений identity или повторной установке значения identity. Наличие дубликатов значений identity не обязательно плохо, если нет требования к уникальности этих значений. Если все значения identity должны быть различными, то это требование должно поддерживаться созданием PRIMARY KEY, ограничения UNIQUE или индекса UNIQUE.

Использование функции IDENTITY

SQL Server предоставляет функцию IDENTITY для определения столбца identity при создании новой таблицы с помощью оператора SELECT с предложением INTO. Функция IDENTITY подобна, но не идентична свойству IDENTITY, которое используется в операторах CREATE или ALTER TABLE. Функция IDENTITY может использоваться только в операторе SELECT, содержащем предложение INTO, который создает и заполняет новую таблицу.

Ниже приведен синтаксис функции IDENTITY:

IDENTITY (data_type [ , seed , increment ] ) AS column_name  

Здесь

data-type — допустимый числовой тип данных, который поддерживает целые значения, отличный от bit или decimal.
seed — определяет первое значение identity, которое будет вставлено в таблицу.
increment — целое значение, которое будет прибавляться к значению seed для каждой добавленной строки.
column_name — имя столбца identity, который будет создан в новой таблице.

Для демонстрации работы функции IDENTITY выполните код в листинге 5.

Листинг 5: Использование функции IDENTITY в команде SELECT INTO

USE AdventureWorks2019;
GO
SELECT IDENTITY(int, 90000, 1) AS Special_ProductId,
Name AS Special_Name,
ProductNumber,
ListPrice
INTO Production.SpecialProduct
FROM Production.Product
WHERE Name like '%LL Road Frame%Black%';
-- Вывод новой таблицы
SELECT * FROM Production.SpecialProduct;

Вывод кода в листинге 5 показан ниже.

Результаты показывают, что столбец с именем Special_ProductID является столбцом identity, который был создан при помощи функции IDENTITY. Первая строка получила значение seed. Каждое значение identity для последующих строк вычислялось прибавлением значения increment к значению identity текущей вставленной строки.

Иногда вам может потребоваться программным образом выяснить значения seed и increment или последнее вставленное значение в столбец identity. Для получения подобной информации SQL Server предоставляет несколько функций.

Для получения значения seed, вы можете использовать функцию IDENT_SEED. Эта функция использует следующий синтаксис:

IDENT_SEED ( 'table_or_view' )  

Если вы меняли значение identity с помощью команды DBCC CHECKIDENT, то эта функция вернет исходное значение seed, назначенное столбцу identity при его начальном создании.

Парная функция с именем IDENT_INCR, которая позволяет получить значение приращения (increment), имеет следующий синтаксис:

IDENT_INCR ( 'table_or_view' )  

Чтобы увидеть обе эти функции в действии, выполните код в листинге 6.

Листинг 6: Получение исходных значений seed и increment

SELECT IDENT_SEED('Production.SpecialProduct') AS OriginalSeed,
IDENT_INCR('Production.SpecialProduct') AS IncrementValue;

Вот результат выполнения этого кода:

Здесь видно, что OriginalSeed и IncrementValue являются теми же, что и аргументы, которые использовались при создании таблицы SpecialProduct в коде из листинга 5.

Вам также может понадобиться знать последнее значение identity, вставленное в таблицу. Обычно это требуется, когда у вас есть две таблицы со связью «родитель-потомок», и дочернюю запись нужно привязать к родительской записи, используя значение identity родительской записи. Есть три различных способа вернуть значение identity последней вставленной записи, которые мы тут рассмотрим: @@IDENTITY, IDENT_CURRENT и SCOPE_IDENTITY.

@@IDENTITY

Системная функция @@IDENTITY возвращает последнее вставленное значение identity. Если последний оператор вставки вставил несколько значений identity, то только последнее значение из них возвращается этой функцией. Если никаких новых значений identity не было вставлено в данной сессии, то функция вернет значений NULL. Если срабатывает триггер на вставку, и этот триггер в свою очередь вставляет строку в таблицу, которая содержит столбец identity, то будет возвращено значение identity, вставленное триггером.

SCOPE_IDENTITY

Функция SCOPE_IDENTITY так же возвращает последнее вставленное значение identity, как и @@IDENTITY, но с одним отличием. Разница состоит в том, что функция SCOPE_IDENTITY возвращает значение identity для последнего оператора INSERT, выполненного в той же сессии и области действия (scope). Напротив, функция @@IDENTITY возвращает последнее вставленное значение независимо от области действия.

Для лучшего понимания того, как влияет область действия на значение identity, возвращаемое этими двумя функциями, выполните код в листинге 7.

Листинг 7: Код, показывающий разницу между SCOPE_IDENTITY и @@IDENTITY

DROP TABLE IF EXISTS TestTable1, TestTable2;
CREATE TABLE TestTable1(
ID INT IDENTITY(1,1),
InsertText1 VARCHAR(100)
);
CREATE TABLE TestTable2(
ID INT IDENTITY(100,100),
InsertText2 VARCHAR(100)
);
GO
CREATE TRIGGER MyTrigger ON TestTable1 AFTER INSERT AS
BEGIN
INSERT INTO TestTable2(InsertText2) VALUES ('Trigger Insert 1');
INSERT INTO TestTable2(InsertText2) VALUES ('Trigger Insert 2');
END
GO
INSERT INTO TestTable1(InsertText1) VALUES ('Original Insert');
GO
-- Возвращаем значения Identity
SELECT @@IDENTITY AS [@@IDENTITY], SCOPE_IDENTITY() AS [SCOPE_IDENTITY];

Код в листинге 7 сначала вставляет одну запись в таблицу TestTable1 в текущей области действия, затем еще 2 записи вставляются в таблицу TestTable2 в другой области действия, когда срабатывает триггер. После вставки и срабатывания триггера на вставку выполняется оператор SELECT, чтобы показать значения, возвращаемые функциями @@IDENTITY и SCOPE_IDENTITY(). Вывод показан ниже.

Следовательно, если вы хотите узнать последнее значение identity независимо от области действия, вы можете использовать @@IDENTITY. Если вам нужно знать последнее значение identity, вставленное в текущей области действия, вам нужно использовать функцию SCOPE_IDENTITY(). На представленных результатах видно, что функция @@IDENTITY вернула значение 200. Это произошло потому, что @@IDENTITY возвращает последнее вставленное значение вне зависимости от области действия. Значение identity для второй записи было вставлено в таблицу TestTable2 триггером «после вставки». Функция SCOPE_IDENTITY() вернула значение 1, это значение identity было присвоено, когда запись вставлялась в TextTable1 в той же области действия.

Имейте в виду, что обе функции @@IDENTITY и SCOPE_IDENTITY() возвращают последнее вставленное значение identity, оставляя без внимания таблицу, куда это значение было вставлено. Если вам нужно знать последнее значение identity, вставленное в конкретную таблицу, вам следует использовать функцию IDENT_CURRENT().

IDENT_CURRENT

Функция IDENT_CURRENT() возвращает последнее значение identity, вставленное в конкретную таблицу, вне зависимости от сессии или области действия, когда это было сделано. С помощью функции IDENT_CURRENT() вы можете легко определить последнее значение identity, созданное для конкретной таблицы, как показано в коде листинга 8.

Листинг 8: Определение последних значений identity, вставленных в таблицы TestTable1 и TestTable2

SELECT IDENT_CURRENT('TestTable1') AS IdentityForTestTable1, 
IDENT_CURRENT('TestTable2') AS IdentityForTestTable2;

Выполнение кода в листинге 2 дает следующие результаты:

Функции @@IDENTITY и SCOPE_IDENTITY() не требуют передачи имени таблицы в качестве параметра, поэтому нелегко идентифицировать, из какой таблицы пришло значение identity. Напротив, IDENT_CURRENT() требует передать имя таблицы. Следовательно, если вы хотите знать последнее значение identity, вставленное в конкретную таблицу вне зависимости от сессии и области действия, вам следует обратить внимание на функцию IDENT_CURRENT().

При вставке множества строк в таблицу со столбцом identity не гарантировано, что каждая строка получит последовательные значения в столбце identity. Это может произойти, когда в то же время другие пользователи вставляют строки. Если вам действительно нужны последовательные значения identity, убедитесь, что ваш код использует эксклюзивную блокировку для таблицы или уровень изоляции SERIALIZE.

Вы также можете обнаружить, что значения identity не всегда присваиваются последовательно. Одной из причин этого является откат транзакции. При откате транзакций любые значения identity, которые были отменены, не будут повторно использоваться. Еще одной причиной появления зазоров является способ, которым SQL Server кэширует значения identity в целях повышения производительности.

Кэширование identity для повышения производительности

Чтобы найти следующее значение identity, SQL Server требуются некоторые ресурсы машины, чтобы заглянуть внутрь и найти это значение. Поэтому для оптимизации производительности и экономии ресурсов машины SQL Server кэширует имеющиеся значения identity. Кэшируя имеющиеся значения identity, SQL Server не нужно вычислять следующее доступное значение идентификатора при вставке новой строки.

Кэширование identity было введено в SQL Server 2012. Проблема с кэшированием identity состоит в том, что когда SQL Server неожиданно падает, он теряет значения, сохраняемые во внутреннем кэше. При потере кэшированных значений эти значения identity больше никогда не будут использоваться. Это может привести к созданию зазора в значениях identity.

Новая опция конфигурации базы данных с именем IDENTITY_CACHE была введена в SQL Server 2017, чтобы помочь решить проблему с зазорами, которые могут вызываться кэшированием. Опция IDENTITY_CACHE включена по умолчанию, но может быть выключена (OFF). При выключении опции SQL Server не кэширует значения identity; тем самым они не будут потеряны при крушении или неожиданной остановке SQL Server. Конечно, отключение кэширования identity приведет к ухудшению производительности.

Чтобы проверить установку IDENTITY_CACHE для базы данных, выполните код из листинга 9.

Листинг 9: Вывод установки IDENTITY_CACHE для текущей базы данных

SELECT * FROM sys.database_scoped_configurations
WHERE NAME = 'IDENTITY_CACHE';

Вывод выполнения кода из листинга 9 на SQL Server 2017 показан ниже.

Видно, что значение IDENTITY_CACHE установлено в 1, что означает, что кэширование identity включено. Чтобы запретить кэширование identity для текущей базы данных, выполните код из листинга 10.

Листинг 10: Выключение кэширования identity

ALTER DATABASE SCOPED CONFIGURATION SET IDENTITY_CACHE=OFF;

Если вы обнаружите множество зазоров в ваших значениях identity, и это является проблемой, вы можете отключить кэширование identity.

Недостатки столбцов identity

Столбцы identity отличный способ автоматизировать заполнение целочисленного столбца различными числами при каждой вставке новой строки. И все же есть несколько недостатков при использовании столбцов identity:

  • Только один столбец identity можно определить на таблицу.
  • Столбец identity нельзя изменить или удалить после его создания.
  • Столбцы identity не являются уникальными по умолчанию. Чтобы обеспечить их уникальность, необходимо определить первичный ключ, ограничение уникальности или уникальный индекс.

  • Remove From My Forums
  • Question

  • I tried

    Alter table table1 alter column column1 Identity(1,1);

    Alter table table1 ADD CONSTRAINT column1_def Identity(1,1) FOR column1

    they all can not work,

    any idea about this? thanks

Answers

  • You can’t alter the existing columns for identity.

    You have 2 options,

    1. Create a new table with identity & drop the existing table

    2. Create a new column with identity & drop the existing column

    But take spl care when these columns have any constraints / relations.

    Code Snippet

    /*

                For already craeted table Names

                Drop table Names

                Create table Names

                (

                            ID int,

                            Name varchar(50)

                )

                Insert Into Names Values(1,’SQL Server’)

                Insert Into Names Values(2,’ASP.NET’)

                Insert Into Names Values(4,’C#’)

    */

    Code Snippet

    —In this Approach you can retain the existing data values on the newly created identity column

    CREATE TABLE dbo.Tmp_Names

                (

                Id int NOT NULL IDENTITY (1, 1),

                Name varchar(50) NULL

                )  ON [PRIMARY]

    go

    SET IDENTITY_INSERT dbo.Tmp_Names ON

    go

    IF EXISTS(SELECT * FROM dbo.Names)

                INSERT INTO dbo.Tmp_Names (Id, Name)

                            SELECT Id, Name FROM dbo.Names TABLOCKX

    go

    SET IDENTITY_INSERT dbo.Tmp_Names OFF

    go

    DROP TABLE dbo.Names

    go

    Exec sp_rename ‘Tmp_Names’, ‘Names’

    Code Snippet

    —In this approach you can’t retain the existing data values on the newly created identity column;

    —The identity column will hold the sequence of number

    Alter Table Names Add Id_new Int Identity(1,1)

    Go

    Alter Table Names Drop Column ID

    Go

    Exec sp_rename ‘Names.Id_new’, ‘ID’,‘Column’

  • Code Snippet

    —create test table

    create table table1 (col1 int, col2 varchar(30))

    insert into table1 values (100, ‘olddata’)

     —add identity column


    alter table table1 add col3 int identity(1,1)

    GO

    —rename or remove old column

    exec sp_rename ‘table1.col1’, ‘oldcol1’, ‘column’

    OR


    alter table table1 drop column col1

    —rename new column to old column name

    exec sp_rename ‘table1.col3’, ‘col1’, ‘column’

    GO

    —add new test record and review table

    insert into table1 values ( ‘newdata’)

    select * from table1

In a rare scenario, I had to update the values in the identity column. There is no straightforward way to update identity values. Here is a workaround I have followed to get the work done.

Note

Before going through the workaround to update the values in identity column, you have to understand that:

  • You cannot update the value of the identity column in SQL Server using UPDATE statement.
  • You can delete the existing column and re-insert it with a new identity value.
  • The only way to remove the identity property for the column is by removing the identity column itself.

Steps for updating existing identity column values

  1. Remove all the foreign key constraints referencing the identity column.
  2. Copy all the records from the identity table and insert it to a staging table.
  3. Now, switch ON IDENTITY_INSERT for the identity table to allow inserting values to the identity Column.
  4. Delete the records from the identity table.
  5. Insert the records from the staging table with your preferred identity values.
  6. Now switch OFF IDENTITY_INSERT.
  7. Finally delete the staging table.

Syntax T-SQL code for the above steps.

/* Step 1: Remove all the foreign key constraints 
	referencing the identity column. */

/* Step 2: Insert the records to a staging table. */
SELECT *  INTO tmp_identityTable FROM identityTable;

/* Step 3: Allow insertion in identity column. */
SET IDENTITY_INSERT identityTable ON;
GO

/* Step 4: Delete all the records from the identity table. */
DELETE FROM identityTable;

/* Step 5: Insert back all the records with the new identity value. */
INSERT INTO identityTable (IDCol, DateCol, OtherCols)
SELECT ID+1 as IDCol /* You can use any other identity generation logic here. */
, DateCol, OtherCols FROM tmp_identityTable
ORDER BY DateCol ASC;

/* Step 6: Switch off the identity insert. */
SET IDENTITY_INSERT identityTable OFF;
GO

/* Step 7: Drop the staging table. */
DROP TABLE tmp_identityTable;

Steps for changing the identity value of new records

In case if you do not want to change the identity values of the existing records, but you want to change the identity value of the new records to start from a higher number, you can use DBCC CHECKIDENT.

For example, if the identity value of the last existing record is 18, and you have to insert a new record to start from 1000, then use the below code.

/* Syntax */
DBCC CHECKIDENT(tableName, RESEED, newReseedValue)

/* Example */
DBCC CHECKIDENT(TestTable, RESEED, 1000)

How To Update Values In Identity Column

Reference

  • More about DBCC CHECKIDENT at Microsoft Docs.
  • More about SET IDENTITY_INSERT at Microsoft Docs.

Do you want to reset an identity column in your table in SQL Server so the numbers are in order?

And you want to do it without recreating the table?

In this article, I’ll show you how you can do this, and a few things to be aware of.

Let’s take a look.

What is an Identity Column?

An identity column is a feature in SQL Server that lets you auto-increment the column’s value. This is helpful for primary keys, where you don’t care what the number is, as long as it’s unique.

You can specify the word IDENTITY as a property after the data type when creating or altering a table.

For example:

CREATE TABLE product (
  product_id INT IDENTITY,
  product_name VARCHAR(200),
  price INT
);

This statement will create a new table called product.

The product_id has the word IDENTITY after it, which means new records will have an automatically generated value.

Let’s see an example of this.

INSERT INTO product (product_name, price)
VALUES ('Chair', 100);

We can check the value was inserted by selecting data from the table.

SELECT product_id, product_name, price
FROM product;
product_id product_name price
1 Chair 100

We can insert a second row into the table to see what the product_id identity column will be set to.

INSERT INTO product (product_name, price)
VALUES ('Desk', 250);

To see the records in the table, we can select from it.

SELECT product_id, product_name, price
FROM product;
product_id product_name price
1 Chair 100
2 Desk 250

Without specifying the product_id in the INSERT statements, the IDENTITY feature has generated a number and populated the row. A new number is created for each row.

So what’s the issue? You may want to reset an identity column if you delete records from the table, or if you get an error when inserting a row.

Let’s delete a record and insert a new one.

DELETE FROM product
WHERE product_id = 2;

INSERT INTO product (product_name, price)
VALUES ('Large Desk', 300);

Once we delete a row and insert a new one, here’s what our table looks like.

SELECT product_id, product_name, price
FROM product;
product_id product_name price
1 Chair 100
3 Large Desk 300

We can see that the new row has a product_id of 3, and not 2.

Our ID values are not in order.

So, if you want them to be in order, you’ll have to reset the identity column.

Identity Values Don’t Matter

If you’re here because you want your primary key identity values to be in numerical order without any gaps, then I would suggest it’s not necessary.

A primary key value should hold no significance to any user or application outside of the database. Its only purpose is to uniquely identify a row and therefore be used to relate to other rows in other tables.

It doesn’t matter to the database if the values are in the order of 1, 2, 3, or if there are missing values like 1, 4, 8. As long as they are unique, the database will still operate in the same way.

If someone looks at an output of a database (e.g. a report that has IDs) and wonders why they are not in order or that there are gaps, then either:

  • you can explain to them that the ID is OK to have gaps
  • if they want numbers with no gaps, you can change the query to generate a row number instead

If someone is using the identity values to determine how many rows are in a table, and the column is “skipping” values like this, then they may think there are more rows in the table than there actually are.

However, the right way to count records is to use the COUNT function, not by looking at the identity column as a row count.

So, to summarise, it doesn’t matter what the value of the identity column is. As long as it’s unique, it’s OK.

People don’t need to see the value.

Having said that, if you really want to reset the identity values (e.g. for a test you’re doing or for a university project), then you can do it in SQL Server.

Check the Current Value Using the DBCC CHECKIDENT Procedure

You can run the DBCC CHECKIDENT procedure in SQL Server to see what the current value of the identity column is. You just specify the name of the table as the parameter.

Here’s an example:

DBCC CHECKIDENT('product');

This will show you the current value of this table’s identity column.

Checking identity information: current identity value '3', current column value '3'.
DBCC execution completed. If DBCC printed error messages,
contact your system administrator.

The value of 3 is the most recent value of the identity column. The next row that’s inserted will have the value of 4.

So, how do we reset the value?

Reset the Identity Value Using the DBCC CHECKIDENT Procedure

If you want to reset the identity column in SQL Server, you can use the DBCC CHECKIDENT procedure with extra parameters:

DBCC CHECKIDENT ('table_name', RESEED, new_value);

Resetting our produce table to use a value of 1 is done using this command:

DBCC CHECKIDENT ('product', RESEED, 0);

However, there are existing records in the table, so if we reset it and insert a new record, there will be an error.

So, what do we do? We need to:

  1. Delete all data from the table
  2. Reset the identity
  3. Re-insert all data

Our script would look like this:

DELETE FROM product;
DBCC CHECKIDENT ('product', RESEED, 0);

INSERT INTO product (product_name, price)
VALUES ('Chair', 100);

INSERT INTO product (product_name, price)
VALUES ('Large Desk', 300);

This will reset the identity value to 0, causing the two inserted rows to have an ID of 1 and 2.

The result is:

product_id product_name price
1 Chair 100
2 Large Desk 300

So that’s how you can reset an identity column in SQL Server.

Reset the Identity Value and Keep Table Data

What if you have a large table? It can be hard or impossible to re-insert all of the values from a script.

One way you can do this is to store the values in another table. The process would be:

  1. Create a new table using the values from the real table
  2. Delete the data from the real table
  3. Reset the identity
  4. Re-insert from the new table

Your script could look like this:

CREATE TABLE product_backup AS
SELECT product_id, product_name, price
FROM product;

DELETE FROM product;

DBCC CHECKIDENT ('product', RESEED, 0);

INSERT INTO product (product_name, price)
SELECT product_name, price
FROM product_backup
ORDER BY product_id ASC;

There are a few things to note here. The product_backup table stores the product_id, which has the gaps, so it can be used in the order by later in the script. This is important if you want the data in the same order. This may not actually be important as you can just order your data in any future queries, but it’s useful if that’s what you want.

Also, in the INSERT statement, you select from the product_backup table, but you don’t insert the product_id from that table. The identity column is generated.

Your data will look the same as the earlier example:

product_id product_name price
1 Chair 100
2 Large Desk 300

Reset the Identity Value: Delete vs Truncate

One issue with using this method is that the value that the CHECKIDENT procedure requires is different depending on if you TRUNCATE or DELETE.

This article here details some tests to explain this.

In short:

  • When you use DELETE to delete all rows in the table, the next assigned value for the identity column is the new reseed value + the current increment
  • When you use TRUNCATE, the next assigned value for the identity column is the initial seed value.

Take a look at the article above for more details on the tests that were run.

Conclusion

Using an identity column for an auto-generating primary key is a great feature. The values of the identity column shouldn’t matter so it doesn’t matter if they are not continuous. But if you really need to make them continuous, you can reset them without dropping and recreating the table using the steps in this article.

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

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

16 ответов

Лучший ответ

Невозможно обновить столбец идентификации.

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


330

Community
20 Июн 2020 в 12:12

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

update table
set identity_column_name = some value

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

Но вот шаги, чтобы сделать это. Возьмите back-up стол

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

enter image description here

Шаг 2 — Отключите столбец идентичности

enter image description here

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

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

Ссылка < / сильный>


75

Prahalad Gaggar
3 Окт 2013 в 14:00

Вам нужно

set identity_insert YourTable ON

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

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

set identity_insert YourTable OFF


66

R S P
3 Окт 2013 в 15:57

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


26

kuklei
2 Апр 2015 в 14:47

Попробуйте использовать DBCC CHECKIDENT:

DBCC CHECKIDENT ('YourTable', RESEED, 1);


14

Darren
3 Окт 2013 в 13:41

DBCC CHECKIDENT(table_name, RESEED, value)

Table_name = укажите таблицу, значение которой вы хотите сбросить

Value = начальное значение должно быть нулевым, чтобы начать столбец идентификатора с 1


5

Igor Borisenko
4 Апр 2014 в 11:50

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

    select columns into newtable from yourtable

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

    ALTER TABLE tableName ADD id MEDIUMINT NOT NULL AUTO_INCREMENT KEY


5

user4002899
3 Сен 2014 в 10:41

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 не позволит вам вставить без их указания


4

befree2j
15 Апр 2019 в 14:45

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

Примере:

SET IDENTITY_INSERT dbo.Tool ON
GO

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


3

DaveShaw
3 Окт 2013 в 13:43

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

Jekin Kalariya
27 Сен 2018 в 10:13

Полное решение для программистов на 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( "rnINSERT 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 ();
}


1

Dale K
10 Сен 2019 в 05:58

Я решил эту проблему сначала с помощью 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. Затем вы можете удалить повторяющиеся строки с более высоким значением идентификатора после того, как вы удалили / переместили их ссылки на внешние ключи, если таковые имеются.


0

Softec
14 Апр 2014 в 15:46

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

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

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


0

Sean H. Worthington
30 Авг 2016 в 02:05

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

РЕДАКТИРОВАТЬ: более новые версии SQL не позволяют изменять сущность syscolumns, поэтому часть моего решения должна выполняться жестким путем. Обратитесь к этому SO о том, как вместо этого удалить Identity из первичного ключа: Удалить идентификатор из столбца в таблице Этот сценарий отключит идентификацию на ПК:

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

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 на 1000000:

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 / FK не конфликтовали. FK метаданных идентичны.


0

Ken Forslund
4 Янв 2021 в 23:10

У меня была аналогичная проблема, мне нужно было обновить некоторые идентификаторы, что я сделал (мне нужно было увеличить их на 10k):

set identity_insert YourTable ON

INSERT INTO YourTable 
   ([ID]
   ,[something1]
   ,[something2]
   ,[something3])
SELECT 
   ([ID] + 10000)
   ,[something1]
   ,[something2]
   ,[something3]) 
FROM YourTable
WHERE something1 = 'needs updeted id' 
   AND something2 = 'some other condition'

set identity_insert YourTable OFF

DELETE FROM YourTable 
WHERE ID >= 'your old ID From' 
   AND ID <= 'Your old ID To' 

И это все. Надеюсь, вы понимаете эту логику, в моем случае было также соединение ключей PK-FK с другими таблицами, что означало, что мне пришлось обновить их, прежде чем я смогу удалить из исходных строк 'YourTable'.

Я знаю, что на это уже есть ответы, я просто хотел оставить SQL-запрос в качестве примера,


0

Dharman
27 Май 2021 в 00:37

Я сделал следующее:

  1. ПЕРЕМЕСТИТЬ связанные данные во временное хранилище
  2. ОБНОВЛЕНИЕ значения столбца первичного ключа / идентификатора (удаление и создание ограничений)
  3. RE-INSERT связанные данные с новым значением внешнего ключа

Я заключил свое решение в СОХРАНЕННУЮ ПРОЦЕДУРУ:

CREATE PROCEDURE [dbo].[UpdateCustomerLocationId]
    @oldCustomerLocationId INT,
    @newCustomerLocationId INT
AS
  /* 
    Updates CustomerLocation.CustomerLocationId @oldCustomerLocationId to @newCustomerLocationId
    
    Example:
        EXEC [dbo].[UpdateCustomerLocationId] 
            @oldCustomerLocationId = 6154874, 
            @newCustomerLocationId = 50334;
    */

BEGIN

    SET NOCOUNT ON;
    
    -- exit if @oldCustomerLocationId does not exists
    IF NOT EXISTS (SELECT * FROM dbo.CustomerLocation cl WHERE cl.CustomerLocationId = @oldCustomerLocationId)
    BEGIN
        PRINT CONCAT('CustomerLocationId ''', @oldCustomerLocationId, ''' (@oldCustomerLocationId) does not exist in dbo.CustomerLocation');
        RETURN 1; -- 0 = success, > 0 = failure
    END

    -- exit if @newCustomerLocationId already exists
    IF EXISTS (SELECT * FROM dbo.CustomerLocation cl WHERE cl.CustomerLocationId = @newCustomerLocationId)
    BEGIN
        PRINT CONCAT('CustomerLocationId ''', @newCustomerLocationId, ''' (@newCustomerLocationId) already exists in dbo.CustomerLocation');
        RETURN 2; -- 0 = success, > 0 = failure
    END
    

    BEGIN TRAN;


        BEGIN -- MOVE related data into temporary storage

            IF EXISTS (SELECT * FROM dbo.CustomerLocationData t WHERE t.CustomerLocationId = @oldCustomerLocationId) BEGIN
    
                IF OBJECT_ID('tempdb..#CustomerLocationData') IS NOT NULL
                    DROP TABLE #CustomerLocationData;

                SELECT * INTO #CustomerLocationData FROM dbo.CustomerLocationData t WHERE t.CustomerLocationId = @oldCustomerLocationId;
                DELETE t FROM dbo.CustomerLocationData t WHERE t.CustomerLocationId = @oldCustomerLocationId;

            END

        END


        BEGIN -- UPDATE dbo.CustomerLocation

            -- DROP CONSTRAINTs
            ALTER TABLE [dbo].[CustomerLocation] DROP CONSTRAINT [UC_CustomerLocation];

            -- INSERT OLD record with new CustomerLocationId
            SET IDENTITY_INSERT dbo.CustomerLocation ON;

            INSERT INTO dbo.CustomerLocation
            (
                CustomerLocationId, CustomerId, LocationId, CustomerLocationIdent, CustomerLocationIdent2, LocationIdent, LocationName, CustomerDistrictId, 
                CustomerLocationGUID, UpdatedOn, IssueManager, EnrollSelfMonitoring, TemperatureControlDeadlineHour, CreatedOn, OperationBegin, ActiveCustomer, 
                Comments, LocationName2, ParentGroup, TempString1, TempString2, TempString3, TempString4, TempString5, AutoInheritFromLocation, ClassificationPrimary
            )
            SELECT @newCustomerLocationId AS CustomerLocationId, CustomerId,LocationId, CustomerLocationIdent, CustomerLocationIdent2, LocationIdent, LocationName, CustomerDistrictId,
                CustomerLocationGUID, UpdatedOn, IssueManager, EnrollSelfMonitoring, TemperatureControlDeadlineHour, CreatedOn, OperationBegin, ActiveCustomer,
                Comments,LocationName2, ParentGroup, TempString1, TempString2, TempString3, TempString4, TempString5, AutoInheritFromLocation, ClassificationPrimary
            FROM dbo.CustomerLocation 
            WHERE CustomerLocationId = @oldCustomerLocationId;

            SET IDENTITY_INSERT dbo.CustomerLocation OFF;

            -- DELETE OLD record
            DELETE cl FROM dbo.CustomerLocation cl WHERE cl.CustomerLocationId = @oldCustomerLocationId;

            -- ADD CONSTRAINTS
            ALTER TABLE [dbo].[CustomerLocation] ADD CONSTRAINT [UC_CustomerLocation] UNIQUE NONCLUSTERED ([CustomerId], [LocationId]);

        END


        BEGIN -- re-INSERT related data from temporary storage

            IF OBJECT_ID('tempdb..#CustomerLocationData') IS NOT NULL BEGIN
                SET IDENTITY_INSERT dbo.CustomerLocationData ON;
                INSERT INTO dbo.CustomerLocationData (Guid, CustomerLocationId, CustomerLocationDataTypeId, Date, Category, Data)
                SELECT Guid, @newCustomerLocationId CustomerLocationId, CustomerLocationDataTypeId, Date, Category, Data FROM #CustomerLocationData;
                SET IDENTITY_INSERT dbo.CustomerLocationData OFF;
            END

        END


    COMMIT TRAN;

END


0

mortenma71
31 Окт 2021 в 00:54

Понравилась статья? Поделить с друзьями:
  • Sql вызов ошибки
  • Sql вызвать ошибку
  • Sql validation error
  • Sql error 1054 42s22 unknown column name in field list
  • Sql error 1052 23000 column id in field list is ambiguous