-- SyncQueue: staging table for the Access -> SQL Server one-way sync. -- Idempotent: safe to re-run (table created only if absent; indexes only if absent). IF OBJECT_ID('dbo.SyncQueue', 'U') IS NULL BEGIN CREATE TABLE dbo.SyncQueue ( QueueID bigint IDENTITY(1,1) NOT NULL, SourceFile nvarchar(255) NOT NULL, SourceTable nvarchar(255) NOT NULL, SourceLogID bigint NOT NULL, TargetSchema nvarchar(128) NOT NULL, TargetTable nvarchar(255) NOT NULL, RecordID nvarchar(50) NOT NULL, OperateType varchar(10) NOT NULL, RowData nvarchar(max) NULL, Status varchar(10) NOT NULL CONSTRAINT DF_SyncQueue_Status DEFAULT 'pending', RetryCount int NOT NULL CONSTRAINT DF_SyncQueue_Retry DEFAULT 0, ErrorMsg nvarchar(max) NULL, CapturedAt datetime2 NOT NULL CONSTRAINT DF_SyncQueue_Captured DEFAULT sysdatetime(), AppliedAt datetime2 NULL, CONSTRAINT PK_SyncQueue PRIMARY KEY CLUSTERED (QueueID) ); END GO IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'UX_SyncQueue_Dedup' AND object_id = OBJECT_ID('dbo.SyncQueue')) BEGIN CREATE UNIQUE INDEX UX_SyncQueue_Dedup ON dbo.SyncQueue(SourceFile, SourceTable, SourceLogID); END GO IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'IX_SyncQueue_Pending' AND object_id = OBJECT_ID('dbo.SyncQueue')) BEGIN CREATE INDEX IX_SyncQueue_Pending ON dbo.SyncQueue(Status, TargetSchema, TargetTable); END GO -- Cleanup bookkeeping: track when a queue row's Access log counterpart has -- been physically deleted, so cleanup never re-deletes the same IDs and the -- table can be purged to bound its growth. IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID('dbo.SyncQueue') AND name = 'CleanedAt') BEGIN ALTER TABLE dbo.SyncQueue ADD CleanedAt datetime2 NULL; END GO IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'IX_SyncQueue_Cleaned' AND object_id = OBJECT_ID('dbo.SyncQueue')) BEGIN CREATE INDEX IX_SyncQueue_Cleaned ON dbo.SyncQueue(Status, CleanedAt); END GO