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

Oracle创建含LEFT OUTER JOIN与MAX子查询的视图触发ORA-01799的解决

错误原因
  • ORA-01799的触发规则是外连接关联条件不允许直接使用依赖外层查询的相关子查询,Oracle对视图创建场景下的该语法校验比直接执行SELECT更严格,因此会出现单独跑SELECT正常、建视图报错的情况。
修复逻辑

将原关联条件中动态计算最大版本的相关子查询,提前通过CTE做全局预聚合,规避外连接条件携带相关子查询的问题,修改后与原查询逻辑完全等价。

修改后的可执行建视图语句
CREATE OR REPLACE VIEW xxxxxx_V (
    ID, SERVICE_ID, PARENT_ID, PARENT_MATERIALITY, PARENT_END_STATUS,
    PARENT_OUTS_TYPE, END_STATUS, MATERIALITY, OUTS_TYPE, CREATED_BY,
    SERVICE_DESCRIPTION_SHORT, VERSION, OUTSOURCER_ID, OUTSOURCER_NAME, 
    INSOURCER_ID, INSOURCER_NAME, PLANNED_SERVICE_START
) AS
WITH latest_risk_map AS (
    SELECT 
        outsourcing_id,
        MAX(version) AS max_risk_version
    FROM OS_RISK_ASSESSMENT
    GROUP BY outsourcing_id
)
SELECT 
    c.id, 
    s.id AS service_id, 
    s.outsourcing_id AS parent_id, 
    p.materiality AS parent_materiality, 
    p.end_status AS parent_end_status,
    p.outsourcing_type AS parent_outs_type, 
    c.end_status, 
    c.materiality, 
    c.outsourcing_type AS outs_type, 
    c.created_by,
    r.service_description_short, 
    r.version, 
    r.outsourcer AS outsourcer_id, 
    o.name AS outsourcer_name, 
    r.insourcer AS insourcer_id,
    i.name AS insourcer_name, 
    r.planned_service_start
FROM OS_OUTSOURCING_CONTRACT c
LEFT JOIN OS_SERVICES s 
    ON s.id = c.service_id
LEFT JOIN OS_OUTSOURCING_CONTRACT p 
    ON p.id = s.outsourcing_id
LEFT JOIN latest_risk_map rm 
    ON rm.outsourcing_id = c.id
LEFT JOIN OS_RISK_ASSESSMENT r 
    ON r.outsourcing_id = rm.outsourcing_id 
    AND r.version = rm.max_risk_version
LEFT JOIN OS_COMPANY_INSOURCER i 
    ON i.id = r.insourcer
LEFT JOIN OS_COMPANY_OUTSOURCER o 
    ON o.id = r.outsourcer
可选优化写法(适配同一外包合同存在多条同最大版本记录的场景)

如果需要避免最大版本下多条重复记录导致的视图结果重复,可改用窗口函数过滤,逻辑更灵活:

CREATE OR REPLACE VIEW xxxxxx_V (
    ID, SERVICE_ID, PARENT_ID, PARENT_MATERIALITY, PARENT_END_STATUS,
    PARENT_OUTS_TYPE, END_STATUS, MATERIALITY, OUTS_TYPE, CREATED_BY,
    SERVICE_DESCRIPTION_SHORT, VERSION, OUTSOURCER_ID, OUTSOURCER_NAME, 
    INSOURCER_ID, INSOURCER_NAME, PLANNED_SERVICE_START
) AS
WITH risk_ranked AS (
    SELECT 
        outsourcing_id,
        service_description_short,
        version,
        outsourcer,
        insourcer,
        planned_service_start,
        ROW_NUMBER() OVER (PARTITION BY outsourcing_id ORDER BY version DESC) AS rn
    FROM OS_RISK_ASSESSMENT
)
SELECT 
    c.id, 
    s.id AS service_id, 
    s.outsourcing_id AS parent_id, 
    p.materiality AS parent_materiality, 
    p.end_status AS parent_end_status,
    p.outsourcing_type AS parent_outs_type, 
    c.end_status, 
    c.materiality, 
    c.outsourcing_type AS outs_type, 
    c.created_by,
    r.service_description_short, 
    r.version, 
    r.outsourcer AS outsourcer_id, 
    o.name AS outsourcer_name, 
    r.insourcer AS insourcer_id,
    i.name AS insourcer_name, 
    r.planned_service_start
FROM OS_OUTSOURCING_CONTRACT c
LEFT JOIN OS_SERVICES s 
    ON s.id = c.service_id
LEFT JOIN OS_OUTSOURCING_CONTRACT p 
    ON p.id = s.outsourcing_id
LEFT JOIN risk_ranked r 
    ON r.outsourcing_id = c.id 
    AND r.rn = 1
LEFT JOIN OS_COMPANY_INSOURCER i 
    ON i.id = r.insourcer
LEFT JOIN OS_COMPANY_OUTSOURCER o 
    ON o.id = r.outsourcer

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.31 04:45:01