Thêm một danh tính vào một cột hiện có


445

Tôi cần thay đổi khóa chính của bảng thành cột nhận dạng và đã có một số hàng trong bảng.

Tôi đã có một tập lệnh để dọn sạch ID để đảm bảo chúng tuần tự bắt đầu từ 1, hoạt động tốt trên cơ sở dữ liệu thử nghiệm của tôi.

Lệnh SQL để thay đổi cột có thuộc tính nhận dạng là gì?

Câu trả lời:


482

Bạn không thể thay đổi các cột hiện có để nhận dạng.

Bạn có 2 lựa chọn,

  1. Tạo một bảng mới với danh tính và thả bảng hiện có

  2. Tạo một cột mới với danh tính và thả cột hiện có

Cách tiếp cận 1. ( Bảng mới ) Tại đây bạn có thể giữ lại các giá trị dữ liệu hiện có trên cột nhận dạng mới được tạo.

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'

Cách tiếp cận 2 ( Cột mới ) Bạn không thể giữ lại các giá trị dữ liệu hiện có trên cột nhận dạng mới được tạo, Cột nhận dạng sẽ giữ chuỗi số.

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'

Xem bài đăng trên Diễn đàn Microsoft SQL Server để biết thêm chi tiết:

Cách thay đổi cột thành nhận dạng (1,1)


49
Nếu dữ liệu bảng nhỏ, tùy chọn này hoạt động tốt. Nếu bảng lớn, có một tùy chọn khác tôi thích: sử dụng ALTER TABLE ... SWITCH để thay thế lược đồ bảng bằng một phiên bản khác bằng cột IDENTITY nhưng lược đồ giống hệt nhau. Ưu điểm của phương pháp ALTER TABLE .... SWITCH là nó hoàn thành nhanh chóng (dưới 5 giây cho một bảng hàng tỷ) vì không cần sao chép hoặc thay đổi dữ liệu bảng. Có những cảnh báo và hạn chế mặc dù. Xem câu trả lời của tôi dưới đây để biết chi tiết.
Justin Grant

7
@Justin Grat: Một lựa chọn rất thú vị và một điều mà tôi chưa từng xem xét! Lý do điều này hoạt động là vì IDENTITY là thuộc tính cột chứ không phải kiểu dữ liệu, do đó phương thức SWITCH xác thực các lược đồ giữa hai bảng (cũ và mới) là có thể xác định được bất kể sự khác biệt của IDENTITY. Cám ơn vì đã chia sẻ!
John Sansom

Nếu bạn không có nhiều dữ liệu, thì "tạo bảng" có thể đạt được bằng cách tạo tập lệnh từ SSMS. Nhấp chuột phải vào bảng> Bảng Scrip dưới dạng> Tạo BẢNG để> (trình soạn thảo truy vấn mới?). Sau đó thả nó xuống và bên trong tập lệnh đó, bạn có thể thêm IDENTITY(1, 1)phần đó bằng cột khóa chính
goamn

Người ta cũng có thể sử dụng SSMS để thực thi điều này. Chuyển đến Công cụ> Tùy chọn> Nhà thiết kế> Bỏ chọn "Ngăn chặn lưu thay đổi yêu cầu tạo lại bảng". BTW này không được khuyến nghị cho các bảng khá lớn.
Zafar

Trong PostgreQuery, bạn có thể thêm danh tính vào một cột số nguyên hiện có bằng lệnh: bảng thay đổi {table_name} thay đổi cột {cột_name} thêm luôn được tạo dưới dạng danh tính (khởi động lại bằng {number});
Andrew Mackie

209

Trong SQL 2005 trở lên, có một mẹo để giải quyết vấn đề này mà không thay đổi các trang dữ liệu của bảng. Điều này rất quan trọng đối với các bảng lớn, nơi chạm vào mọi trang dữ liệu có thể mất vài phút hoặc vài giờ. Thủ thuật này cũng hoạt động ngay cả khi cột định danh là khóa chính, là một phần của chỉ mục được phân cụm hoặc không phân cụm hoặc các vấn đề khác có thể vượt qua giải pháp "thêm / xóa / đổi tên" đơn giản hơn.

Đây là mẹo: bạn có thể sử dụng ALTER TABLE ... SWITCH của SQL Server để thay đổi lược đồ của bảng mà không thay đổi dữ liệu, nghĩa là bạn có thể thay thế bảng bằng IDENTITY bằng lược đồ bảng giống hệt nhau, nhưng không có cột IDENTITY. Thủ thuật tương tự hoạt động để thêm IDENTITY vào một cột hiện có.

Thông thường, ALTER BẢNG ... CÔNG TẮC được sử dụng để thay thế một cách hiệu quả một phân vùng đầy đủ trong một bảng được phân vùng bằng một phân vùng trống mới. Nhưng nó cũng có thể được sử dụng trong các bảng không phân vùng.

Tôi đã sử dụng thủ thuật này để chuyển đổi, trong vòng chưa đầy 5 giây, một cột trong bảng hàng 2,5 tỷ từ IDENTITY sang không IDENTITY (để chạy truy vấn nhiều giờ có kế hoạch truy vấn hoạt động tốt hơn cho tính không IDENTITY cột), và sau đó khôi phục cài đặt IDENTITY, một lần nữa sau chưa đầy 5 giây.

Đây là một mẫu mã về cách thức hoạt động của nó.

 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; 

Điều này rõ ràng có liên quan nhiều hơn các giải pháp trong các câu trả lời khác, nhưng nếu bảng của bạn lớn thì đây có thể là một trình tiết kiệm thực sự. Có một số cảnh báo:

  • Theo tôi biết, danh tính là điều duy nhất bạn có thể thay đổi về các cột trong bảng của mình bằng phương thức này. Thêm / xóa cột, thay đổi vô hiệu, vv không được phép.
  • Bạn sẽ cần bỏ các phím foriegn trước khi bạn thực hiện chuyển đổi và khôi phục chúng sau.
  • Tương tự đối với các chức năng SCHEMABINDING, các khung nhìn, v.v.
  • các chỉ mục của bảng mới cần khớp chính xác (cùng các cột, cùng thứ tự, v.v.)
  • Các bảng cũ và mới cần phải nằm trên cùng một nhóm.
  • Chỉ hoạt động trên SQL Server 2005 trở lên
  • Trước đây tôi tin rằng thủ thuật này chỉ hoạt động trên các phiên bản SQL Server dành cho Doanh nghiệp hoặc Nhà phát triển (vì các phân vùng chỉ được hỗ trợ trong phiên bản Enterprise và Developer), nhưng Mason G. Zhwiti trong nhận xét của mình bên dưới nói rằng nó cũng hoạt động trong SQL Standard Edition. Tôi cho rằng điều này có nghĩa là hạn chế đối với Doanh nghiệp hoặc Nhà phát triển không áp dụng cho ALTER TABLE ... SWITCH.

Có một bài viết hay về TechNet chi tiết các yêu cầu ở trên.

CẬP NHẬT - Eric Wu đã có một bình luận bên dưới có thêm thông tin quan trọng về giải pháp này. Sao chép nó ở đây để đảm bảo nó được chú ý nhiều hơn:

Có một cảnh báo khác ở đây là đáng nói. Mặc dù bảng mới sẽ vui vẻ nhận dữ liệu từ bảng cũ và tất cả các hàng mới sẽ được chèn theo mẫu nhận dạng, chúng sẽ bắt đầu ở 1 và có khả năng bị phá vỡ nếu cột nói là khóa chính. Cân nhắc chạy DBCC CHECKIDENT('<newTableName>')ngay sau khi chuyển đổi. Xem msdn.microsoft.com/en-us/l Library / ms176057.aspx để biết thêm thông tin.

Nếu bảng đang tích cực được mở rộng với các hàng mới (có nghĩa là bạn không có nhiều thời gian chết giữa việc thêm IDENTITY và thêm các hàng mới, thì thay vì DBCC CHECKIDENTbạn sẽ muốn đặt giá trị hạt giống nhận dạng theo cách thủ công trong lược đồ bảng mới thành lớn hơn so với ID hiện lớn nhất trong bảng, ví dụ IDENTITY (2435457, 1). Bạn có thể có thể bao gồm cả ALTER TABLE...SWITCHDBCC CHECKIDENTtrong một giao dịch (hoặc not-- đã không kiểm tra này) nhưng có vẻ như thiết lập các giá trị hạt giống bằng tay sẽ dễ dàng hơn và an toàn hơn.

Rõ ràng, nếu không có hàng mới nào được thêm vào bảng (hoặc đôi khi chúng chỉ được thêm vào, như quy trình ETL hàng ngày) thì điều kiện cuộc đua này sẽ không xảy ra nên DBCC CHECKIDENTvẫn ổn.


5
Nếu trí nhớ của tôi là chính xác, tôi đã có ý tưởng từ bài viết này: sqlservercentral.com/articles/T-Query/61979
Justin Grant

2
FYI, điều này dường như cũng hoạt động trên phiên bản tiêu chuẩn của SQL 2008 R2. Có lẽ họ đã kích hoạt tính năng này giống như bây giờ họ đã kích hoạt khả năng bật tính năng nén sao lưu.
Mason G. Zhwiti

3
@jbatista - Câu hỏi của OP nói rằng anh ta đã có khóa chính trên bàn và đã có thể đảm bảo các giá trị đúng, nhưng anh ta chỉ muốn thay đổi nó thành một cột IDENTITY. Câu trả lời của tôi ở trên tập trung vào trường hợp sử dụng hẹp: làm thế nào để thêm IDENTITY vào một cột mà không thực sự thay đổi bất kỳ dữ liệu nào. Cách tiếp cận tôi tài liệu ở trên là một trình tiết kiệm thời gian rất lớn cho các bảng lớn. Nếu bạn cần thay đổi dữ liệu, thì bạn sẽ cần sử dụng các giải pháp khác.
Justin Grant

3
Có một cảnh báo khác ở đây là đáng nói. Mặc dù bảng mới sẽ vui vẻ nhận dữ liệu từ bảng cũ và tất cả các hàng mới sẽ được chèn theo mẫu nhận dạng, chúng sẽ bắt đầu ở 1 và có khả năng bị phá vỡ nếu cột nói là khóa chính. Cân nhắc chạy DBCC CHECKIDENT('<newTableName>')ngay sau khi chuyển đổi. Xem msdn.microsoft.com/en-us/l Library / ms176057.aspx để biết thêm thông tin.
Eric Wu

3
Đây là một câu trả lời tuyệt vời! Cũng lưu ý rằng tính vô hiệu của các cột phải giống nhau. Vì vậy, nếu bạn cần thay đổi một vô hiệu hóa cột, bạn sẽ phải làm điều đó ở bước sau. Tương tự với các ràng buộc PK. Tôi cũng thay đổi giá trị nhận dạng trong việc tạo bảng để khớp với mức tối đa hiện tại: IDENTITY (maxID + 1, 1)
Philippe

71

Bạn không thể thay đổi một cột thành một cột IDENTITY. Những gì bạn sẽ cần làm là tạo một cột mới được xác định là IDENTITY từ việc di chuyển, sau đó thả cột cũ và đổi tên cột mới thành tên cũ.

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

ALTER TABLE (yourTable) DROP COLUMN OldColumnName

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

Marc


Tham số \ @objname không rõ ràng hoặc tuyên bố \ @objtype (COLUMN) là sai.
Jenny O'Reilly

1
@ JennyO'Reilly: đặt câu hỏi đó vào một câu hỏi riêng và cho chúng tôi thấy lệnh hoàn chỉnh mà bạn đang sử dụng!
marc_s

2
Đó là thủ tục sp_rename đã thất bại. Tôi tìm thấy một giải pháp trên stackoverflow bằng cách tìm kiếm văn bản lỗi. Nó dường như là một số quy tắc cú pháp nghiêm ngặt với dấu ngoặc, mặc dù bảng của tôi không có ký tự đặc biệt nào trong tên của nó.
Jenny O'Reilly

1
hoặc nó có thể là như sau: 'ALTER TABLE (yourTable) DROP COLUMN OldColumnName' và 'ALTER TABLE (yourTable) ADD OldColumnName INT SẮC (1,1)', tại sao đổi tên: p
RK Sharma

Marc, tôi đã thử lệnh chính xác này trên một bảng lớn (~ 300 triệu hàng), nhưng tôi đã dừng quá trình sau ~ 10 phút
Naomi

14

Có một giải pháp tuyệt vời được mô tả ở đây: SQL SERVER - Thêm hoặc xóa thuộc tính danh tính trên cột

Trong chỉnh sửa ngắn bằng tay bảng của bạn trong SQL Manager, chuyển đổi danh tính, KHÔNG LƯU LẠI thay đổi, chỉ hiển thị tập lệnh sẽ được tạo cho các thay đổi, sao chép nó và sử dụng nó sau.

Đó là tiết kiệm thời gian rất lớn, bởi vì nó (tập lệnh) chứa tất cả các khóa ngoại, chỉ mục, v.v. liên quan đến bảng bạn thay đổi. Viết cái này bằng tay ... Chúa cấm.


đây là giải pháp tôi đã sử dụng - SSMS tạo T-SQL để thực hiện thay đổi ... nó làm như vậy bằng cách tạo bảng tạm thời mới của cùng một thiết kế lược đồ, sau đó sao chép tất cả các hàng vào đó, xóa nguồn gốc và đổi tên . có thể mất một chút thời gian để chạy hoàn toàn nhưng nó hoạt động hoàn hảo.
mdelvecchio

Tôi không nghĩ Pinal Dave thực sự nói rằng bạn cần chạy tập lệnh mà bạn tạo ra, nó chỉ là để hiển thị những gì tạo ra sự thay đổi thông qua UI làm cho bạn ...
Zack

Tính chất kịch bản này trong SSMS (về việc thay đổi định nghĩa của bảng) thực sự là phương tiện chính xác duy nhất khi ghi lại một bảng được phân đoạn. Vị trí thích hợp nhất 'tác vụ' -> 'bảng kịch bản' luôn quên kịch bản chức năng phân vùng!
Martijn van der Jagt

1
Có thể hữu ích cho ai đó. Để có được Script thay đổi sau khi thay đổi. Nhấp chuột phải vào bảng trong chế độ thiết kế trên SSMS và chọn tùy chọn "Tạo tập lệnh thay đổi" và lưu tập lệnh trong ổ đĩa cục bộ
Vijai

11

Cân nhắc sử dụng SEQUENCE thay vì IDENTITY .

IN sql server 2014 (Tôi không biết về các phiên bản thấp hơn) bạn có thể thực hiện việc này một cách đơn giản, bằng cách sử dụng trình tự.

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

Từ đây: Trình tự làm giá trị mặc định cho một cột


6

Giải thích đơn giản

Đổi tên cột hiện có bằng sp_RENAME

EXEC sp_RENAME 'Table_Name.Ex hiện_ColumnName', 'New_ColumnName', 'COLUMN'

Ví dụ cho Đổi tên:

Cột UserID hiện tại được đổi tên thành OldUserID

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

Sau đó thêm một cột mới bằng cách sử dụng truy vấn thay đổi để đặt làm khóa chính và giá trị nhận dạng

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

Ví dụ cho Đặt khóa chính

Tên cột được tạo mới là UserID

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

sau đó thả cột đổi tên

ALTER TABLE Table_Name DROP COLUMN Renamed_ColumnName

Ví dụ cho cột được đổi tên

ALTER TABLE Users DROP COLUMN OldUserID

Bây giờ chúng tôi đã thêm một khóa chính và danh tính cho cột hiện có trên bảng.


5

Tôi là một nhà phát triển java tình cờ tham gia vào một nhóm không có DBA và là một nhà phát triển, tôi không thể có quyền DBA. Tôi được giao nhiệm vụ di chuyển toàn bộ lược đồ giữa hai cơ sở dữ liệu, vì vậy không có DBA, tôi phải thực hiện và thực hiện bằng cách chạy các tập lệnh, không thể sử dụng GUI trong SQL Server 2008 vì tôi không có quyền quản trị viên.

Mọi thứ đã được di chuyển mà không có vấn đề, tuy nhiên, khi chạy một thủ tục được lưu trữ trên lược đồ mới. Tôi thấy tôi bị mất trường nhận dạng trong một bảng. Tôi đã kiểm tra lại tập lệnh đã tạo bảng và nó đã ở đó, tuy nhiên, SQL Server đã không nhận được tập lệnh này khi tôi chạy tập lệnh. Sau đó tôi đã được một DBA nói rằng anh ta đã thấy vấn đề tương tự trước đây.

Trong mọi trường hợp, đối với SQL Server 2008, đây là các bước tôi đã thực hiện để giải quyết vấn đề này và chúng đã hoạt động, vì vậy tôi sẽ đăng bài này lên đây với hy vọng nó sẽ giúp ích cho ai đó. Đây là những gì tôi đã làm khi tôi có các phụ thuộc FK trên một bảng khác khiến việc này trở nên khó khăn hơn:

Tôi đã sử dụng truy vấn này để xác minh danh tính thực sự bị thiếu và để xem các phụ thuộc trên bảng.

1.) Tìm số liệu thống kê trên bảng:

exec sp_help 'dbo.table_name_old';

2.) Tạo một bảng mới trùng lặp, giống hệt nhau, ngoại trừ thêm một trường nhận dạng trên trường PK nơi nó đã có trước đó.

3.) Vô hiệu hóa danh tính để di chuyển dữ liệu.

SET IDENTITY_INSERT dbo.table_name ON 

4.) Chuyển dữ liệu.

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

5.) Xác minh dữ liệu ở đó.

SELECT * FROM dbo.table_name_new

6.) Kích hoạt lại danh tính.

SET IDENTITY_INSERT ToyRecP.ToyAwards.lkpFile_New OFF

7.) Đây là tập lệnh tốt nhất tôi tìm thấy để có được tất cả các mối quan hệ FK để xác minh (các) bảng nào tham chiếu bảng gốc là phụ thuộc và tôi đã gặp nhiều người, vì vậy đó là một người giữ!

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.) Đảm bảo rằng bạn có tất cả các tập lệnh PK và FK cho tất cả các bảng có liên quan, trước bước tiếp theo này.

9.) Bạn có thể nhấp chuột phải vào từng khóa và tập lệnh này bằng SQL Server 2008

10.) Thả FK (s) từ (các) bảng phụ thuộc bằng cú pháp này:

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

11.) Thả bảng gốc:

DROP TABLE dbo.table_name_old;

13.) Các bước tiếp theo này dựa trên các tập lệnh bạn đã tạo trong SQL Server 2008 trong bước 9.

--Thêm PK vào bảng mới.

--Thêm FK vào bảng mới.

--Thêm FK trở lại bảng phụ thuộc.

14.) Xác minh mọi thứ là chính xác và đầy đủ. Tôi đã sử dụng GUI để xem các bảng.

15.) Đổi tên bảng mới thành tên bảng gốc.

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

Cuối cùng, mọi thứ đã hoạt động!


4

bạn không thể làm như vậy, bạn cần thêm một cột khác, thả cột ban đầu và đổi tên cột mới hoặc tạo một bảng mới, sao chép dữ liệu vào và thả bảng cũ theo sau là đổi tên bảng mới sang bảng cũ bàn

nếu bạn sử dụng SSMS và đặt thuộc tính nhận dạng thành BẬT trong trình thiết kế thì đây là những gì SQL Server thực hiện phía sau hậu trường. Vì vậy, nếu bạn có một bảng có tên [người dùng] thì đây là điều sẽ xảy ra nếu bạn tạo UserID và danh tính

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

Đã nói rằng có một cách để hack bảng hệ thống để thực hiện nó bằng cách đặt giá trị bitwise nhưng điều đó không được hỗ trợ và tôi sẽ không làm điều đó


4

Như tôi đã hiểu trong các trường hợp thông thường, chúng tôi đang tạo một bảng có khóa Chính có thuộc tính Nhận dạng
Vì vậy, Đổi tên hoặc Xóa một cột được liên kết với ràng buộc Khóa chính sẽ không thể thực hiện được vì các quy tắc ràng buộc đang xác thực cấu trúc cột. Để đạt được điều này, chúng tôi phải xử lý một số bước theo cách sau: Chúng ta hãy giả sử TableName = 'Employee'ColumnName = 'EmployeeId' 1. Thêm cột mới 'EmployeeId_new' trong bảng 'Nhân viên' THAY ĐỔI Nhân viên THÊM Nhân viên THÊM 1,1)




  1. Bây giờ hãy xóa cột 'EmployeeId' khỏi bảng 'Employee'
    ALTER TABLE Employee DROP COLUMN EmployeeId

  2. Điều này sẽ gây ra lỗi vì các quy tắc ràng buộc khóa chính được áp dụng và xác thực cấu trúc cột.
    * ### ' Msg 5074, Cấp 16, Trạng thái 1, Dòng 1 Đối tượng [PK_dbo.Employee] phụ thuộc vào colmn [EmployeeId].' ###

  3. Vì vậy, trước tiên chúng ta phải xóa ràng buộc Khóa chính khỏi bảng 'Nhân viên', sau đó chúng ta có thể xóa cột
    ALTER TABLE ràng buộc DROP của nhân viên [PK_dbo.Employee]

  4. Bây giờ chúng tôi có thể xóa cột 'EmployeeId' khỏi bảng 'Employee' như đã làm ở bước trước, nơi chúng tôi đã gặp lỗi
    ALTER TABLE Employee DROP COLUMN EmployeeId

  5. Bây giờ Cột 'EmployeeId' đã bị xóa khỏi bảng Vì vậy, chúng tôi sẽ Đổi tên cột mới được thêm vào 'EmployeeId_new' với 'EmployeeId'
    sp_rename 'Employee.EmployeeId', 'EmployeeId_new', 'COLUMN'

  6. Để sắp xếp lại bảng theo dạng như trước đây, chúng ta phải thêm ràng buộc khóa chính cho cột 'EmployeeId'
    ALTER TABLE Nhân viên thêm ràng buộc [PK_dbo.Employee] khóa chính (EmployeeId)

8. Bây giờ bảng 'Nhân viên' với 'Nhân viên' đã được sửa đổi cho các quy tắc Nhận dạng cùng với ràng buộc khóa chính hiện có


3

Theo thiết kế, không có cách đơn giản nào để bật hoặc tắt tính năng nhận dạng cho một cột hiện có. Cách duy nhất để làm điều này là tạo một cột mới và biến nó thành một cột nhận dạng hoặc tạo một bảng mới và di chuyển dữ liệu của bạn.

Nếu chúng tôi sử dụng SQL Server Management Studio để loại bỏ giá trị nhận dạng trên cột "id", một bảng tạm thời mới được tạo, dữ liệu sẽ được chuyển sang bảng tạm thời, bảng cũ sẽ bị hủy và bảng mới được đổi tên.

Sử dụng Management Studio để thực hiện thay đổi và sau đó nhấp chuột phải vào trình thiết kế và chọn "Tạo tập lệnh thay đổi".

Bạn sẽ thấy rằng đây là những gì máy chủ SQL đang làm trong nền.


2

Đáng buồn thay, không có một; thuộc tính IDENTITY thuộc về bảng chứ không phải cột.

Cách dễ dàng hơn là thực hiện trong GUI, nhưng nếu đây không phải là một tùy chọn, bạn có thể đi một chặng đường dài để sao chép dữ liệu, thả cột, thêm lại bằng nhận dạng và đưa dữ liệu trở lại.

Xem ở đây cho một tài khoản blow-by-blow.


2

Nhấp chuột phải vào tên bảng trong Object Explorer. Bạn sẽ nhận được một số tùy chọn. Nhấp vào 'Thiết kế'. Một tab mới sẽ được mở cho bảng này. Bạn có thể thêm ràng buộc danh tính ở đây trong 'Thuộc tính cột'.


2

Để sửa đổi các thuộc tính danh tính cho một cột:

  • Trong Server Explorer, bấm chuột phải vào bảng có thuộc tính nhận dạng bạn muốn sửa đổi và bấm Mở Định nghĩa bảng. Bảng mở trong Trình thiết kế bảng.
  • Xóa hộp kiểm Cho phép null cho cột bạn muốn thay đổi.
  • Trong tab Thuộc tính Cột, mở rộng thuộc tính Đặc điểm nhận dạng.
  • Bấm vào ô lưới cho thuộc tính con Nhận dạng và chọn Có từ danh sách thả xuống.
  • Nhập một giá trị trong ô Hạt giống. Giá trị này sẽ được gán cho hàng đầu tiên trong bảng. Giá trị 1 sẽ được gán theo mặc định.

Đó là nó, và nó làm việc cho tôi


2

Nếu bạn tình cờ sử dụng Visual Studio 2017+

  1. Trong Server Object Explorer, nhấp chuột phải vào bảng của bạn và chọn "xem mã"
  2. Thêm công cụ sửa đổi "IDENTITY" vào cột của bạn
  3. Cập nhật

Điều này sẽ làm tất cả cho bạn.


Đúng! Cảm ơn bạn đã gợi ý điều này! Tôi không có phiên bản SSMS trên hộp Windows 7 cho phép tôi thực hiện thay đổi Thiết kế cho các bảng trên máy chủ Sản xuất của mình vì đó là năm 2017, SSMS của tôi là 2014 và SSMS 2017 cần Windows 10. Bạn đã tạo ra một ngày của tôi. Đi vào VS 2017> Server Explorer> tạo kết nối mới để sản xuất SQL Server> nhấp chuột phải vào bảng> "Định nghĩa bảng mở"> Wala!
JustJohn

Trên thực tế, tôi thấy bạn có thể nhấp chuột phải vào trường và chọn Thuộc tính và tạo Danh tính trên đó chọn Có hoặc Không
JustJohn

1

Nếu người đăng ban đầu thực sự muốn đặt một cột hiện có thành một PRIMARY KEYbảng và thực sự không cần cột là một IDENTITYcột (hai điều khác nhau) thì điều này có thể được thực hiện thông qua t-SQL với:

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

Lưu ý dấu ngoặc quanh tên cột sau PRIMARY KEY tùy chọn.

Mặc dù bài đăng này đã cũ và tôi đang đưa ra giả định về nhu cầu của người yêu cầu, tôi cảm thấy thông tin bổ sung này có thể hữu ích cho người dùng gặp chủ đề này vì tôi tin rằng cuộc trò chuyện có thể khiến người ta tin rằng một cột hiện tại không thể được đặt là khóa chính mà không thêm nó dưới dạng một cột mới trước sẽ không chính xác.


1

Theo điều kiện hiện tại của tôi, tôi làm theo phương pháp này. Tôi muốn cung cấp danh tính cho một bảng chính sau khi dữ liệu được chèn qua tập lệnh.

Vì tôi muốn nối thêm danh tính, nên nó luôn bắt đầu từ 1 đến hết số lượng bản ghi mà tôi muốn.

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

Điều này sẽ tạo cùng một cột khóa chính với danh tính

Tôi đã sử dụng các liên kết này: https://blog.sqlauthority.com/2014/10/11/sql-server-add-auto-incremental-identity-column-to-table-after-creating-table/

Thêm khóa chính vào bảng hiện có


0

Tôi không tin rằng bạn có thể thay đổi một cột hiện có thành một cột nhận dạng bằng cách sử dụng tsql. Tuy nhiên, bạn có thể làm điều đó thông qua chế độ xem thiết kế Enterprise Manager.

Ngoài ra, bạn có thể tạo một hàng mới làm cột nhận dạng, thả cột cũ, sau đó đổi tên cột mới của bạn.

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

2
Hãy nhớ rằng nếu bạn làm điều đó thông qua SSMS / Trình quản lý doanh nghiệp - bạn sẽ tạo một bảng mới, sao chép dữ liệu, bỏ bảng cũ và đổi tên bảng mới. Điều đó có thể khá tốn kém khi bạn có những bàn lớn ...
Scott Ivey

0

Về cơ bản có bốn bước hợp lý.

  1. Tạo một cột Danh tính mới. Bật Chèn danh tính cho cột mới này.

  2. Chèn dữ liệu từ cột nguồn (cột bạn muốn chuyển đổi sang Danh tính) sang cột mới này.

  3. Tắt Nhận dạng Chèn cho cột mới.

  4. Thả cột nguồn của bạn và đổi tên cột mới thành tên của cột nguồn.

Có thể có một số phức tạp hơn như làm việc trên nhiều máy chủ, v.v.

Vui lòng tham khảo bài viết sau để biết các bước (sử dụng ssms & T-sql). Các bước này dành cho người mới bắt đầu với ít nắm bắt hơn về T-SQL.

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


0

tạo tập lệnh cho tất cả các bảng có khóa chính = bigint không có bộ nhận dạng; điều này sẽ trả về một danh sách các tập lệnh được tạo với mỗi bảng;

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;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.