Kimlik sütunu değerleri programlı olarak nasıl değiştirilir?


160

TestSütun içeren bir tablo ile bir MS SQL 2005 veritabanı var ID. IDbir kimlik sütunu.

Bu tablodaki satırları var ve hepsinin karşılık gelen kimliği otomatik artan değeri var.

Şimdi bu tablodaki her kimliği şu şekilde değiştirmek istiyorum:

ID = ID + 1

Ama bunu yaptığımda bir hata alıyorum:

'ID' kimlik sütunu güncellenemiyor.

Bunu denedim:

    ALTER TABLE Test NOCHECK CONSTRAINT ALL 
    set identity_insert ID ON

Ancak bu sorunu çözmez.

Ben bu sütuna ayarlanmış kimlik olması gerekir, ama zaman zaman değerleri de değiştirmek gerekiyor. Benim sorum bu görevi nasıl yerine getireceğidir.

Yanıtlar:


220

Gerek

set identity_insert YourTable ON

Ardından satırınızı silin ve farklı bir kimlikle yeniden yerleştirin.

Ekleme işlemini yaptıktan sonra identity_insert'i kapatmayı unutmayın

set identity_insert YourTable OFF

133
bu ayar yalnızca veri eklenirken çalışır, güncelleme sırasında çalışmaz. UPDATE deyimi yine başarısız olur.
Husein Roncevic

31
Güncelleme için silmeniz ve tekrar eklemeniz gerekir. Başka yol yok.
ashes999

1
@MartinSmith çözümünüz çok uzun görünüyor. İki adımda (kimlik kapatma, silme / ekleme, kimlik açma) yapabilmek çok daha etkilidir.
ashes999

3
@ ashes999 Bu 4 adım değil 2. Cevabım sadece bir tane daha (tablo oluşturma, değiştirme, güncelleme, geri dönme, bırakma). Güncelleme çok daha verimli olabilir ve birçok satır söz konusu olduğunda eki silebilirsiniz. Ayrıca silinen satırları nerede tutuyorsunuz? Eğer #tempdüşürdüğünüz bir masa bu başka bir adımsa, burada saymadınız.
Martin Smith

40

IDENTITY sütun değerleri değiştirilemez.

Ancak, IDENTITYözelliği kaldırmak , güncellemeyi yapmak ve sonra geri dönmek için tablo meta verilerini değiştirmek mümkündür .

Aşağıdaki yapıyı varsayarsak

CREATE TABLE Test
(
ID INT IDENTITY(1,1) PRIMARY KEY,
X VARCHAR(10)
)

INSERT INTO Test 
OUTPUT INSERTED.*
SELECT 'Foo' UNION ALL
SELECT 'Bar' UNION ALL
SELECT 'Baz'

Sonra yapabilirsin

/*Define table with same structure but no IDENTITY*/
CREATE TABLE Temp
(
ID INT PRIMARY KEY,
X VARCHAR(10)
)

/*Switch table metadata to new structure*/
ALTER TABLE Test SWITCH TO Temp;

/*Do the update*/
UPDATE Temp SET ID = ID + 1;

/*Switch table metadata back*/
ALTER TABLE Temp SWITCH TO Test;

/*ID values have been updated*/
SELECT *
FROM Test

/*Safety check in case error in preceding step*/
IF NOT EXISTS(SELECT * FROM Temp)
    DROP TABLE Temp /*Drop obsolete table*/

SQL Server 2012'de, daha basit bir şekilde güncellenebilen bir otomatik artan sütuna sahip olmak mümkündür SEQUENCES

CREATE SEQUENCE Seq
    AS INT
    START WITH 1
    INCREMENT BY 1

CREATE TABLE Test2
(
ID INT DEFAULT NEXT VALUE FOR Seq NOT NULL PRIMARY KEY,
X VARCHAR(10)
)

INSERT INTO Test2(X)
SELECT 'Foo' UNION ALL
SELECT 'Bar' UNION ALL
SELECT 'Baz'

UPDATE Test2 SET ID+=1

1
Çok kaygan. Her gün yeni bir şey öğrenin (BTW SQLExpress'te test ettim; görünüşe göre bölümleme kullanmıyor olmasına rağmen). Tablonun hemen hemen tam olarak eşleşmesi gerektiğini unutmayın (dizinler, FK'ler, vb.)
Mark Sowul

1
Orijinal tabloya PK, FK, Dizin ve Görünümler yüklendiğinde anahtar yöntemi çalışıyor mu? Bu yöntemi kullanarak kırılacaklar mı?
tj

1
@tj geçici tablo komut dosyasını oluştururken tüm dizinleri ve kısıtlamaları içeren kaynak tabloyu dışa aktarın. Sonra çarpışmaları önlemek için tablonun adlarını ve kısıtlamaları değiştirin. Dizine eklenmemiş veya şemada olmadığı sürece görünümler soruna neden olmaz.
Martin Smith

Tabloda tam metin arama dizini varsa çalışmaz. Sanırım daha sonra kaldırmak ve yeniden oluşturmak mümkün, ancak test etmedim.
Youen

26

SQL Server 2005 yöneticisindeki kullanıcı arayüzü aracılığıyla, sütunu değiştirin ve sütunun otomatik numara (kimlik) özelliğini kaldırın (tabloyu sağ tıklayarak seçin ve "Tasarım" ı seçin).

Ardından sorgunuzu çalıştırın:

UPDATE table SET Id = Id + 1

Ardından gidip autonumber özelliğini sütuna geri ekleyin.


3
Değişikliği manuel olarak yaparsanız, yöneticiden değişiklik için SQL komut dosyasını oluşturmasını isteyebilirsiniz (tablo tasarımcısı menüsü, değişiklik komut dosyası oluştur). Bu değişiklik için yeni bir tablo oluşturur ve verileri karşıya kopyalar, ardından orijinali siler.
Robin Bennett

2
@tomaszs - Fiziksel olarak tabloyu hiç yeniden oluşturmadığı için bu daha verimli bir kod örneği (bu iki kez yapar) burada
Martin Smith

Kimliği geri ekleyemezsiniz. Yapıyor musun? stackoverflow.com/questions/1049210/…
Tomas Kubes

Teşekkürler. Bu mükemmeldi. Masamda farkında olmadığım 1 satır vardı, bu yüzden masamın bootstrap komut dosyalarında 1 ile IdOtomatik Kimlik değerleri vardı .
Shiva

18

Öncelikle bu konuda IDENTITY_INSERT ayarının açık veya kapalı olması, ihtiyacınız olan şey için işe yaramaz (boşlukları tıkamak gibi yeni değerler eklemek için kullanılır).

İşlemi GUI üzerinden yapmak yalnızca geçici bir tablo oluşturur, tüm verileri kimlik alanı olmadan yeni bir tabloya kopyalar ve tabloyu yeniden adlandırır.


9

Bu geçici bir tablo kullanılarak yapılabilir.

Fikir

  • kısıtlamaları devre dışı bırak (kimliğinize yabancı bir anahtarla başvurulması durumunda)
  • yeni kimliğe sahip geçici tablo oluşturma
  • tablo içeriğini sil
  • kopyalanan tablodan orijinal tablonuza veri kopyalayın
  • önceden devre dışı bırakılmış kısıtlamaları etkinleştir

SQL Sorguları

Let senin söylemek testtablo iki ek sütunlar (varsa column2ve column3) ve 2 referanslanmasına yabancı anahtarları olan tablolar olduğunu testadlandırılan foreign_table1ve foreign_table2(gerçek hayat sorunları basit asla çünkü).

alter table test nocheck constraint all;
alter table foreign_table1 nocheck constraint all;
alter table foreign_table2 nocheck constraint all;
set identity_insert test on;

select id + 1 as id, column2, column3 into test_copy from test v;
delete from test;
insert into test(id, column2, column3)
select id, column2, column3 from test_copy

alter table test check constraint all;
alter table foreign_table1 check constraint all;
alter table foreign_table2 check constraint all;
set identity_insert test off;
drop table test_copy;

Bu kadar.


6

DBCC CHECKIDENT ('databasename.dbo.orders', RESEED, 999) bu komutla herhangi bir kimlik sütunu numarasını değiştirebilir ve ayrıca bu alan numarasını istediğiniz her numaradan başlatabilirsiniz. Örneğin komutumda 1000 (999 + 1) yeterli olacağını umuyoruz ... iyi şanslar


4

Sütun bir PK değilse, tabloda her zaman artan sayılarla YENİ bir sütun oluşturabilir, orijinali bırakabilir ve ardından yenisini eski olacak şekilde değiştirebilirsiniz.

neden bunu yapmanız gerekebilir merak ediyorum ... şimdiye kadar kimlik sütunları ile futz zorunda en çok sayıları doldurmak oldu ve ben sadece DBCC CHECKIDENT (tablename, RESEED, newnextnumber) kullanarak sona erdi

iyi şanslar!


1

Kimlik değiştirme, temel olarak kimlik sütununa bağlı nesneler / ilişkiler etrafında dönen bir dizi faktöre bağlı olarak başarısız olabilir. Görünüşe göre db tasarım burada sorun olarak id gibi nadiren hiç değiştirmek gerekir (nedenleri var eminim ve değişiklikleri cascasding). Kimlikleri gerçekten zaman zaman değiştirmeniz gerekiyorsa, kendinizi yönetebileceğiniz ve geçerli değerlerden oluşturabileceğiniz birincil anahtar / otomatik sayı olmayan yeni bir kukla kimlik sütunu oluşturmanızı öneririm. Alternatif olarak, kimlik eklemeye izin verme konusunda sorun yaşıyorsanız yukarıdaki Chrisotphers fikri benim diğer önerim olacaktır.

İyi şanslar

PS, çalıştığı sıralı sipariş, listedeki bir değeri kimlik listesinde zaten var olan bir öğeye güncellemeye çalıştığı için başarısız değil mi? payetlere tutarak belki + 1 satır sayısını ekleyin, eğer işe yararsa satır sayısını çıkarın: -S


1

Kimlikleri zaman zaman değiştirmeniz gerekirse, muhtemelen bir kimlik sütunu kullanmamak en iyisidir. Geçmişte, her tablo için bir sonraki kimliği izleyen bir 'Sayaçlar' tablosu kullanarak otomatik numara alanlarını manuel olarak uyguladık. Bunu, kimlik sütunlarının SQL2000'de veritabanı bozulmasına neden olduğu, ancak kimliklerini değiştirebilmesinin test için bazen yararlı olduğu için bunu yaptık.


1

Değiştirilmiş değerlere sahip yeni satırlar ekleyebilir ve ardından eski satırları silebilirsiniz. Aşağıdaki örnek kimliği yabancı anahtar PersonId ile aynı olacak şekilde değiştirin

SET IDENTITY_INSERT [PersonApiLogin] ON

INSERT INTO [PersonApiLogin](
       [Id]
      ,[PersonId]
      ,[ApiId]
      ,[Hash]
      ,[Password]
      ,[SoftwareKey]
      ,[LoggedIn]
      ,[LastAccess])
SELECT [PersonId]
      ,[PersonId]
      ,[ApiId]
      ,[Hash]
      ,[Password]
      ,[SoftwareKey]
      ,[LoggedIn]
      ,[LastAccess]
FROM [db304].[dbo].[PersonApiLogin]
GO

DELETE FROM [PersonApiLogin]
WHERE [PersonId] <> ID
GO
SET IDENTITY_INSERT [PersonApiLogin] OFF
GO

1

Önce tüm kimlikleri kaydedin ve programlı olarak istemediğiniz değerlere değiştirin, sonra veritabanından kaldırın ve sonra benzer bir şey kullanarak tekrar ekleyin:

use [Name.Database]
go
set identity_insert [Test] ON
insert into [dbo].[Test]
           ([Id])
     VALUES
           (2)
set identity_insert [Test] OFF

Toplu kesici uç kullanımı için:

use [Name.Database]
go
set identity_insert [Test] ON
BULK INSERT [Test]
FROM 'C:\Users\Oscar\file.csv'
WITH (FIELDTERMINATOR = ';',
      ROWTERMINATOR = '\n',
      KEEPIDENTITY)
set identity_insert [Test] OFF

File.csv dosyasındaki örnek veriler:

2;
3;
4;
5;
6;

identity_insertKapalı olarak ayarlamazsanız aşağıdaki hatayı alırsınız:

IDENTITY_INSERT KAPALI olarak ayarlandığında 'Test' tablosuna kimlik sütunu için açık değer eklenemiyor.


0

Son anda bana yardımcı olan iyi bir makale gördüm .. Kimlik sütununa sahip bir tabloya birkaç satır eklemeye çalışıyordum ama yanlış yaptım ve silmem gerekiyordu. Satırları sildikten sonra kimlik sütunum değişti. Takılan sütunu güncellemek için bir yol bulmaya çalışıyordum ama - şanssız. Google'da arama yaparken bir bağlantı buldu ..

  1. Yanlış yerleştirilmiş sütunları sildi
  2. Kimlik açık / kapalı kullanarak zorla ekleme kullanın (aşağıda açıklanmıştır)

http://beyondrelational.com/modules/2/blogs/28/posts/10337/sql-server-how-do-i-insert-an-explicit-value-into-an-identity-column-how-do- i-güncelleme-değer-of-an.aspx


1
Yine de buradaki soruyu gerçekten cevapladığınızdan emin değilim.
Andrew Barber

0

Çok güzel bir soru, ilk önce belirli bir tablo için IDENTITY_INSERT üzerinde , sonra ekleme sorgusu çalıştırmak gerekir (sütun adı belirtilmelidir).

Not: Kimlik sütununu düzenledikten sonra IDENTITY_INSERT ürününü kapatmayı unutmayın . Bunu yapmadıysanız, başka bir tablonun kimlik sütununu düzenleyemezsiniz.

SET IDENTITY_INSERT Emp_tb_gb_Menu ON
     INSERT Emp_tb_gb_Menu(MenuID) VALUES (68)
SET IDENTITY_INSERT Emp_tb_gb_Menu OFF

http://allinworld99.blogspot.com/2016/07/how-to-edit-identity-field-in-sql.html

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.