Mevcut bir sütuna kimlik ekleme


445

Bir tablonun birincil anahtarını bir kimlik sütununa değiştirmem gerekiyor ve zaten tablodaki bir dizi satır var.

1 den başlayarak sıralı olduklarından emin olmak için kimlikleri temizlemek için bir komut dosyası var, test veritabanımda iyi çalışıyor.

Sütunu bir kimlik özelliğine sahip olacak şekilde değiştirmek için SQL komutu nedir?

Yanıtlar:


482

Varolan sütunları kimlik için değiştiremezsiniz.

2 seçeneğiniz var,

  1. Kimliğe sahip yeni bir tablo oluşturun ve mevcut tabloyu bırakın

  2. Kimlikle yeni bir sütun oluşturun ve mevcut sütunu bırakın

Yaklaşım 1. ( Yeni tablo ) Burada, yeni oluşturulan kimlik sütununda mevcut veri değerlerini koruyabilirsiniz.

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'

Yaklaşım 2 ( Yeni sütun ) Yeni oluşturulan kimlik sütununda mevcut veri değerlerini tutamazsınız, Kimlik sütunu sayı dizisini tutacaktır.

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'

Daha fazla ayrıntı için aşağıdaki Microsoft SQL Server Forum yayınına bakın:

Sütunu kimliğe değiştirme (1,1)


49
Tablo verileri küçükse, bu seçenek gret çalışır. Tablo büyükse, tercih ettiğim başka bir seçenek daha vardır: tablo şemasını bir IDENTITY sütunuyla başka bir sürümle değiştirmek için ALTER TABLE ... SWITCH komutunu kullanın, aksi takdirde aynı şema. ALTER TABLE .... SWITCH yaklaşımının avantajı, hiçbir tablo verisinin kopyalanmasına veya değiştirilmesine gerek olmadığından hızlı bir şekilde tamamlanmasıdır (milyar satırlık bir tablo için 5 saniyenin altında). Ancak uyarılar ve sınırlamalar vardır. Ayrıntılar için aşağıdaki cevabıma bakın.
Justin Grant

7
@ Justin Grat: Çok ilginç bir alternatif ve hiç düşünmediğim bir alternatif! Bunun nedeni, IDENTITY öğesinin veri türü değil, bir sütun özelliği olmasıdır, bu nedenle SWITCH yöntemi, IDENTITY farkından bağımsız olarak iki tablo arasındaki (eski ve yeni) şemaları doğrular. Paylaşım için teşekkürler!
John Sansom

Çok fazla veriye sahip değilseniz, SSMS'den bir komut dosyası oluşturarak "tablo oluşturmak" elde edilebilir. Tablo> Komut Dosyası tablosu>> TABLO Oluştur> (yeni sorgu düzenleyicisi?) Seçeneğini sağ tıklayın. Sonra bırakın ve bu komut dosyasının içine IDENTITY(1, 1)parçayı birincil anahtar sütunu ile ekleyebilirsiniz
goamn

Bunu uygulamak için SSMS de kullanılabilir. Araçlar> Seçenekler> Tasarımcılar> "Yeniden tablo oluşturma gerektiren değişiklikleri kaydetmeyi engelle" seçeneğinin işaretini kaldırın. BTW bu oldukça büyük tablolar için önerilmez.
Zafar

PostgreSQL'de Eğer olabilir komutu ile var olan bir tam sayı kolonuna kimlik ekleyin: alter tablo her bir kimlik olarak üretilen ekleyin {tablo_adı} alter kolon {column_name} ile (yeniden {sayı});
Andrew Mackie

209

SQL 2005 ve sonraki sürümlerde, tablonun veri sayfalarını değiştirmeden bu sorunu çözmek için bir hile vardır. Bu, her veri sayfasına dokunmanın dakikalar veya saatler sürebileceği büyük tablolar için önemlidir. Hile, kimlik sütunu birincil anahtar olsa da, kümelenmiş veya kümelenmemiş bir dizinin parçası veya daha basit "ekle / kaldır / yeniden adlandır sütunu" çözümünü açabilen diğer gotcha'lar olsa bile çalışır.

İşte püf noktası : SQL Server'ın ALTER TABLE ... SWITCH deyimini, verileri değiştirmeden bir tablonun şemasını değiştirmek için kullanabilirsiniz; başka bir deyişle, IDENTITY olan bir tabloyu aynı tablo şemasıyla, ancak IDENTITY sütunu olmadan değiştirebilirsiniz. Aynı hile, mevcut bir sütuna KİMLİK eklemek için de geçerlidir.

Normalde, ALTER TABLE ... SWITCH , bölümlenmiş bir tablodaki tam bölümün yerine yeni, boş bir bölümün verimli bir şekilde değiştirilmesi için kullanılır. Ancak bölümlenmemiş tablolarda da kullanılabilir.

Bu hileyi, 5 saniyenin altında, 2.5 milyar satırlık bir sütunun kimliğini KİMLİK'ten KİMLİK olmayan bir duruma dönüştürmek için kullandım (sorgu planı KİMLİK olmayanlar için daha iyi çalışan çok saatlik bir sorguyu çalıştırmak için) sütunları) ve ardından IDENTITY ayarını tekrar 5 saniyeden daha kısa sürede geri yükledi.

İşte nasıl çalıştığına dair bir kod örneği.

 CREATE TABLE Test
 (
   id int identity(1,1),
   somecolumn varchar(10)
 );

 INSERT INTO Test VALUES ('Hello');
 INSERT INTO Test VALUES ('World');

 -- copy the table. use same schema, but no identity
 CREATE TABLE Test2
 (
   id int NOT NULL,
   somecolumn varchar(10)
 );

 ALTER TABLE Test SWITCH TO Test2;

 -- drop the original (now empty) table
 DROP TABLE Test;

 -- rename new table to old table's name
 EXEC sp_rename 'Test2','Test';

 -- update the identity seed
 DBCC CHECKIDENT('Test');

 -- see same records
 SELECT * FROM Test; 

Bu açıkçası diğer cevaplardaki çözümlerden daha fazla söz konusudur, ancak tablonuz büyükse bu gerçek bir hayat kurtarıcı olabilir. Bazı uyarılar var:

  • Bildiğim kadarıyla kimlik, bu yöntemle tablonuzun sütunları hakkında değiştirebileceğiniz tek şey. Sütun eklemeye / kaldırmaya, nullabiliteyi değiştirmeye vb.
  • Geçişi yapmadan önce yabancı anahtarları bırakmanız ve sonra geri yüklemeniz gerekir.
  • SCHEMABINDING işlevleri, görünümleri vb.İLE aynı.
  • yeni tablonun dizinlerinin tam olarak eşleşmesi gerekir (aynı sütunlar, aynı sipariş vb.)
  • Eski ve yeni tabloların aynı dosya grubunda olması gerekir.
  • Yalnızca SQL Server 2005 veya sonraki sürümlerinde çalışır
  • Daha önce bu hile sadece SQL Server'ın Enterprise veya Developer sürümlerinde çalıştığına inanıyordum (çünkü bölümler sadece Enterprise ve Developer sürümlerinde destekleniyor), ancak aşağıdaki yorumunda Mason G. Zhwiti de SQL Standard Edition'da da çalıştığını söylüyor. Bunun Kurumsal veya Geliştirici kısıtlamasının ALTER TABLE ... SWITCH için geçerli olmadığı anlamına gelir.

TechNet'te yukarıdaki gereksinimleri ayrıntılı olarak anlatan iyi bir makale var .

GÜNCELLEME - Eric Wu , aşağıda bu çözüm hakkında önemli bilgiler ekleyen bir yorum yaptı. Daha fazla dikkat çekmek için buraya kopyalamak:

Burada bahsetmeye değer başka bir uyarı var. Her ne kadar yeni tablo eski tablodan mutlu bir şekilde veri alacak olsa da ve tüm yeni satırlar bir kimlik modelinin ardından eklenecek olsa da, söz konusu sütun birincil anahtarsa ​​1'den başlayacak ve potansiyel olarak kesilecektir. Geçişten DBCC CHECKIDENT('<newTableName>')hemen sonra çalışmayı düşünün . Daha fazla bilgi için msdn.microsoft.com/en-us/library/ms176057.aspx adresine bakın .

Tablo aktif olarak yeni satırlarla genişletiliyorsa (yani, KİMLİK ekleme ile yeni satır ekleme arasında herhangi bir kesinti süreniz DBCC CHECKIDENTyoksa, yani yeni tablo şemasındaki kimlik çekirdeği değerini manuel olarak ayarlamak istersiniz. Tablodaki mevcut en büyük kimliğe göre daha büyüktür, ör IDENTITY (2435457, 1). Hem ALTER TABLE...SWITCHve hem de DBCC CHECKIDENTbir işleme dahil edebilirsiniz (veya test etmediniz - bunu test etmediniz), ancak tohum değerini manuel olarak ayarlamak daha kolay ve daha güvenli olacaktır.

Açıkçası, tabloya yeni satır eklenmiyorsa (veya günlük ETL işlemi gibi yalnızca ara sıra eklenirse), bu yarış durumu gerçekleşmez, bu yüzden DBCC CHECKIDENTiyi.


5
Hafızam doğruysa, bu makaleden fikri aldım: sqlservercentral.com/articles/T-SQL/61979
Justin Grant

2
Bilginize, bu aynı zamanda SQL 2008 R2'nin Standart sürümü üzerinde de çalışıyor gibi görünüyor. Belki de bu özelliği şimdi yedek sıkıştırmayı açma yeteneğini etkinleştirmiş gibi etkinleştirdiler.
Mason G.Zhwiti

3
@jbatista - OP'nin sorusu zaten masada birincil bir anahtarının olduğunu ve zaten doğru değerleri sağlayabileceğini belirtti, ancak sadece bir KİMLİK sütunu olarak değiştirmek istedi. Yukarıdaki cevabım bu dar kullanım senaryosuna odaklanıyor: herhangi bir veriyi değiştirmeden kimliğe nasıl IDENTITY eklenir. Yukarıda belgelediğim yaklaşım büyük tablolar için büyük bir zaman tasarrufu. Verileri değiştirmeniz gerekiyorsa, diğer çözümleri kullanmanız gerekir.
Justin Grant

3
Burada bahsetmeye değer başka bir uyarı var. Yeni tablo, eski tablodan mutlu bir şekilde veri alacak ve tüm yeni satırlar bir kimlik modelinin ardından eklenecek , söz konusu sütun birincil anahtarsa , 1'den başlayacak ve potansiyel olarak kesilecektir. Geçişten DBCC CHECKIDENT('<newTableName>')hemen sonra çalışmayı düşünün . Daha fazla bilgi için msdn.microsoft.com/en-us/library/ms176057.aspx adresine bakın .
Eric Wu

3
Bu harika bir cevap! Ayrıca sütunların geçersizliğinin aynı olması gerektiğini unutmayın. Bu nedenle, bir sütun oynaklığını değiştirmeniz gerekirse, bunu daha sonraki bir adımda yapmanız gerekir. PK kısıtlamaları için de aynı şey geçerlidir. Ayrıca tablo oluşturmadaki kimlik değerini geçerli maksimum değerle eşleşecek şekilde değiştiriyorum: IDENTITY (maxID + 1, 1)
Philippe

71

Bir sütunu KİMLİK sütunu olarak değiştiremezsiniz. Yapmanız gereken, hareket halindeyken bir KİMLİK olarak tanımlanan yeni bir sütun oluşturmak, ardından eski sütunu bırakmak ve yeni sütunu eski adla yeniden adlandırmaktır.

ALTER TABLE (yourTable) ADD NewColumn INT IDENTITY(1,1)

ALTER TABLE (yourTable) DROP COLUMN OldColumnName

EXEC sp_rename 'yourTable.NewColumn', 'OldColumnName', 'COLUMN'

üzüm posası


\ @Objname parametresi belirsiz veya talep edilen \ @objtype (COLUMN) yanlış.
Jenny O'Reilly

1
@ JennyO'Reilly: Bunu ayrı bir soruya koyun ve bize kullandığınız komutun tamamını gösterin !
marc_s

2
Başarısız olan sp_rename yordamıydı. Hata metnini arayarak stackoverflow üzerinde bir çözüm buldum. Tablonuzun adında özel karakterler bulunmamasına rağmen, parantez içeren bazı katı sözdizimi kuralı gibi görünüyor.
Jenny O'Reilly

1
ya da şöyle olabilir: 'ALTER TABLE (yourTable) DROP COLUMN OldColumnName' ve 'ALTER TABLE (yourTable) ADD OldColumnName INT IDENTITY (1,1)', neden yeniden adlandırın: p
RK Sharma

Marc, bu komutu büyük bir masada (~ 300 milyon satır) denedim, ancak ~ 10 dakika sonra süreci durdurdum
Naomi

14

Burada açıklanan harika bir çözüm var: SQL SERVER - Sütuna Kimlik Özelliği Ekle veya Kaldır

Kısacası SQL Manager'da tablonuzu manuel olarak düzenleyin, kimliği değiştirin, değişiklikleri KAYDETMEYİN, sadece değişiklikler için oluşturulacak komut dosyasını gösterin, kopyalayın ve daha sonra kullanın.

Büyük bir zaman tasarrufu, çünkü (script) değiştirdiğiniz tabloyla ilgili tüm yabancı anahtarları, endeksleri vb. İçerir. Bunu el ile yazmak ... Tanrı korusun.


bu benim kullandığım çözümdür - SSMS, değişikliği yapmak için T-SQL'i üretir ... bunu aynı şema tasarımının yeni bir geçici tablosunu oluşturarak, ardından tüm satırları içine kopyalayarak, orig'i kaldırarak ve yeniden adlandırarak yapar . tamamen çalışması biraz zaman alabilir ama mükemmel çalıştı.
mdelvecchio

Pinal Dave'in aslında oluşturduğunuz senaryoyu çalıştırmanız gerektiğini söylediğini sanmıyorum, sadece kullanıcı arayüzünde değişiklik yapmanın sizin için ne yaptığını göstermek için ...
Zack

SSMS'deki bu komut dosyası oluşturma kolaylığı (bir tablonun tanımını değiştirerek) bölümlenmiş bir tabloyu belgelendirirken tek doğru tesistir. En uygun konum 'görev' -> 'kod tablosu' her zaman bölümleme fonksiyonunu kodlamayı unutur!
Martijn van der Jagt

1
Birisi için yararlı olabilir. Değişikliklerden sonra Değişiklik Komut Dosyasını almak için. SSMS'de tasarım modunda tabloya sağ tıklayın ve "Değişiklik Komut Dosyası Oluştur" seçeneğini seçin ve komut dosyasını Yerel sürücüde kaydedin
Vijai

11

IDENTITY yerine SEQUENCE kullanmayı düşünün .

Sql server 2014 IN (daha düşük sürümler hakkında bilmiyorum) bunu sıralaması kullanarak basitçe yapabilirsiniz.

CREATE SEQUENCE  sequence_name START WITH here_higher_number_than_max_existed_value_in_column INCREMENT BY 1;

ALTER TABLE table_name ADD CONSTRAINT constraint_name DEFAULT NEXT VALUE FOR sequence_name FOR column_name

Buradan: Bir sütun için varsayılan değer olarak sıra


6

Basit açıklama

Sp_RENAME kullanarak mevcut sütunu yeniden adlandırın

EXEC sp_RENAME 'Table_Name.Existing_ColumnName', 'New_ColumnName', 'COLUMN'

Yeniden Adlandırma Örneği:

Mevcut sütun UserID, OldUserID olarak yeniden adlandırıldı

EXEC sp_RENAME 'AdminUsers.UserID' , 'OldUserID', 'COLUMN'

Ardından, birincil anahtar ve kimlik değeri olarak ayarlamak için değiştirme sorgusunu kullanarak yeni bir sütun ekleyin

ALTER TABLE TableName ADD Old_ColumnName INT NOT NULL PRIMARY KEY IDENTITY(1,1)

Birincil Anahtar Ayarlama Örneği

Yeni oluşturulan sütun adı UserID'dir

ALTER TABLE Users ADD UserID INT NOT NULL PRIMARY KEY IDENTITY(1,1)

ardından Yeniden Adlandırılan Sütunu Bırak

ALTER TABLE Table_Name DROP COLUMN Renamed_ColumnName

Yeniden adlandırılan Drop sütununa örnek

ALTER TABLE Users DROP COLUMN OldUserID

Şimdi tablodaki mevcut sütuna birincil anahtar ve kimlik ekledik.


5

Ben bir DBA'sı olmayan ve bir geliştirici olarak DBA haklarını alamadığım bir takıma katılan bir java geliştiricisiyim. Tüm şemayı iki veritabanı arasında taşımakla görevlendirildim, bu yüzden bir DBA olmadan, komut dosyaları çalıştırarak yapmalıydım, SQL Server 2008'de GUI'yi kullanamadım çünkü yönetici ayrıcalıklarına sahip değildim.

Her şey sorunsuz bir şekilde taşındı, ancak yeni schema.table üzerinde saklı bir yordam çalıştırırken, bir tablodaki kimlik alanını kaybettim buldum. Tabloyu oluşturan komut dosyasını iki kez kontrol ettim ve oradaydı, ancak komut dosyasını çalıştırdığımda SQL Server alamadı. Daha sonra bir DBA tarafından daha önce aynı sorunu gördüğünü söylediler.

Her halükarda, SQL Server 2008 için, bunlar bunu çözmek için attığım adımlar ve çalıştılar, bu yüzden burada birine yardım edeceği umuduyla burada gönderiyorum. Bunu daha zor hale getiren başka bir masada FK bağımlılıkları vardı yaptığım budur:

Bu sorgu kimliğin gerçekten eksik olduğunu doğrulamak ve tabloda bağımlılıkları görüntülemek için kullandım.

1.) Bir tablodaki istatistikleri bulun:

exec sp_help 'dbo.table_name_old';

2.) Daha önce olduğu PK alanına bir kimlik alanı eklemek dışında, aynı yeni bir tablo oluşturun.

3.) Verileri taşımak için kimliği devre dışı bırakın.

SET IDENTITY_INSERT dbo.table_name ON 

4.) Verileri aktarın.

INSERT INTO dbo.table_name_new
(
field1, field2, etc...
)
SELECT 
field1, field2, etc...
FROM 
dbo.table_name_old;

5.) Verilerin orada olduğunu doğrulayın.

SELECT * FROM dbo.table_name_new

6.) Kimliği yeniden etkinleştirin.

SET IDENTITY_INSERT ToyRecP.ToyAwards.lkpFile_New OFF

7.) Bu, özgün tablo referanslarını hangi tablo (lar) ı bağımlılıklar olarak doğrulamak için tüm FK ilişkilerini elde etmek için bulduğum en iyi komut dosyasıdır ve birçok kişiye rastladım, bu yüzden bir kaleci!

SELECT f.name AS ForeignKey,
   OBJECT_NAME(f.parent_object_id) AS TableName,
   COL_NAME(fc.parent_object_id, fc.parent_column_id) AS ColumnName,
   OBJECT_NAME (f.referenced_object_id) AS ReferenceTableName,
   COL_NAME(fc.referenced_object_id, fc.referenced_column_id) AS ReferenceColumnName
FROM sys.foreign_keys AS f
INNER JOIN sys.foreign_key_columns AS fc
   ON f.OBJECT_ID = fc.constraint_object_id
   ORDER BY ReferenceTableName;

8.) Bu sonraki adımdan önce ilgili tüm tablolar için tüm PK ve FK komut dosyalarına sahip olduğunuzdan emin olun.

9.) SQL Server 2008 kullanarak her bir tuşa sağ tıklayıp komut dosyası oluşturabilirsiniz

10.) Bu sözdizimini kullanarak FK'yi bağımlılık tablolarından ayırın:

ALTER TABLE [dbo].[table_name] DROP CONSTRAINT [Name_of_FK]

11.) Orijinal masayı düşürün:

DROP TABLE dbo.table_name_old;

13.) Bu sonraki adımlar, 9. adımda SQL Server 2008'de oluşturduğunuz komut dosyalarına dayanır.

- PK'yi yeni tabloya ekleyin.

- FK'yi yeni masaya ekleyin.

FK'yi bağımlılık tablosuna ekleyin.

14.) Her şeyin doğru ve eksiksiz olduğunu doğrulayın. Tablolara bakmak için GUI'yi kullandım.

15.) Yeni tabloyu orijinal tablo adıyla yeniden adlandırın.

exec sp_RENAME '[Schema_Name.OldTableName]' , '[NewTableName]';

Sonunda, her şey işe yaradı!


4

bu şekilde yapamazsınız, başka bir sütun eklemeniz, orijinal sütunu bırakmanız ve yeni sütunu yeniden adlandırmanız veya yeni bir tablo oluşturmanız, verileri kopyalayıp eski tabloyu bırakmanız ve ardından yeni tabloyu eski olarak yeniden adlandırmanız gerekir. tablo

SSMS kullanıyorsanız ve kimlik özelliğini tasarımcıda AÇIK olarak ayarlarsanız, SQL Server'ın perde arkasında yaptığı şey budur. Eğer [user] adında bir tablonuz varsa, UserID ve kimlik yaparsanız böyle olur

BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION

GO

GO
CREATE TABLE dbo.Tmp_User
    (
    UserID int NOT NULL IDENTITY (1, 1),
    LastName varchar(50) NOT NULL,
    FirstName varchar(50) NOT NULL,
    MiddleInitial char(1) NULL

    )  ON [PRIMARY]
GO

SET IDENTITY_INSERT dbo.Tmp_User ON
GO
IF EXISTS(SELECT * FROM dbo.[User])
 EXEC('INSERT INTO dbo.Tmp_User (UserID, LastName, FirstName, MiddleInitial)
    SELECT UserID, LastName, FirstName, MiddleInitialFROM dbo.[User] TABLOCKX')
GO
SET IDENTITY_INSERT dbo.Tmp_User OFF
GO

GO
DROP TABLE dbo.[User]
GO
EXECUTE sp_rename N'dbo.Tmp_User', N'User', 'OBJECT'
GO
ALTER TABLE dbo.[User] ADD CONSTRAINT
    PK_User PRIMARY KEY CLUSTERED 
    (
    UserID
    ) ON [PRIMARY]

GO
COMMIT

Bitwise değerini ayarlayarak bunu başarmak için sistem tablosunu kesmek için bir yol olduğunu söyledikten ancak desteklenmiyor ve bunu yapmam


4

Normal durumlarda anladığım gibi , Kimlik özelliğine sahip Birincil anahtarlı bir tablo oluşturuyoruz. Bu nedenle Birincil Anahtar kısıtlamasıyla ilişkili bir sütunu Yeniden Adlandır veya Sil mümkün olmayacak çünkü kısıtlama Kuralları sütun yapısını doğrulıyor. Aşağıdaki şekilde bazı adımlar işlemek zorunda bunu başarmak tto: alalım = 'Çalışan' TableName ve SütunAdı = 'EmployeeID' 'Çalışanın' tablo içinde 1. Ekle yeni sütun 'EmployeeId_new' ALTER tablo Çalışan ADD EmployeeId_new INT KİMLİK ( 1,1)





  1. Şimdi 'EmployeeId' sütununu 'Employee' tablosundan kaldırın
    ALTER TABLE Employee DROP COLUMN EmployeeId

  2. Birincil Anahtar Kısıtı kuralları geçerli olduğundan ve sütun yapısını doğruladığından bu hata verir.
    * ### ' Msg 5074, Seviye 16, Durum 1, Satır 1 [PK_dbo.Employee] nesnesi [EmployeeId] sütununa bağımlı.' ###

  3. Bu yüzden önce Birincil Anahtar kısıtlamasını 'Çalışan' tablosundan kaldırmalıyız, ardından ALTER TABLE Çalışan DROP kısıtlaması [PK_dbo.Employee] sütununu kaldırabiliriz.

  4. Şimdi 'EmployeeId' sütununu,
    ALTER TABLE Çalışan DAMLA COLUMN Çalışan

  5. Şimdi 'EmployeeId' sütunu tablodan kaldırıldı Bu yüzden yeni eklenen yeni 'EmployeeId_new' sütununu 'EmployeeId'
    sp_rename 'Employee.EmployeeId', 'EmployeeId_new', 'COLUMN' ile yeniden adlandıracağız

  6. Tabloyu olduğu gibi yeniden düzenlemek için, 'EmployeeId' ALTER TABLE Çalışan ekleme kısıtlaması [PK_dbo.Employee] birincil anahtarı (EmployeeId) sütunu için Ana Anahtar Kısıtlaması
    eklemeliyiz

8. Şimdi 'EmployeeId' içeren 'Employee' tablosu, mevcut birincil anahtar kısıtlamasıyla birlikte Kimlik kuralları için değiştirildi


3

Tasarım gereği, mevcut bir sütunun kimlik özelliğini açmanın veya kapatmanın basit bir yolu yoktur. Bunu yapmanın tek temiz yolu yeni bir sütun oluşturmak ve onu bir kimlik sütunu yapmak ya da yeni bir tablo oluşturmak ve verilerinizi taşımaktır.

"İd" sütunundaki kimlik değerinden kurtulmak için SQL Server Management Studio kullanırsak, yeni bir geçici tablo oluşturulur, veriler geçici tabloya taşınır, eski tablo bırakılır ve yeni tablo yeniden adlandırılır.

Değişiklik yapmak için Management Studio'yu kullanın ve ardından tasarımcıya sağ tıklayın ve "Değişiklik Betiği Oluştur" u seçin.

SQL sunucusunun arka planda yaptığı şey budur.


2

Ne yazık ki bir tane yok; IDENTITY özelliği sütuna değil tabloya aittir.

Daha kolay yol GUI'de yapmaktır, ancak bu bir seçenek değilse, verileri kopyalamak, sütunu bırakmak, kimlikle yeniden eklemek ve verileri geri koymak için uzun bir yol kat edebilirsiniz.

Bir blow-by-blow hesabı için buraya bakın .


2

Nesne Gezgini'nde tablo adına sağ tıklayın. Bazı seçenekler elde edersiniz. 'Tasarım'ı tıklayın. Bu tablo için yeni bir sekme açılacaktır. Kimlik kısıtlamasını buraya 'Sütun Özellikleri'nde ekleyebilirsiniz.


2

Bir sütunun kimlik özelliklerini değiştirmek için:

  • Sunucu Gezgini'nde, değiştirmek istediğiniz kimlik özelliklerine sahip tabloyu sağ tıklatın ve Tablo Tanımını Aç'ı tıklatın. Tablo, Tablo Tasarımcısı'nda açılır.
  • Değiştirmek istediğiniz sütun için Boş değerlere izin ver onay kutusunu temizleyin.
  • Sütun Özellikleri sekmesinde, Kimlik Belirtimi özelliğini genişletin.
  • Kimlik mi alt özelliği için ızgara hücresini tıklatın ve açılır listeden Evet'i seçin.
  • Kimlik Tohum hücresine bir değer yazın. Bu değer, tablonun ilk satırına atanacaktır. Varsayılan olarak 1 değeri atanacaktır.

Hepsi bu ve benim için çalıştı


2

Visual Studio 2017+ kullanıyorsanız

  1. Server Object Explorer'da tablonuza sağ tıklayın ve "kodu görüntüle" yi seçin
  2. "IDENTITY" değiştiricisini sütununuza ekleyin
  3. Güncelleme

Bu sizin için her şeyi yapar.


Evet! Bunu önerdiğiniz için teşekkürler! Windows 7 kutumda Üretim sunucumdaki tablolarda Tasarım değişiklikleri yapmama izin veren SSMS'nin bir sürümü yok, çünkü 2017, SSMS'm 2014 ve 2017 SSMS'nin Windows 10'a ihtiyacı var. VS 2017'ye girdim> Sunucu Gezgini> üretime yeni bir bağlantı yaptı SQL Server> masaya sağ tıklayın> "Masa Tanımı Aç"> Wala!
JustJohn

Aslında, sahaya sağ tıklayıp Özellikler'i seçebileceğinizi ve orada Evet veya Hayır'ı seçerek Kimliğinizi yapabileceğinizi
buldum

1

Orijinal poster aslında varolan bir sütunu PRIMARY KEYtablo için bir ayarlamak istiyordu ve aslında sütunun bir IDENTITYsütun (iki farklı şey) olması gerekmiyorsa, bu t-SQL ile şu şekilde yapılabilir:

ALTER TABLE [YourTableName]
ADD CONSTRAINT [ColumnToSetAsPrimaryKey] PRIMARY KEY ([ColumnToSetAsPrimaryKey])

Seçenekten sonra sütun adının etrafındaki parantezlere dikkat edin PRIMARY KEY.

Bu yazı eski olmasına ve talep edenlerin ihtiyacı hakkında bir varsayımda bulunuyorum, ancak bu ek bilgilerin, konuşmanın mevcut bir sütunun bir birincil anahtar, yeni bir sütun olarak eklenmeden yanlış olur.


1

Mevcut durumuma göre bu yaklaşımı takip ediyorum. Komut dosyası aracılığıyla veri girildikten sonra birincil tabloya kimlik vermek istiyorum.

Kimlik eklemek istediğim için, her zaman istediğim kayıt sayısının 1'den sonuna kadar başlıyor.

--first drop column and add with identity
ALTER TABLE dbo.tblProductPriceList drop column ID 
ALTER TABLE dbo.tblProductPriceList add ID INT IDENTITY(1,1)

--then add primary key to that column (exist option you can ignore)
IF  NOT EXISTS (SELECT * FROM sys.key_constraints  WHERE object_id = OBJECT_ID(N'[dbo].[PK_tblProductPriceList]') AND parent_object_id = OBJECT_ID(N'[dbo].[tblProductPriceList]'))
    ALTER TABLE [tblProductPriceList] ADD PRIMARY KEY (id)
GO

Bu, kimlikle aynı birincil anahtar sütununu oluşturur

Bu bağlantıları kullandım: https://blog.sqlauthority.com/2014/10/11/sql-server-add-auto-incremental-identity-column-to-table-after-creating-table/

Mevcut tabloya birincil anahtar ekle


0

Varolan bir sütunu tsql kullanarak kimlik sütunu olarak değiştirebileceğinize inanmıyorum. Ancak bunu Enterprise Manager tasarım görünümünden yapabilirsiniz.

Alternatif olarak, kimlik sütunu olarak yeni bir satır oluşturabilir, eski sütunu bırakıp yeni sütununuzu yeniden adlandırabilirsiniz.

ALTER TABLE FooTable
ADD BarColumn INT IDENTITY(1, 1)
               NOT NULL
               PRIMARY KEY CLUSTERED

2
SSMS / Enterprise Manager üzerinden yaparsanız yeni bir tablo oluşturacak, verileri kopyalayacak, eski tabloyu bırakacak ve yenisini yeniden adlandıracağınızı unutmayın. Büyük masalarınız olduğunda bu oldukça pahalı olabilir ...
Scott Ivey

0

Temel olarak dört mantıksal adım vardır.

  1. Yeni bir Kimlik sütunu oluşturun. Bu yeni sütun için Kimlik Ekle'yi açın.

  2. Kaynak sütundaki (Kimliğe dönüştürmek istediğiniz sütun) bu yeni sütuna veri ekleyin.

  3. Yeni sütun için Kimlik Ekle'yi kapatın.

  4. Kaynak sütununuzu bırakın ve yeni sütunu kaynak sütunun adıyla yeniden adlandırın.

Birden fazla sunucuda çalışmak gibi daha fazla karmaşıklık olabilir.

Adımlar için lütfen aşağıdaki makaleye bakın (ssms & T-sql kullanarak). Bu adımlar, T-SQL üzerinde daha az kavrama olan yeni başlayanlar için tasarlanmıştır.

http://social.technet.microsoft.com/wiki/contents/articles/23816.how-to-convert-int-column-to-identity-in-the-ms-sql-server.aspx


0

birincil anahtar = bigint olan ve kimlik kümesi olmayan tüm tablolar için bir komut dosyası oluşturur; bu, her tabloyla oluşturulan komut dosyalarının bir listesini döndürür;

SET NOCOUNT ON;

declare @sql table(s varchar(max), id int identity)

DECLARE @table_name nvarchar(max),
        @table_schema nvarchar(max);

DECLARE vendor_cursor CURSOR FOR 
SELECT
  t.name, s.name
FROM sys.schemas AS s
INNER JOIN sys.tables AS t
  ON s.[schema_id] = t.[schema_id]
WHERE EXISTS (
    SELECT
    [c].[name]
    from sys.columns [c]
    join sys.types [y] on [y].system_type_id = [c].system_type_id
    where [c].[object_id] = [t].[object_id] and [y].name = 'bigint' and [c].[column_id] = 1
) and NOT EXISTS 
(
  SELECT 1 FROM sys.identity_columns
    WHERE [object_id] = t.[object_id]
) and exists (
    select 1 from sys.indexes as [i] 
    inner join sys.index_columns as [ic]  ON  i.OBJECT_ID = ic.OBJECT_ID AND i.index_id = ic.index_id
    where object_name([ic].[object_id]) = [t].[name]
)
OPEN vendor_cursor

FETCH NEXT FROM vendor_cursor 
INTO @table_name, @table_schema

WHILE @@FETCH_STATUS = 0
BEGIN

DELETE FROM @sql

declare @pkname varchar(100),
    @pkcol nvarchar(100)

SELECT  top 1
        @pkname = i.name,
        @pkcol = COL_NAME(ic.OBJECT_ID,ic.column_id)
FROM    sys.indexes AS [i]
INNER JOIN sys.index_columns AS [ic] ON  i.OBJECT_ID = ic.OBJECT_ID AND i.index_id = ic.index_id
WHERE   i.is_primary_key = 1 and OBJECT_NAME(ic.OBJECT_ID) = @table_name

declare @q nvarchar(max) = 'SELECT  '+@pkcol+' FROM ['+@table_schema+'].['+@table_name+'] ORDER BY '+@pkcol+' DESC'

DECLARE @ident_seed nvarchar(max) -- Change this to the datatype that you are after
SET @q = REPLACE(@q, 'SELECT', 'SELECT TOP 1 @output = ')
EXEC sp_executeSql @q, N'@output bigint OUTPUT', @ident_seed OUTPUT

insert into  @sql(s) values ('BEGIN TRANSACTION')
insert into  @sql(s) values ('BEGIN TRY')

-- create statement
insert into  @sql(s) values ('create table ['+@table_schema+'].[' + @table_name + '_Temp] (')

-- column list
insert into @sql(s) 
select 
    '  ['+[c].[name]+'] ' +
    y.name + 

    (case when [y].[name] like '%varchar' then
    coalesce('('+(case when ([c].[max_length] < 0 or [c].[max_length] >= 1024) then 'max' else cast([c].max_length as varchar) end)+')','')
    else '' end)

     + ' ' +
    case when [c].name = @pkcol then 'IDENTITY(' +COALESCE(@ident_seed, '1')+',1)' else '' end + ' ' +
    ( case when c.is_nullable = 0 then 'NOT ' else '' end ) + 'NULL ' + 
    coalesce('DEFAULT ('+(
        REPLACE(
            REPLACE(
                LTrim(
                    RTrim(
                        REPLACE(
                            REPLACE(
                                REPLACE(
                                    REPLACE(
                                        LTrim(
                                            RTrim(
                                                REPLACE(
                                                    REPLACE(
                                                        object_definition([c].default_object_id)
                                                    ,' ','~')
                                                ,')',' ')
                                            )
                                        )
                                    ,' ','*')
                                ,'~',' ')
                            ,' ','~')
                        ,'(',' ')
                    )
                )
            ,' ','*')
        ,'~',' ')
    ) +
    case when object_definition([c].default_object_id) like '%get%date%' then '()' else '' end
    +
    ')','') + ','
 from sys.columns c
 JOIN sys.types y ON y.system_type_id = c.system_type_id
  where OBJECT_NAME(c.[object_id]) = @table_name and [y].name != 'sysname'
 order by [c].column_id


 update @sql set s=left(s,len(s)-1) where id=@@identity

-- closing bracket
insert into @sql(s) values( ')' )

insert into @sql(s) values( 'SET IDENTITY_INSERT ['+@table_schema+'].['+@table_name+'_Temp] ON')

declare @cols nvarchar(max)
SELECT @cols = STUFF(
    (
        select ',['+c.name+']'
        from sys.columns c
        JOIN sys.types y ON y.system_type_id = c.system_type_id
        where c.[object_id] = OBJECT_ID(@table_name)
        and [y].name != 'sysname'
        and [y].name != 'timestamp'
        order by [c].column_id
        FOR XML PATH ('')
     )
    , 1, 1, '')

insert into @sql(s) values( 'IF EXISTS(SELECT * FROM ['+@table_schema+'].['+@table_name+'])')
insert into @sql(s) values( 'EXEC(''INSERT INTO ['+@table_schema+'].['+@table_name+'_Temp] ('+@cols+')')
insert into @sql(s) values( 'SELECT '+@cols+' FROM ['+@table_schema+'].['+@table_name+']'')')

insert into @sql(s) values( 'SET IDENTITY_INSERT ['+@table_schema+'].['+@table_name+'_Temp] OFF')


insert into @sql(s) values( 'DROP TABLE ['+@table_schema+'].['+@table_name+']')

insert into @sql(s) values( 'EXECUTE sp_rename N''['+@table_schema+'].['+@table_name+'_Temp]'', N'''+@table_name+''', ''OBJECT''')

if ( @pkname is not null ) begin
    insert into @sql(s) values('ALTER TABLE ['+@table_schema+'].['+@table_name+'] ADD CONSTRAINT ['+@pkname+'] PRIMARY KEY CLUSTERED (')
    insert into @sql(s)
        select '  ['+COLUMN_NAME+'] ASC,' from information_schema.key_column_usage
        where constraint_name = @pkname
        GROUP BY COLUMN_NAME, ordinal_position
        order by ordinal_position

    -- remove trailing comma
    update @sql set s=left(s,len(s)-1) where id=@@identity
    insert into @sql(s) values ('  )')
end

insert into  @sql(s) values ('--Run your Statements')
insert into  @sql(s) values ('COMMIT TRANSACTION')
insert into  @sql(s) values ('END TRY')
insert into  @sql(s) values ('BEGIN CATCH')
insert into  @sql(s) values ('        ROLLBACK TRANSACTION')
insert into  @sql(s) values ('        DECLARE @Msg NVARCHAR(MAX)  ')
insert into  @sql(s) values ('        SELECT @Msg=ERROR_MESSAGE() ')
insert into  @sql(s) values ('        RAISERROR(''Error Occured: %s'', 20, 101,@msg) WITH LOG')
insert into  @sql(s) values ('END CATCH')

declare @fqry nvarchar(max)

-- result!
SELECT @fqry = (select char(10) + s from @sql order by id FOR XML PATH (''))


SELECT @table_name as [Table_Name], @fqry as [Generated_Query]
PRINT 'Table: '+@table_name
EXEC sp_executeSql @fqry

    FETCH NEXT FROM vendor_cursor 
    INTO @table_name, @table_schema
END 
CLOSE vendor_cursor;
DEALLOCATE vendor_cursor;
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.