Saya menjalankan SQL Server 2014 secara lokal untuk database yang akan disebarkan ke database Azure SQL V12.
Saya memiliki tabel yang menyimpan nilai properti yang dapat diperluas untuk objek entitas bisnis, dalam hal ini ketiga tabel tersebut terlihat seperti ini:
CREATE TABLE Widgets (
WidgetId bigint IDENTITY(1,1),
...
)
CREATE TABLE WidgetProperties (
PropertyId int IDENTITY(1,1),
Name nvarchar(50)
Type int -- 0 = int, 1 = string, 2 = date, etc
)
CREATE TABLE WidgetPropertyValues (
WidgetId bigint,
PropertyId int,
Revision int,
DateTime datetimeoffset(7),
Value varbinary(255)
CONSTRAINT [PK_WidgetPropertyValues] PRIMARY KEY CLUSTERED (
[WidgetId] ASC,
[PropertyIdId] ASC,
[Revision] ASC
)
)
ALTER TABLE dbo.WidgetPropertyValues WITH CHECK ADD CONSTRAINT FK_WidgetPropertyValues_WidgetProperties FOREIGN KEY( PropertyId )
REFERENCES dbo.WidgetProperties ( PropertyId )
ALTER TABLE dbo.WidgetPropertyValues WITH CHECK ADD CONSTRAINT FK_WidgetPropertyValues_Widgets FOREIGN KEY( WidgetId )
REFERENCES dbo.Widgets ( WidgetId )
Jadi Anda melihat bagaimana WidgetId, PropertyId, Revision
merupakan kunci komposit dan tabel menyimpan seluruh riwayat Nilai (nilai saat ini diperoleh dengan mendapatkan baris dengan angka Revision
terbesar untuk setiap WidgetId + PropertyId
.
Saya ingin tahu bagaimana cara mengatur kolom Revision
agar bertambah 1 untuk setiap WidgetId + PropertyId
. Saya ingin data seperti ini:
WidgetId, PropertyId, Revision, DateTime, Value
------------------------------------------------
1 1 1 123
1 1 2 456
1 1 3 789
1 2 1 012
IDENTITY
tidak akan berfungsi karena bersifat global pada tabel dan hal yang sama berlaku dengan objek SEQUENCE
.
Pembaruan Saya dapat memikirkan kemungkinan solusi menggunakan pemicu INSTEAD OF INSERT
:
CREATE TRIGGER WidgetPropertyValueInsertTrigger ON WidgetPropertyValues
INSTEAD OF INSERT
AS
BEGIN
DECLARE @maxRevision int
SELECT @maxRevision = ISNULL( MAX( Revision ), 0 ) FROM WidgetPropertyValues WHERE WidgetId = INSERTED.WidgetId AND PropertyId = INSERTED.PropertyId
INSERT INTO WidgetPropertyValues VALUES (
INSERTED.WidgetId,
INSERTED.PropertyId,
@maxRevision + 1,
INSERTED.DateTime,
INSERTED.Value,
)
END
(Bagi yang belum tahu, pemicu INSTEAD OF INSERT
dijalankan alih-alih operasi INSERT
apa pun di tabel, dibandingkan dengan pemicu INSERT
normal yang dijalankan sebelum atau sesudah operasi INSERT
)
Saya pikir ini akan aman untuk konkurensi karena semua operasi INSERT
memiliki transaksi implisit, dan setiap pemicu terkait dieksekusi dalam konteks transaksi yang sama, yang berarti aman. Kecuali ada yang bisa mengklaim sebaliknya?
IDENTITY
Anda dapat menggunakan fungsi jendelarow_number()
untuk menghitung revisi berdasarkan urutan penyisipannya. - person Kamil Gosciminski   schedule 06.01.2016Revision
harus akurat dan berdekatan sehingga kami dapat mengetahui kapan suatu baris telah dihapus. - person Dai   schedule 06.01.2016IDENTITY
maka kunci komposit tabel berisi kunci pengganti, yang tidak ideal. - person Dai   schedule 06.01.2016DEFAULT
yang memanggil fungsi yang mendapatkan angkaRevision
maksimum untukWidgetId+PropertyId
tertentu? - person Dai   schedule 06.01.2016Revision
yang tidak bersebelahan dan menggunakanIDENTITY
sebagai gantinya. - person Dai   schedule 06.01.2016