Files
ProductionDataBaseSync_Data…/sql/01_sync_queue.sql
Misaka_Company 65939f5e85 feat: SyncQueue table and set-based apply stored procedure
- sql/01_sync_queue.sql: idempotent DDL for dbo.SyncQueue (PK + unique
  dedup index + pending lookup index), safe to re-run.
- sql/02_sync_apply.sql: dbo.usp_SyncApply (@MaxRetries INT=5). Per
  distinct (TargetSchema,TargetTable) it builds column projections from
  sys.columns (excludes ID key/computed/identity/rowversion) and runs a
  dynamic-SQL MERGE (last-write-wins via ROW_NUMBER over SourceLogID DESC)
  for Insert/Update plus a DELETE for the last op = Delete.
  SET IDENTITY_INSERT ON preserves Access PKs.
- tests/conftest.py: sql_conn fixture reads conn_str from gitignored
  config.yaml via load_config; skipped without RUN_INTEGRATION=1.
- tests/test_apply_proc.py: integration test covering IDENTITY-preserving
  INSERT, last-write-wins UPDATE, BIT conversion, and DELETE; cleans up.

Deviation from the brief's procedure (root-cause fix, design preserved):
every JSON path key is quoted ('$."col"') so non-ASCII column names
(e.g. Chinese 名字/数量) parse correctly. Without quoting, JSON_VALUE
raises "JSON path format is not correct" on Chinese columns, which is the
real target schema for this Access->SQL Server sync.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-14 12:12:21 +08:00

43 lines
1.7 KiB
Transact-SQL

-- 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