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

解决ORA-01427错误:单行列子查询返回多行问题

解决ORA-01427错误并合并多备选仓位记录

问题背景

PART_LOCATION表中存在大量PART_NO、MFG、LOCATION匹配但BIN_LOC不同的记录,需要将同组内的备选仓位合并到该组TEMP_ID最小的主记录的ALT_BIN_XXX字段,随后删除组内其余非主记录。

原UPDATE语句在仅存在1个备选仓位时可正常执行,但存在多个备选仓位时触发ORA-01427: single-row subquery returns more than one row错误:

update PART_LOCATION a
    set alt_bin_loc_1 = 
    (
     select bin_loc
     from PART_LOCATION b where a.part_no = b.part_no and a.mfg = b.mfg and a.location = b.location and a.bin_loc <> b.bin_loc
     and a.temp_id < b.temp_id
    )
    where exists
    (
     select bin_loc
     from PART_LOCATION b where a.part_no = b.part_no and a.mfg = b.mfg and a.location = b.location and a.bin_loc <> b.bin_loc
     and a.temp_id < b.temp_id
    );

解决方案

步骤1:标记主记录与备选仓位排序

通过窗口函数给每组(按PART_NO、MFG、LOCATION分组)的记录排序,确定主记录(TEMP_ID最小,排序为1),并给备选仓位分配序号,用于后续映射到ALT_BIN_1、ALT_BIN_2等字段:

WITH ranked_bins AS (
    SELECT 
        part_no, mfg, location, bin_loc, temp_id,
        -- 标记主记录(TEMP_ID最小的为1)
        ROW_NUMBER() OVER (PARTITION BY part_no, mfg, location ORDER BY temp_id) AS record_rank,
        -- 给备选仓位按TEMP_ID排序,生成序号
        ROW_NUMBER() OVER (PARTITION BY part_no, mfg, location ORDER BY temp_id) - 1 AS alt_bin_seq
    FROM PART_LOCATION
)
SELECT * FROM ranked_bins;

步骤2:转换备选仓位为列并更新主记录

使用PIVOT将同组内的备选仓位转为多列,通过MERGE语句更新主记录的ALT_BIN_XXX字段:

MERGE INTO PART_LOCATION main
USING (
    SELECT 
        part_no, mfg, location,
        "1" AS alt_bin_loc_1,
        "2" AS alt_bin_loc_2,
        "3" AS alt_bin_loc_3 -- 根据实际备选数量扩展字段
    FROM (
        SELECT 
            part_no, mfg, location, bin_loc,
            ROW_NUMBER() OVER (PARTITION BY part_no, mfg, location ORDER BY temp_id) - 1 AS alt_seq
        FROM PART_LOCATION
        WHERE ROW_NUMBER() OVER (PARTITION BY part_no, mfg, location ORDER BY temp_id) > 1 -- 仅取备选记录
    )
    PIVOT (
        MAX(bin_loc)
        FOR alt_seq IN (1, 2, 3) -- 对应alt_bin_loc_1/2/3,按需添加更多序号
    )
) alt_bins
ON (main.part_no = alt_bins.part_no AND main.mfg = alt_bins.mfg AND main.location = alt_bins.location)
-- 仅更新组内TEMP_ID最小的主记录
WHERE main.temp_id = (SELECT MIN(temp_id) FROM PART_LOCATION WHERE part_no = main.part_no AND mfg = main.mfg AND location = main.location)
WHEN MATCHED THEN UPDATE SET
    main.alt_bin_loc_1 = alt_bins.alt_bin_loc_1,
    main.alt_bin_loc_2 = alt_bins.alt_bin_loc_2,
    main.alt_bin_loc_3 = alt_bins.alt_bin_loc_3; -- 按需扩展更新字段

步骤3:删除非主记录

完成主记录更新后,删除组内TEMP_ID不是最小的冗余记录:

DELETE FROM PART_LOCATION
WHERE (part_no, mfg, location, temp_id) NOT IN (
    SELECT part_no, mfg, location, MIN(temp_id)
    FROM PART_LOCATION
    GROUP BY part_no, mfg, location
);

补充说明

  • 若备选仓位数量超过3个,只需在PIVOT的IN子句和MERGE的更新字段中添加对应序号(如4对应alt_bin_loc_4)即可。
  • 所有操作建议先在测试环境验证,避免误操作生产数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 22:12:51