Switch warehouse matching to use IDs

This commit is contained in:
2026-06-24 23:25:06 +08:00
parent 4670220614
commit bd9b5a6f4d
27 changed files with 776 additions and 419 deletions
@@ -0,0 +1,162 @@
/*
用途:
1. 为材料出入库和库存表补充 WarehouseId 字段。
2. 将历史 WarehouseCode 中保存的仓库名称/主键统一回填到 WarehouseId。
3. 库存表按 项目+材料主编码+仓库主键 合并重复库存。
执行前建议先备份数据库,并先执行最后的“未匹配检查”确认是否存在重名或缺失仓库。
*/
SET XACT_ABORT ON;
BEGIN TRAN;
IF COL_LENGTH('dbo.Tw_InOutPlanMaster', 'WarehouseId') IS NULL
BEGIN
ALTER TABLE dbo.Tw_InOutPlanMaster ADD WarehouseId NVARCHAR(50) NULL;
END;
IF COL_LENGTH('dbo.Tw_InputMaster', 'WarehouseId') IS NULL
BEGIN
ALTER TABLE dbo.Tw_InputMaster ADD WarehouseId NVARCHAR(50) NULL;
END;
IF COL_LENGTH('dbo.Tw_OutputMaster', 'WarehouseId') IS NULL
BEGIN
ALTER TABLE dbo.Tw_OutputMaster ADD WarehouseId NVARCHAR(50) NULL;
END;
IF COL_LENGTH('dbo.Tw_MaterialStock', 'WarehouseId') IS NULL
BEGIN
ALTER TABLE dbo.Tw_MaterialStock ADD WarehouseId NVARCHAR(50) NULL;
END;
IF EXISTS (
SELECT 1
FROM dbo.Base_Warehouse
GROUP BY ProjectId, WarehouseName
HAVING COUNT(1) > 1
)
BEGIN
THROW 51000, N'同一项目存在重名仓库,历史 WarehouseCode 名称数据无法唯一回填,请先处理 Base_Warehouse 重名数据。', 1;
END;
/* 历史数据中 WarehouseCode 可能保存仓库名称,也可能已经保存 WarehouseId,这里两种都兼容。 */
UPDATE m
SET
m.WarehouseId = w.WarehouseId,
m.WarehouseCode = w.WarehouseName
FROM dbo.Tw_InOutPlanMaster AS m
INNER JOIN dbo.Base_Warehouse AS w
ON w.ProjectId = m.ProjectId
AND (w.WarehouseId = m.WarehouseCode OR w.WarehouseName = m.WarehouseCode OR w.WarehouseId = m.WarehouseId)
WHERE ISNULL(m.WarehouseId, '') <> w.WarehouseId
OR ISNULL(m.WarehouseCode, '') <> w.WarehouseName;
UPDATE m
SET
m.WarehouseId = w.WarehouseId,
m.WarehouseCode = w.WarehouseName
FROM dbo.Tw_InputMaster AS m
INNER JOIN dbo.Base_Warehouse AS w
ON w.ProjectId = m.ProjectId
AND (w.WarehouseId = m.WarehouseCode OR w.WarehouseName = m.WarehouseCode OR w.WarehouseId = m.WarehouseId)
WHERE ISNULL(m.WarehouseId, '') <> w.WarehouseId
OR ISNULL(m.WarehouseCode, '') <> w.WarehouseName;
UPDATE m
SET
m.WarehouseId = w.WarehouseId,
m.WarehouseCode = w.WarehouseName
FROM dbo.Tw_OutputMaster AS m
INNER JOIN dbo.Base_Warehouse AS w
ON w.ProjectId = m.ProjectId
AND (w.WarehouseId = m.WarehouseCode OR w.WarehouseName = m.WarehouseCode OR w.WarehouseId = m.WarehouseId)
WHERE ISNULL(m.WarehouseId, '') <> w.WarehouseId
OR ISNULL(m.WarehouseCode, '') <> w.WarehouseName;
UPDATE s
SET
s.WarehouseId = w.WarehouseId,
s.WarehouseCode = w.WarehouseName
FROM dbo.Tw_MaterialStock AS s
INNER JOIN dbo.Base_Warehouse AS w
ON w.ProjectId = s.ProjectId
AND (w.WarehouseId = s.WarehouseCode OR w.WarehouseName = s.WarehouseCode OR w.WarehouseId = s.WarehouseId)
WHERE ISNULL(s.WarehouseId, '') <> w.WarehouseId
OR ISNULL(s.WarehouseCode, '') <> w.WarehouseName;
/* 回填后,历史上同一仓库可能因“名称”和“主键”各有一条库存记录,这里合并为一条。 */
IF OBJECT_ID('tempdb..#StockMerge') IS NOT NULL
BEGIN
DROP TABLE #StockMerge;
END;
SELECT
ProjectId,
PipeLineMatCode,
WarehouseId,
MIN(Id) AS KeepId,
SUM(ISNULL(StockNum, 0)) AS TotalStock
INTO #StockMerge
FROM dbo.Tw_MaterialStock
WHERE WarehouseId IS NOT NULL
GROUP BY ProjectId, PipeLineMatCode, WarehouseId
HAVING COUNT(1) > 1;
UPDATE s
SET s.StockNum = m.TotalStock
FROM dbo.Tw_MaterialStock AS s
INNER JOIN #StockMerge AS m ON m.KeepId = s.Id;
DELETE s
FROM dbo.Tw_MaterialStock AS s
INNER JOIN #StockMerge AS m
ON m.ProjectId = s.ProjectId
AND m.PipeLineMatCode = s.PipeLineMatCode
AND m.WarehouseId = s.WarehouseId
AND s.Id <> m.KeepId;
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'IX_Tw_InOutPlanMaster_Project_WarehouseId' AND object_id = OBJECT_ID('dbo.Tw_InOutPlanMaster'))
BEGIN
CREATE INDEX IX_Tw_InOutPlanMaster_Project_WarehouseId ON dbo.Tw_InOutPlanMaster(ProjectId, WarehouseId);
END;
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'IX_Tw_InputMaster_Project_WarehouseId' AND object_id = OBJECT_ID('dbo.Tw_InputMaster'))
BEGIN
CREATE INDEX IX_Tw_InputMaster_Project_WarehouseId ON dbo.Tw_InputMaster(ProjectId, WarehouseId);
END;
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'IX_Tw_OutputMaster_Project_WarehouseId' AND object_id = OBJECT_ID('dbo.Tw_OutputMaster'))
BEGIN
CREATE INDEX IX_Tw_OutputMaster_Project_WarehouseId ON dbo.Tw_OutputMaster(ProjectId, WarehouseId);
END;
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'IX_Tw_MaterialStock_Project_Material_WarehouseId' AND object_id = OBJECT_ID('dbo.Tw_MaterialStock'))
BEGIN
CREATE INDEX IX_Tw_MaterialStock_Project_Material_WarehouseId ON dbo.Tw_MaterialStock(ProjectId, PipeLineMatCode, WarehouseId);
END;
COMMIT TRAN;
/* 未匹配检查:这些记录需要人工确认仓库名称是否错误、是否重名或是否缺少 Base_Warehouse 数据。 */
SELECT 'Tw_InOutPlanMaster' AS TableName, Id, ProjectId, WarehouseCode, WarehouseId
FROM dbo.Tw_InOutPlanMaster
WHERE ISNULL(WarehouseCode, '') <> '' AND ISNULL(WarehouseId, '') = ''
UNION ALL
SELECT 'Tw_InputMaster' AS TableName, Id, ProjectId, WarehouseCode, WarehouseId
FROM dbo.Tw_InputMaster
WHERE ISNULL(WarehouseCode, '') <> '' AND ISNULL(WarehouseId, '') = ''
UNION ALL
SELECT 'Tw_OutputMaster' AS TableName, Id, ProjectId, WarehouseCode, WarehouseId
FROM dbo.Tw_OutputMaster
WHERE ISNULL(WarehouseCode, '') <> '' AND ISNULL(WarehouseId, '') = ''
UNION ALL
SELECT 'Tw_MaterialStock' AS TableName, Id, ProjectId, WarehouseCode, WarehouseId
FROM dbo.Tw_MaterialStock
WHERE ISNULL(WarehouseCode, '') <> '' AND ISNULL(WarehouseId, '') = '';
/* 仓库重名检查:如果同一项目有重名仓库,历史名称数据无法唯一回填,需要先处理重名。 */
SELECT ProjectId, WarehouseName, COUNT(1) AS RepeatCount
FROM dbo.Base_Warehouse
GROUP BY ProjectId, WarehouseName
HAVING COUNT(1) > 1;