2012-08-20 87 views
1

SequenceId是一個自動遞增標識列,但不是主鍵。SQL Server:在行更新時重新生成標識列的值

我希望發生的是,當一個行被更新,SequenceId設置爲下一個可用的值,例如:

_____________________ 
| SequenceId | Name | 
| 1   | John | 
| 2   | Jane | 
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 

更新約翰·傑克。 SequenceId被設置爲下一個可用標識值。

_____________________ 
| SequenceId | Name | 
| 3   | Jack | 
| 2   | Jane | 
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 

這可能與SQL Server?如果不是,將會有什麼替代方案?

+1

你不能這樣做 - 一個'IDENTITY'列不能更新 - 只能插入。 – 2012-08-20 04:44:17

回答

6

我不認爲你可以,至少不容易或乾淨。爲什麼不使用ROWVERSION列?每當行更新爲數據庫中新的唯一遞增值時,ROWVERSION列都會更新。如果您想索引它,您可以創建一個計算列,將其轉換爲bigint。缺點是時間戳是數據庫範圍的,所以如果你有多個使用它們的表,你可以跳過數字。

FIDDLE

create table TestRowVersion (
    Id int primary key, 
    Name varchar(20), 
    BinaryRowVersion ROWVERSION, 
    IntegerRowVersion as convert(BIGINT, BinaryRowVersion) 
) 

create index IDX_TestRowVersion on TestRowVersion (IntegerRowVersion) 

insert into TestRowVersion (Id, Name) values (1, 'Alvin') 
insert into TestRowVersion (Id, Name) values (2, 'Betsy') 
insert into TestRowVersion (Id, Name) values (3, 'Charles') 
select * From TestRowVersion 
update TestRowVersion set Name = 'Frank' where Id = 2 
select * From TestRowVersion 

[編輯] - 更新爲使用RowVersion因爲時間戳已被棄用

+0

哇,時間戳數據類型(別名rowversion:http://msdn.microsoft.com/en-us/library/ms182776.aspx)是一個輝煌的解決方案正在努力去做。謝謝傑森! – 2012-08-20 05:29:55

0

這應該工作...

SET IDENTITY_INSERT [table] ON 

UPDATE [table] 
SET Name = 'some name', 
    SequenceId = MAX(SequenceId) + 1 
WHERE ID = 123 

SET IDENTITY_INSERT [table] OFF 
+1

如果SequenceId是標識它不起作用 – 2012-08-20 03:50:27

+0

我添加了IDENTITY_INSERT,我不完全確定在更新上工作,但我會這麼認爲。 – CoderMarkus 2012-08-20 03:53:50

+3

'IDENTITY_INSERT'將起作用,然後您**將一個新值插入到具有'IDENTITY'的列中。它不工作**'UPDATE' – 2012-08-20 04:43:43

1

我希望發生的是,當一個行被更新,SequenceId設置爲下一個可用的值...

這還不夠,您還想更新序列發電機,所以下一個插入的值將是正確的。

如果您使用的是MS SQL Server 2012,則可以明確使用sequence object而不是隱式IDENTITY。這可以讓你產生不插入一個序列號,這樣的:

CREATE SEQUENCE MySquence AS INT START WITH 0; 

CREATE TABLE MyTable (
    SequenceId INT DEFAULT (NEXT VALUE FOR MySquence), 
    Name VARCHAR(50) PRIMARY KEY 
); 

INSERT INTO MyTable (Name) VALUES ('John'); 
INSERT INTO MyTable (Name) VALUES ('Jane'); 

SELECT * FROM MyTable; 

    SEQUENCEID NAME 
    1   Jane 
    0   John 

UPDATE 
    MyTable SET SequenceId = NEXT VALUE FOR MySquence, 
    Name = 'Jack' 
WHERE Name = 'John'; 

SELECT * FROM MyTable; 

    SEQUENCEID NAME 
    2   Jack 
    1   Jane 

[SQL Fiddle]


在舊版本中,你可以有一個單獨的表模仿序列,它包含一個IDENTITY列然後:

  • 插入新行到該表,並得到使用INSERT..OUTPUT(或@@IDENTITY)所產生的自動遞增的數字,
  • 然後你可以立即刪除該行來保存存儲。

或者,如果你沒有任何參照完整性刪除和插入它關心,你可以「更新」的行。