SequenceId
是一个自动递增的标识列,但不是主键。
我想要发生的是,当更新行时,SequenceId
被设置为下一个可用值,例如:
_____________________
| SequenceId | Name |
| 1 | John |
| 2 | Jane |
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
将约翰更新为杰克。 SequenceId
设置为下一个可用的标识值。
_____________________
| SequenceId | Name |
| 3 | Jack |
| 2 | Jane |
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
SQL Server可以实现吗?如果没有,会有什么替代方案?
答案 0 :(得分:6)
我认为你不能,至少不容易或干净。为什么不使用ROWVERSION列?每次将行更新为数据库中新的唯一递增值时,ROWVERSION列都会更新。您可以创建一个计算列,如果要对其进行索引,则将其转换为bigint。缺点是时间戳是数据库范围的,所以如果有多个表使用它们,你可以跳过数字。
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
答案 1 :(得分:1)
我想要发生的是,当一行更新时,SequenceId被设置为下一个可用值......
这还不够,您还想更新序列生成器,因此下一个插入的值将是正确的。
如果您使用的是MS SQL Server 2012,则可以显式使用sequence object,而不是隐式IDENTITY。这允许您在没有INSERT的情况下生成下一个序列号,如下所示:
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
在旧版本中,您可以通过包含单个IDENTITY列的单独表来模拟序列,然后:
INSERT..OUTPUT
(或@@IDENTITY
)获取生成的自动递增数字,或者,如果您没有任何关注的参照完整性,您可以通过删除和插入来“更新”该行。
答案 2 :(得分:0)
这应该有用......
SET IDENTITY_INSERT [table] ON
UPDATE [table]
SET Name = 'some name',
SequenceId = MAX(SequenceId) + 1
WHERE ID = 123
SET IDENTITY_INSERT [table] OFF