You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MSSQL环境下基于Knex.js处理Brokers表重复行并关联BrokerIndividuals表的技术方案问询

解决MSSQL中brokers表部分唯一索引及重复数据处理方案

针对你提到的需求——处理brokers表重复数据、关联更新brokerIndividuals外键,以及创建带过滤条件的唯一索引(Knex暂不支持,用原生SQL实现),我整理了一套分步执行的方案,适配MSSQL 6.0.1版本:

1. 先定位重复的活跃经纪公司记录

首先用窗口函数找出所有companyName重复且isDeleted为NULL的行,标记出每组里需要被软删除的重复项:

WITH DuplicateBrokers AS (
    SELECT 
        brokerId,
        companyName,
        isDeleted,
        -- 按brokerId排序,每组第一条标记为rowNum=1,其余为>1
        ROW_NUMBER() OVER (PARTITION BY companyName ORDER BY brokerId) AS rowNum
    FROM brokers
    WHERE isDeleted IS NULL
)
-- 查看所有需要处理的重复行
SELECT * FROM DuplicateBrokers WHERE rowNum > 1;

执行这个查询可以先确认要处理的目标数据,避免误操作。

2. 软删除重复的经纪公司记录

确认重复数据后,将每组中除第一条外的记录isDeleted设为true(这里假设isDeleted是bit类型,MSSQL中1代表true,如果是其他类型请自行调整值):

WITH DuplicateBrokers AS (
    SELECT 
        brokerId,
        ROW_NUMBER() OVER (PARTITION BY companyName ORDER BY brokerId) AS rowNum
    FROM brokers
    WHERE isDeleted IS NULL
)
UPDATE brokers
SET isDeleted = 1
FROM brokers
JOIN DuplicateBrokers ON brokers.brokerId = DuplicateBrokers.brokerId
WHERE DuplicateBrokers.rowNum > 1;

3. 更新关联的经纪人个体外键

接下来把关联到被软删除经纪公司的brokerIndividuals记录,外键更新到每组保留的第一条经纪公司主键:

WITH BrokerGroups AS (
    -- 获取每个companyName对应的主记录(保留的第一条)
    SELECT 
        brokerId AS mainBrokerId,
        companyName
    FROM (
        SELECT 
            brokerId,
            companyName,
            ROW_NUMBER() OVER (PARTITION BY companyName ORDER BY brokerId) AS rowNum
        FROM brokers
        WHERE isDeleted IS NULL
    ) AS ranked
    WHERE rowNum = 1
),
DeletedDuplicates AS (
    -- 获取被软删除的重复经纪公司记录
    SELECT 
        brokerId,
        companyName
    FROM brokers
    WHERE isDeleted = 1
)
UPDATE bi
SET bi.brokerId = bg.mainBrokerId
FROM brokerIndividuals bi
JOIN DeletedDuplicates dd ON bi.brokerId = dd.brokerId
JOIN BrokerGroups bg ON dd.companyName = bg.companyName;

4. 创建带过滤条件的唯一索引

最后创建MSSQL支持的过滤唯一索引,保证isDeleted为NULL的记录中companyName唯一:

CREATE UNIQUE NONCLUSTERED INDEX IX_brokers_companyName_Unique_Active
ON brokers (companyName)
WHERE isDeleted IS NULL;

这个索引会阻止后续插入/更新出现companyName重复且isDeleted为NULL的记录。

在Knex.js中执行原生SQL

因为Knex暂不支持这种带WHERE子句的唯一索引,所以需要用knex.raw()执行上述原生SQL,示例代码如下:

// 软删除重复行
await knex.raw(`
    WITH DuplicateBrokers AS (
        SELECT 
            brokerId,
            ROW_NUMBER() OVER (PARTITION BY companyName ORDER BY brokerId) AS rowNum
        FROM brokers
        WHERE isDeleted IS NULL
    )
    UPDATE brokers
    SET isDeleted = 1
    FROM brokers
    JOIN DuplicateBrokers ON brokers.brokerId = DuplicateBrokers.brokerId
    WHERE DuplicateBrokers.rowNum > 1;
`);

// 更新brokerIndividuals外键
await knex.raw(`
    WITH BrokerGroups AS (
        SELECT 
            brokerId AS mainBrokerId,
            companyName
        FROM (
            SELECT 
                brokerId,
                companyName,
                ROW_NUMBER() OVER (PARTITION BY companyName ORDER BY brokerId) AS rowNum
            FROM brokers
            WHERE isDeleted IS NULL
        ) AS ranked
        WHERE rowNum = 1
    ),
    DeletedDuplicates AS (
        SELECT 
            brokerId,
            companyName
        FROM brokers
        WHERE isDeleted = 1
    )
    UPDATE bi
    SET bi.brokerId = bg.mainBrokerId
    FROM brokerIndividuals bi
    JOIN DeletedDuplicates dd ON bi.brokerId = dd.brokerId
    JOIN BrokerGroups bg ON dd.companyName = bg.companyName;
`);

// 创建过滤唯一索引
await knex.raw(`
    CREATE UNIQUE NONCLUSTERED INDEX IX_brokers_companyName_Unique_Active
    ON brokers (companyName)
    WHERE isDeleted IS NULL;
`);

注意:执行所有操作前,请务必在测试环境验证,并且备份数据,防止数据丢失或误修改。

内容的提问来源于stack exchange,提问作者HAK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 04:57:32