Làm cách nào để cập nhật Cột danh tính trong SQL Server?


194

Tôi có cơ sở dữ liệu SQL Server và tôi muốn thay đổi cột nhận dạng vì nó bắt đầu với một số lượng lớn 10010và nó liên quan đến một bảng khác, bây giờ tôi có 200 bản ghi và tôi muốn khắc phục vấn đề này trước khi hồ sơ tăng lên.

Cách tốt nhất để thay đổi hoặc thiết lập lại cột này là gì?

Câu trả lời:


269

Bạn không thể cập nhật cột danh tính.

SQL Server không cho phép cập nhật cột nhận dạng không giống như những gì bạn có thể làm với các cột khác bằng câu lệnh cập nhật.

Mặc dù có một số lựa chọn thay thế để đạt được một loại yêu cầu tương tự.

  • Khi giá trị cột Danh tính cần được cập nhật cho các bản ghi mới

Sử dụng DBCC CHECKIDENT để kiểm tra giá trị nhận dạng hiện tại cho bảng và nếu cần, thay đổi giá trị nhận dạng.

DBCC CHECKIDENT('tableName', RESEED, NEW_RESEED_VALUE)
  • Khi giá trị cột Danh tính cần được cập nhật cho các bản ghi hiện có

Sử dụng IDENTITY_INSERT cho phép chèn các giá trị rõ ràng vào cột định danh của bảng.

SET IDENTITY_INSERT YourTable {ON|OFF}

Thí dụ:

-- Set Identity insert on so that value can be inserted into this column
SET IDENTITY_INSERT YourTable ON
GO
-- Insert the record which you want to update with new value in the identity column
INSERT INTO YourTable(IdentityCol, otherCol) VALUES(13,'myValue')
GO
-- Delete the old row of which you have inserted a copy (above) (make sure about FK's)
DELETE FROM YourTable WHERE ID=3
GO
--Now set the idenetity_insert OFF to back to the previous track
SET IDENTITY_INSERT YourTable OFF

6
DBCC Đặt lại bản ghi mới tiếp theo, nhưng những gì tôi muốn bây giờ để thay đổi các bản ghi hiện có.
Abdulsalam Elsharif

bạn có thể cho ví dụ xin vui lòng?
Abdulsalam Elsharif

38
@sachin đây không phải là cập nhật IDENTITY hiện tại, đây là cách chèn thủ công
Phill Greggan

3
@PhillGreggan vâng, đây là giải pháp tốt nhất có thể để đạt được điều này. Bạn không thể cập nhật cột Danh tính khi bạn cập nhật các cột thông thường.
Sachin

17
Câu trả lời được chấp nhận này không trả lời câu hỏi, đó là cách cập nhật cột nhận dạng (ví dụ UPDATE YourTable SET IdentityCol = 13). SET IDENTITY_INSERT YourTable ONchỉ cho phép CHỨNG MINH, không CẬP NHẬT.
Ian Boyd

61

Nếu bạn có câu hỏi đúng, bạn muốn làm một cái gì đó như

update table
set identity_column_name = some value

Hãy để tôi nói với bạn, nó không phải là một quá trình dễ dàng và không nên sử dụng nó, vì có thể có một số foreign keyliên quan đến nó.

Nhưng đây là các bước để làm điều đó, xin vui lòng lấy một back-upbảng

Bước 1- Chọn giao diện thiết kế của bảng

nhập mô tả hình ảnh ở đây

Bước 2- Tắt cột danh tính

nhập mô tả hình ảnh ở đây

Bây giờ bạn có thể sử dụng updatetruy vấn.

Bây giờ redobước 1 và bước 2 và Bật cột nhận dạng

Tài liệu tham khảo


1
Tôi có một bảng khác liên quan đến bảng này, tôi nghĩ rằng tôi không thể làm điều đó
Abdulsalam Elsharif

4
Do đó, tuyên bố này không được khuyến khích :)
Luv

3
@AbdusalamElsherif Nhưng bạn đã hỏi cách thay đổi cột định danh.
paparazzo

@luv ít nhất bạn đã trả lời cho câu hỏi đã được hỏi
Phill Greggan

Tôi sử dụng thủ tục này để thiết lập id trong cơ sở dữ liệu phát triển của mình. Sẽ thật tuyệt nếu có một lệnh cho phép tôi làm điều đó bằng mọi cách, nhưng điều này hoạt động.
Jeff Davis

56

Bạn cần phải

set identity_insert YourTable ON

Sau đó xóa hàng của bạn và đặt lại nó với danh tính khác nhau.

Khi bạn đã thực hiện thao tác chèn, đừng quên tắt nhận dạng_insert

set identity_insert YourTable OFF

Điều này rất dễ dàng và an toàn hơn nhiều so với việc tắt Danh tính cho cột!
Người bảo vệ một

Điều này an toàn hơn và dễ dàng cho một số lượng nhỏ hồ sơ, nhưng không trả lời đúng câu hỏi. Tắt danh tính, mặc dù nguy hiểm hơn và đôi khi không thể, cho phép bạn cập nhật cột danh tính.
Matthew Hudson

18
--before running this make sure Foreign key constraints have been removed that reference the ID. 

--set table to allow identity to be inserted
SET IDENTITY_INSERT yourTable ON;
GO
--insert everything into a temp table
SELECT * 
INTO #tmpYourTable
FROM yourTable

--clear your table
DELETE FROM yourTable
--insert back all the values with the updated ID column
INSERT INTO yourTable (IDCol, OtherCols)
SELECT ID+1 as updatedID --put any other update logic to the ID here
, OtherCols FROM #tmpYourTable
--drop the temp table
DROP TABLE #tmpYourTable
--put identity back to normal
SET IDENTITY_INSERT yourTable OFF;
GO

1
Chỉ là một mẹo hiệu suất nếu bảng rất lớn, thay vì thực hiện xóa trên bảng, hãy thực hiện Bảng rút gọn yourTable. Nó là tức thời. Mặc dù vậy, thận trọng, không quay trở lại với cắt ngắn vì nó không được đăng nhập.
kuklei


5

sao chép bảng của bạn vào một bảng mới mà không có cột định danh.

    select columns into newtable from yourtable

thêm một cột danh tính vào newtable với hạt giống mới và làm cho nó làm khóa chính

    ALTER TABLE tableName ADD id MEDIUMINT NOT NULL AUTO_INCREMENT KEY

3
DBCC CHECKIDENT(table_name, RESEED, value)

tên_bảng = cung cấp bảng bạn muốn đặt lại giá trị

value = giá trị ban đầu bằng 0, để bắt đầu cột nhận dạng bằng 1


3
SET IDENTITY_INSERT dbo.TableName ON
INSERT INTO dbo.TableName 
(
    TableId, ColumnName1, ColumnName2, ColumnName3
)
VALUES
(
    TableId_Value, ColumnName1_Value, ColumnName2_Value, ColumnName3_Value
)

SET IDENTITY_INSERT dbo.TableName OFF

Khi sử dụng Identity_Insert đừng quên bao gồm các tên cột vì sql sẽ không cho phép bạn chèn mà không chỉ định chúng


2

Bạn cũng có thể sử dụng SET IDENTITY INSERTđể cho phép bạn chèn giá trị vào cột nhận dạng.

Thí dụ:

SET IDENTITY_INSERT dbo.Tool ON
GO

Và sau đó bạn có thể chèn vào một cột danh tính các giá trị bạn cần.


1
ALTER TABLE tablename add newcolumn int
update tablename set newcolumn=existingcolumnname
ALTER TABLE tablename DROP COLUMN existingcolumnname;
EXEC sp_RENAME 'tablename.oldcolumn' , 'newcolumnname', 'COLUMN'
update tablename set newcolumnname=value where condition

Tuy nhiên, mã trên chỉ hoạt động nếu không có quan hệ khóa chính-ngoại


1

Giải pháp hoàn chỉnh cho các lập trình viên C # bằng cách sử dụng trình xây dựng lệnh

Trước hết, bạn phải biết sự thật này:

  • Trong mọi trường hợp, bạn không thể sửa đổi một cột danh tính, vì vậy bạn phải xóa hàng và thêm lại với danh tính mới.
  • Bạn không thể xóa thuộc tính danh tính khỏi cột (bạn sẽ phải xóa sang cột)
  • Trình tạo lệnh tùy chỉnh từ .net luôn bỏ qua cột nhận dạng, vì vậy bạn không thể sử dụng nó cho mục đích này.

Vì vậy, một khi biết rằng, những gì bạn phải làm là. Lập trình câu lệnh SQL Chèn của riêng bạn hoặc chương trình trình tạo lệnh chèn của riêng bạn. Hoặc sử dụng cái này mà tôi đã lập trình cho bạn. Đưa ra một DataTable, tạo tập lệnh Chèn SQL:

public static string BuildInsertSQLText ( DataTable table )
{
    StringBuilder sql = new StringBuilder(1000,5000000);
    StringBuilder values = new StringBuilder ( "VALUES (" );
    bool bFirst = true;
    bool bIdentity = false;
    string identityType = null;

    foreach(DataRow myRow in table.Rows) 
    {
        sql.Append( "\r\nINSERT INTO " + table.TableName + " (" );

        foreach ( DataColumn column in table.Columns )
        {
            if ( column.AutoIncrement )
            {
                bIdentity = true;

                switch ( column.DataType.Name )
                {
                    case "Int16":
                        identityType = "smallint";
                        break;
                    case "SByte":
                        identityType = "tinyint";
                        break;
                    case "Int64":
                        identityType = "bigint";
                        break;
                    case "Decimal":
                        identityType = "decimal";
                        break;
                    default:
                        identityType = "int";
                        break;
                }
            }
            else
            {
                if ( bFirst )
                    bFirst = false;
                else
                {
                    sql.Append ( ", " );
                    values.Append ( ", " );
                }
                sql.Append ("[");
                sql.Append ( column.ColumnName );
                sql.Append ("]");

                //values.Append (myRow[column.ColumnName].ToString() );

                if (myRow[column.ColumnName].ToString() == "True")
                    values.Append("1");
                else if (myRow[column.ColumnName].ToString() == "False")
                    values.Append("0");
                else if(myRow[column.ColumnName] == System.DBNull.Value)    
                    values.Append ("NULL");
                else if(column.DataType.ToString().Equals("System.String"))
                {
                    values.Append("'"+myRow[column.ColumnName].ToString()+"'");
                }
                else
                    values.Append (myRow[column.ColumnName].ToString());
                    //values.Append (column.DataType.ToString() );
            }
        }
        sql.Append ( ") " );
        sql.Append ( values.ToString () );
        sql.Append ( ")" );

        if ( bIdentity )
        {
            sql.Append ( "; SELECT CAST(scope_identity() AS " );
            sql.Append ( identityType );
            sql.Append ( ")" );
        }
        bFirst = true;
        sql.Append(";");
        values = new StringBuilder ( "VALUES (" );
    } //fin foreach
    return sql.ToString ();
}

0

Tôi đã giải quyết vấn đề này trước tiên bằng cách sử dụng DBCC và sau đó sử dụng insert. Ví dụ nếu bảng của bạn là

Trước tiên, đặt Giá trị ID hiện tại mới trên bảng là NEW_RESEED_VALUE

MyTable {IDCol, colA, colB}

    DBCC CHECKIDENT('MyTable', RESEED, NEW_RESEED_VALUE)

sau đó bạn có thể sử dụng

    insert into MyTable (colA, ColB) select colA, colB from MyTable

Điều này sẽ nhân đôi tất cả các bản ghi của bạn nhưng sử dụng giá trị IDCol mới bắt đầu là NEW_RESEED_VALUE. Sau đó, bạn có thể xóa các hàng trùng lặp Giá trị ID cao hơn sau khi bạn đã xóa / di chuyển các tham chiếu khóa ngoại của chúng, nếu có.


1
Đây là một ý tưởng hay, nhưng New_reseed_value là hạt giống hiện tại và số tiếp theo sẽ được sử dụng sẽ nhiều hơn 1 giá trị đó. Vì vậy, nếu bạn muốn hàng được chèn tiếp theo là danh tính 10, thì NEW_RESEED_VALUE phải được đặt thành 9.
LarryBud

0

Bạn có thể tạo một bảng mới bằng cách sử dụng mã sau đây.

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

Sau đó xóa db cũ và đổi tên db mới thành tên db cũ. Lưu ý : rằng cột1 và cột2 đại diện cho tất cả các cột trong bảng cũ mà bạn muốn giữ trong bảng mới của mình.


0

Nếu bạn đặc biệt cần thay đổi giá trị khóa chính thành một số khác (ví dụ 123 -> 1123). Các khối thuộc tính nhận dạng thay đổi một giá trị PK. Đặt Identity_insert sẽ không hoạt động. Không nên thực hiện Chèn / Xóa nếu bạn xóa tầng (trừ khi bạn tắt kiểm tra tính toàn vẹn tham chiếu).

Kịch bản này sẽ tắt danh tính trên PK:

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

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

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

Tiếp theo, bạn có thể đặt các mối quan hệ để họ sẽ cập nhật các tham chiếu khóa ngoài. Hoặc nếu không bạn cần phải tắt thực thi mối quan hệ. Liên kết SO này cho thấy làm thế nào: Làm thế nào các ràng buộc khóa ngoại có thể tạm thời bị vô hiệu hóa bằng T-SQL?

Bây giờ, bạn có thể làm cập nhật của bạn. Tôi đã viết một đoạn mã ngắn để viết tất cả SQL cập nhật của mình dựa trên cùng một tên cột (trong trường hợp của tôi, tôi cần tăng CaseID thêm 1.000.000:

select 
'update ['+c.table_name+'] SET ['+Column_Name+']=['+Column_Name+']+1000000'
from Information_Schema.Columns as c
JOIN Information_Schema.Tables as t ON t.table_Name=c.table_name and t.Table_Schema=c.table_schema and t.table_type='BASE TABLE'
where Column_Name like 'CaseID' order by Ordinal_position

Cuối cùng, kích hoạt lại tính toàn vẹn tham chiếu và sau đó kích hoạt lại cột Danh tính trên khóa chính.

Lưu ý: Tôi thấy một số người trong những câu hỏi này hỏi TẠI SAO. Trong trường hợp của tôi, tôi phải hợp nhất dữ liệu từ một phiên bản sản xuất thứ hai vào một DB chính để tôi có thể tắt phiên bản thứ hai. Tôi chỉ cần tất cả các PK / FK của dữ liệu hoạt động để không va chạm. FK siêu dữ liệu là giống hệt nhau.

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.