Tôi đang sử dụng SQL Server 2008 Standard, không có SEQUENCEtính năng này.
Một hệ thống bên ngoài đọc dữ liệu từ một số bảng chuyên dụng của cơ sở dữ liệu chính. Hệ thống bên ngoài giữ một bản sao dữ liệu và kiểm tra định kỳ các thay đổi trong dữ liệu và làm mới bản sao của nó.
Để thực hiện đồng bộ hóa hiệu quả, tôi muốn chỉ chuyển các hàng đã được cập nhật hoặc chèn kể từ đồng bộ hóa trước đó. (Các hàng không bao giờ bị xóa). Để biết hàng nào đã được cập nhật hoặc chèn kể từ lần đồng bộ hóa cuối cùng, có một bigintcột RowUpdateCountertrong mỗi bảng.
Ý tưởng là bất cứ khi nào một hàng được chèn hoặc cập nhật, số trong RowUpdateCountercột của nó sẽ thay đổi. Các giá trị đi vào RowUpdateCountercột phải được lấy từ một chuỗi số ngày càng tăng. Các giá trị trong RowUpdateCountercột phải là duy nhất và mỗi giá trị mới được lưu trữ trong một bảng phải lớn hơn bất kỳ giá trị nào trước đó.
Xin vui lòng xem các kịch bản cho thấy các hành vi mong muốn.
Lược đồ
CREATE TABLE [dbo].[Test](
[ID] [int] NOT NULL,
[Value] [varchar](50) NOT NULL,
[RowUpdateCounter] [bigint] NOT NULL,
CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED
(
[ID] ASC
))
GO
CREATE UNIQUE NONCLUSTERED INDEX [IX_RowUpdateCounter] ON [dbo].[Test]
(
[RowUpdateCounter] ASC
)
GO
XÁC NHẬN một số hàng
INSERT INTO [dbo].[Test]
([ID]
,[Value]
,[RowUpdateCounter])
VALUES
(1, 'A', ???),
(2, 'B', ???),
(3, 'C', ???),
(4, 'D', ???);
Kết quả mong đợi
+----+-------+------------------+
| ID | Value | RowUpdateCounter |
+----+-------+------------------+
| 1 | A | 1 |
| 2 | B | 2 |
| 3 | C | 3 |
| 4 | D | 4 |
+----+-------+------------------+
Các giá trị được tạo ra RowUpdateCountercó thể khác nhau, giả sử 5, 3, 7, 9. Chúng phải là duy nhất và chúng phải lớn hơn 0, vì chúng tôi đã bắt đầu từ bảng trống.
XÁC NHẬN và CẬP NHẬT một số hàng
DECLARE @NewValues TABLE (ID int NOT NULL, Value varchar(50));
INSERT INTO @NewValues (ID, Value) VALUES
(3, 'E'),
(4, 'F'),
(5, 'G'),
(6, 'H');
MERGE INTO dbo.Test WITH (HOLDLOCK) AS Dst
USING
(
SELECT ID, Value
FROM @NewValues
)
AS Src ON Dst.ID = Src.ID
WHEN MATCHED THEN
UPDATE SET
Dst.Value = Src.Value
,Dst.RowUpdateCounter = ???
WHEN NOT MATCHED BY TARGET THEN
INSERT
(ID
,Value
,RowUpdateCounter)
VALUES
(Src.ID
,Src.Value
,???)
;
Kết quả mong đợi
+----+-------+------------------+
| ID | Value | RowUpdateCounter |
+----+-------+------------------+
| 1 | A | 1 |
| 2 | B | 2 |
| 3 | E | 5 |
| 4 | F | 6 |
| 5 | G | 7 |
| 6 | H | 8 |
+----+-------+------------------+
RowUpdateCounterđối với các hàng có ID1,2nên giữ nguyên, vì các hàng này không bị thay đổi.RowUpdateCounterđối với các hàng có ID3,4nên thay đổi, vì chúng đã được cập nhật.RowUpdateCounterđối với các hàng có ID5,6sẽ thay đổi, vì chúng đã được chèn.RowUpdateCounterđối với tất cả các hàng thay đổi phải lớn hơn 4 (cuối cùngRowUpdateCountertừ chuỗi).
Thứ tự mà các giá trị mới ( 5,6,7,8) được gán cho các hàng thay đổi không thực sự quan trọng. Các giá trị mới có thể có khoảng trống, ví dụ 15,26,47,58, nhưng chúng không bao giờ nên giảm.
Có một số bảng với các quầy như vậy trong cơ sở dữ liệu. Sẽ không có vấn đề gì nếu tất cả chúng sử dụng chuỗi toàn cầu duy nhất cho các số của chúng hoặc mỗi bảng có một chuỗi riêng.
Tôi không muốn sử dụng một cột có tem datetime thay vì bộ đếm số nguyên, bởi vì:
Đồng hồ trên máy chủ có thể nhảy cả tiến và lùi. Đặc biệt là khi nó ở trên một máy ảo.
Các giá trị được trả về bởi các hàm hệ thống giống
SYSDATETIMEnhau cho tất cả các hàng bị ảnh hưởng. Quá trình đồng bộ hóa có thể đọc các thay đổi theo đợt. Ví dụ: nếu kích thước lô là 3 hàng, thì sauMERGEbước trên quy trình đồng bộ sẽ chỉ đọc các hàngE,F,G. Khi quá trình đồng bộ được chạy lần sau, nó sẽ tiếp tục từ hàngH.
Cách tôi đang làm bây giờ khá là xấu xí.
Vì không có SEQUENCEtrong SQL Server 2008, tôi mô phỏng SEQUENCEtheo một bảng chuyên dụng với IDENTITYnhư trong câu trả lời này . Điều này tự nó khá xấu xí và trở nên trầm trọng hơn bởi thực tế là tôi cần phải tạo ra không phải một, mà là một loạt các số cùng một lúc.
Sau đó, tôi có một INSTEAD OF UPDATE, INSERTkích hoạt trên mỗi bảng với RowUpdateCountervà tạo các bộ số cần thiết ở đó.
Trong INSERT, UPDATEvà MERGEtruy vấn tôi đặt RowUpdateCounter0, mà được thay thế bằng các giá trị đúng trong cò. Các ???truy vấn trên là 0.
Nó hoạt động, nhưng có một giải pháp dễ dàng hơn?
rowversionsẽ không cho tôi khả năng này, nếu tôi hiểu đúng nó là gì ... Có đảm bảo được ngày càng tăng?
rowversion. Nó trông rất hấp dẫn. Mối quan tâm duy nhất của tôi là tất cả các ví dụ về việc sử dụng nó mà tôi đã thấy cho đến nay đều xoay quanh việc phát hiện xem một hàng có thay đổi hay không. Tôi cần một cách hiệu quả để biết tập hợp hàng nào đã thay đổi kể từ một thời điểm nhất định. Bên cạnh đó, có thể bỏ lỡ một bản cập nhật?
Acập nhật một hàng, chuyển đổi hàng của nó thay đổi thành 123, Achưa được cam kết. time = 2: Giao dịch Bcập nhật một hàng khác, chuyển đổi hàng của nó thay đổi thành 124. time = 3: Bcam kết. time = 4: quá trình đồng bộ hóa chạy và tìm nạp tất cả các hàng có chuyển đổi hàng> 122, có nghĩa là các hàng chỉ được cập nhật theo B. thời gian = 5: Acam kết. Kết quả: thay đổi theo Asẽ không bao giờ được chọn bởi quá trình đồng bộ hóa. Tôi có lầm không? Có thể một số sử dụng thông minh MIN_ACTIVE_ROWVERSIONsẽ giúp?