Tidak ada dukungan asli untuk jenis kolom ini, tetapi Anda dapat menerapkannya menggunakan pemicu:
CREATE TRIGGER tr_MyTable_Number
ON MyTable
INSTEAD OF INSERT
AS
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN;
WITH MaxNumbers_CTE AS
(
SELECT ParentEntityID, MAX(Number) AS Number
FROM MyTable
WHERE ParentEntityID IN (SELECT ParentEntityID FROM inserted)
)
INSERT MyTable (ParentEntityID, Number)
SELECT
i.ParentEntityID,
ROW_NUMBER() OVER
(
PARTITION BY i.ParentEntityID
ORDER BY (SELECT 1)
) + ISNULL(m.Number, 0) AS Number
FROM inserted i
LEFT JOIN MaxNumbers_CTE m
ON m.ParentEntityID = i.ParentEntityID
COMMIT
Tidak diuji tetapi saya cukup yakin itu akan berhasil. Jika Anda memiliki kunci utama, Anda juga dapat menerapkan ini sebagai AFTER
pemicu (saya tidak suka menggunakan INSTEAD OF
pemicu, mereka lebih sulit dipahami saat Anda perlu memodifikasinya 6 bulan kemudian).
Hanya untuk menjelaskan apa yang terjadi di sini:
-
SERIALIZABLE
adalah mode isolasi paling ketat; itu menjamin bahwa hanya satu transaksi basis data pada satu waktu yang dapat mengeksekusi pernyataan-pernyataan ini, yang kita perlukan untuk menjamin integritas "urutan" ini. Perhatikan bahwa ini mempromosikan seluruh transaksi secara permanen, jadi Anda tidak akan ingin menggunakan ini di dalam transaksi yang berjalan lama. -
CTE mengambil nomor tertinggi yang sudah digunakan untuk setiap ID induk;
-
ROW_NUMBER
menghasilkan urutan unik untuk setiap ID induk (PARTITION BY
) mulai dari angka 1; kami menambahkan ini ke maksimum sebelumnya jika ada satu untuk mendapatkan urutan baru.
Saya mungkin juga harus menyebutkan bahwa jika Anda hanya perlu memasukkan satu entitas anak baru pada satu waktu, Anda lebih baik menyalurkan operasi tersebut melalui prosedur tersimpan daripada menggunakan pemicu - Anda pasti akan mendapatkan kinerja yang lebih baik darinya . Beginilah cara melakukannya saat ini dengan hierarchyid
kolom dalam SQL '08.