Oracle中快速排查存储过程问题

为了方便查询,我在写了存储过程自动生成数据视图。但是执行过程中发下失败

sql 复制代码
BEGIN
    CREATE_HYPERTENSION_VIEWS(2026);
END;

下面是存储过程语句:

sql 复制代码
CREATE OR REPLACE PROCEDURE CREATE_HYPERTENSION_VIEWS(
    p_year IN NUMBER
) AS
    v_year_char VARCHAR2(4);  
    v_sql CLOB;               
BEGIN
  
    v_year_char := TO_CHAR(p_year);

    v_sql := 'CREATE OR REPLACE VIEW YJDGXY_' || v_year_char || ' AS
select distinct empiid from (
select empiid from (

SELECT empiid
FROM (
    SELECT empiid, visitdate,
           LEAD(visitdate) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitdate,
           LEAD(visitdate,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_visitdate,
           VISITEVALUATE,
           LEAD(VISITEVALUATE) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_VISITEVALUATE,
           LEAD(VISITEVALUATE,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_VISITEVALUATE,
           MEDICINEBADEFFECT, 
           LEAD(MEDICINEBADEFFECT) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_MEDICINEBADEFFECT,
           LEAD(MEDICINEBADEFFECT,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_MEDICINEBADEFFECT,
           LEAD(referralreason) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_referralreason,
           LEAD(referralreason,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_referralreason,
           LEAD(agencyanddept) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_agencyanddept,
           LEAD(agencyanddept,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_agencyanddept,
           visitway,VISITEFFECT
    FROM mdc_hypertensionvisit 
    WHERE to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-01-01'' 
      AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-04-01''
    )
WHERE VISITEVALUATE = 1 AND VISITEFFECT = 1 
  AND next_visitdate IS NULL AND next_next_visitdate IS NULL


UNION ALL
SELECT empiid
FROM (
    SELECT empiid, visitdate,
           LEAD(visitdate) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitdate,
           LEAD(visitdate,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_visitdate,
           VISITEVALUATE,
           LEAD(VISITEVALUATE) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_VISITEVALUATE,
           LEAD(VISITEVALUATE,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_VISITEVALUATE,
           MEDICINEBADEFFECT, 
           LEAD(MEDICINEBADEFFECT) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_MEDICINEBADEFFECT,
           LEAD(MEDICINEBADEFFECT,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_MEDICINEBADEFFECT,
           LEAD(referralreason) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_referralreason,
           LEAD(referralreason,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_referralreason,
           LEAD(agencyanddept) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_agencyanddept,
           LEAD(agencyanddept,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_agencyanddept,
           visitway,VISITEFFECT
    FROM mdc_hypertensionvisit 
    WHERE to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-01-01'' 
      AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-04-13''
)
WHERE next_visitdate IS NOT NULL AND next_next_visitdate IS NULL 
  AND next_VISITEVALUATE = 1 AND VISITEVALUATE != 1 
  AND VISITEFFECT = 1

UNION ALL
SELECT empiid
FROM (
    SELECT empiid, visitdate,
           LEAD(visitdate) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitdate,
           LEAD(visitdate,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_visitdate,
           VISITEVALUATE,
           LEAD(VISITEVALUATE) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_VISITEVALUATE,
           LEAD(VISITEVALUATE,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_VISITEVALUATE,
           MEDICINEBADEFFECT, 
           LEAD(MEDICINEBADEFFECT) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_MEDICINEBADEFFECT,
           LEAD(MEDICINEBADEFFECT,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_MEDICINEBADEFFECT,
           LEAD(referralreason) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_referralreason,
           LEAD(referralreason,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_referralreason,
           LEAD(agencyanddept) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_agencyanddept,
           LEAD(agencyanddept,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_agencyanddept,
           visitway,VISITEFFECT
    FROM mdc_hypertensionvisit 
    WHERE to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-01-01'' 
      AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-04-26''
)
WHERE next_next_visitdate IS NOT NULL 
  AND next_next_VISITEVALUATE = 1 
  AND next_VISITEVALUATE != 1 AND VISITEVALUATE != 1 
  AND next_visitdate - visitdate <= 14 
  AND next_next_visitdate - next_visitdate <= 14 
  AND (next_agencyanddept IS NOT NULL OR next_referralreason IS NOT NULL) 
  AND VISITEFFECT = 1


UNION ALL
SELECT empiid
FROM (
    SELECT empiid, visitdate,
           LEAD(visitdate) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitdate,
           LEAD(visitdate,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_visitdate,
           VISITEVALUATE,
           LEAD(VISITEVALUATE) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_VISITEVALUATE,
           LEAD(VISITEVALUATE,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_VISITEVALUATE,
           MEDICINEBADEFFECT, 
           LEAD(MEDICINEBADEFFECT) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_MEDICINEBADEFFECT,
           LEAD(MEDICINEBADEFFECT,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_MEDICINEBADEFFECT,
           LEAD(referralreason) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_referralreason,
           LEAD(referralreason,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_referralreason,
           LEAD(agencyanddept) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_agencyanddept,
           LEAD(agencyanddept,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_agencyanddept,
           visitway,VISITEFFECT
    FROM mdc_hypertensionvisit 
    WHERE to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-01-01'' 
      AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-04-26''
)
WHERE next_next_visitdate IS NOT NULL 
  AND next_next_VISITEVALUATE != 1 
  AND next_VISITEVALUATE != 1 AND VISITEVALUATE != 1 
  AND next_visitdate - visitdate <= 14 
  AND next_next_visitdate - next_visitdate <= 14 
  AND (next_agencyanddept IS NOT NULL OR next_referralreason IS NOT NULL) 
  AND VISITEFFECT = 1

UNION ALL
SELECT empiid
FROM mdc_hypertensionvisit
WHERE (constriction >= 180 OR diastolic >= 110)
  AND (referralreason IS NOT NULL OR agencyanddept IS NOT NULL)
  AND to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-01-01'' 
  AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-04-01''
  AND VISITEFFECT = 1
) cc

WHERE EXISTS(
    SELECT empiid FROM (
        SELECT distinct z.empiid 
        FROM mdc_hypertensionvisit z
        LEFT JOIN face_log s ON z.empiid = s.empiid
        LEFT JOIN ehr_pasthistoryrecord t ON z.empiid = t.empiid
        LEFT JOIN mdc_hypertensionrecord r ON z.empiid = r.empiid
        WHERE z.visitdate IS NOT NULL
          AND z.constriction IS NOT NULL
          AND z.DIASTOLIC IS NOT NULL
          AND z.weight IS NOT NULL
          AND z.bmi IS NOT NULL
          AND z.smokecount IS NOT NULL
          AND z.drinkcount IS NOT NULL
          AND z.psychologychange IS NOT NULL
          AND z.obeydoctor IS NOT NULL
          AND z.medicine IS NOT NULL
          AND z.nextdate IS NOT NULL
          AND z.visitdoctor IS NOT NULL
          AND (z.traintimesweek + z.targettraintimesweek + z.trainminute + z.targettrainminute) IS NOT NULL
          AND z.VISITEFFECT = 1
          AND to_char(z.visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-01-01'' 
          AND to_char(z.visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-04-26''
          AND s.submitdate > z.visitDate - 19  
          AND s.submitdate < z.visitdate + 19
          AND t.confirmdate_gxy IS NOT NULL
          AND r.status = 0
          AND z.visitway IN (''1'',''2'')
        
        UNION ALL
        
        SELECT distinct z.empiid 
        FROM mdc_hypertensionvisit z
        LEFT JOIN face_log s ON z.empiid = s.empiid
        LEFT JOIN ehr_pasthistoryrecord t ON z.empiid = t.empiid
        LEFT JOIN mdc_hypertensionrecord r ON z.empiid = r.empiid
        WHERE z.visitdate IS NOT NULL
          AND z.constriction IS NOT NULL
          AND z.DIASTOLIC IS NOT NULL
          AND z.weight IS NOT NULL
          AND z.bmi IS NOT NULL
          AND z.smokecount IS NOT NULL
          AND z.drinkcount IS NOT NULL
          AND z.psychologychange IS NOT NULL
          AND z.obeydoctor IS NOT NULL
          AND z.medicine IS NOT NULL
          AND z.nextdate IS NOT NULL
          AND z.visitdoctor IS NOT NULL
          AND (z.traintimesweek + z.targettraintimesweek + z.trainminute + z.targettrainminute) IS NOT NULL
          AND z.VISITEFFECT = 1
          AND to_char(z.visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-01-01'' 
          AND to_char(z.visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-04-26''
          AND t.confirmdate_gxy IS NOT NULL
          AND r.status = 0
          AND z.visitway IN (''3'')
    ) dd 
    WHERE cc.empiid = dd.empiid
)
) ff';

 
    EXECUTE IMMEDIATE v_sql;
    DBMS_OUTPUT.PUT_LINE('视图 YJDGXY_' || v_year_char || ' 创建成功');
    

    -- =========================================================================
    -- 3. 生成二季度基础视图:EJDGX_年份(如EJDGX_2026)
    -- =========================================================================
    v_sql := 'CREATE OR REPLACE VIEW EJDGX_' || v_year_char || ' AS
select "EMPIID" from (
select distinct empiid from (
select empiid from (
-- 第一步:第一次控制满意且二季度仅1次随访
SELECT empiid
FROM (
    SELECT empiid, visitdate,
           LEAD(visitdate) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitdate,
           LEAD(visitdate,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_visitdate,
           VISITEVALUATE,
           LEAD(VISITEVALUATE) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_VISITEVALUATE,
           LEAD(VISITEVALUATE,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_VISITEVALUATE,
           MEDICINEBADEFFECT, 
           LEAD(MEDICINEBADEFFECT) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_MEDICINEBADEFFECT,
           LEAD(MEDICINEBADEFFECT,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_MEDICINEBADEFFECT,
           LEAD(referralreason) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_referralreason,
           LEAD(referralreason,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_referralreason,
           LEAD(agencyanddept) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_agencyanddept,
           LEAD(agencyanddept,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_agencyanddept,
           visitway,VISITEFFECT
    FROM mdc_hypertensionvisit 
    WHERE to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-04-01'' 
      AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-07-01''
    )
WHERE VISITEVALUATE = 1 AND VISITEFFECT = 1 
  AND next_visitdate IS NULL AND next_next_visitdate IS NULL
  AND visitway IN (''1'',''2'')

-- 第二步:第二次随访控制满意(第一次不满意)
UNION ALL
SELECT empiid
FROM (
    SELECT empiid, visitdate,
           LEAD(visitdate) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitdate,
           LEAD(visitdate,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_visitdate,
           VISITEVALUATE,
           LEAD(VISITEVALUATE) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_VISITEVALUATE,
           LEAD(VISITEVALUATE,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_VISITEVALUATE,
           MEDICINEBADEFFECT, 
           LEAD(MEDICINEBADEFFECT) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_MEDICINEBADEFFECT,
           LEAD(MEDICINEBADEFFECT,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_MEDICINEBADEFFECT,
           LEAD(referralreason) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_referralreason,
           LEAD(referralreason,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_referralreason,
           LEAD(agencyanddept) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_agencyanddept,
           LEAD(agencyanddept,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_agencyanddept,
           LEAD(visitway) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitway,
           visitway,VISITEFFECT
    FROM mdc_hypertensionvisit 
    WHERE to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-04-01'' 
      AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-07-13''
)
WHERE next_visitdate IS NOT NULL AND next_next_visitdate IS NULL 
  AND next_VISITEVALUATE = 1 AND VISITEVALUATE != 1 
  AND VISITEFFECT = 1 AND visitway IN (''1'',''2'')

-- 第三步:第三次随访控制满意(前两次不满意+有转诊)
UNION ALL
SELECT empiid
FROM (
    SELECT empiid, visitdate,
           LEAD(visitdate) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitdate,
           LEAD(visitdate,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_visitdate,
           VISITEVALUATE,
           LEAD(VISITEVALUATE) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_VISITEVALUATE,
           LEAD(VISITEVALUATE,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_VISITEVALUATE,
           MEDICINEBADEFFECT, 
           LEAD(MEDICINEBADEFFECT) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_MEDICINEBADEFFECT,
           LEAD(MEDICINEBADEFFECT,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_MEDICINEBADEFFECT,
           LEAD(referralreason) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_referralreason,
           LEAD(referralreason,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_referralreason,
           LEAD(agencyanddept) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_agencyanddept,
           LEAD(agencyanddept,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_agencyanddept,
           LEAD(visitway) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitway,
           visitway,VISITEFFECT
    FROM mdc_hypertensionvisit 
    WHERE to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-04-01'' 
      AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-07-26''
)
WHERE next_next_visitdate IS NOT NULL 
  AND next_next_VISITEVALUATE = 1 
  AND next_VISITEVALUATE != 1 AND VISITEVALUATE != 1 
  AND next_visitdate - visitdate <= 14 
  AND next_next_visitdate - next_visitdate <= 14 
  AND (next_agencyanddept IS NOT NULL OR next_referralreason IS NOT NULL) 
  AND VISITEFFECT = 1 AND visitway IN (''1'',''2'')

-- 第四步:连续三次控制不满意+第二次转诊
UNION ALL
SELECT empiid
FROM (
    SELECT empiid, visitdate,
           LEAD(visitdate) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitdate,
           LEAD(visitdate,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_visitdate,
           VISITEVALUATE,
           LEAD(VISITEVALUATE) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_VISITEVALUATE,
           LEAD(VISITEVALUATE,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_VISITEVALUATE,
           MEDICINEBADEFFECT, 
           LEAD(MEDICINEBADEFFECT) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_MEDICINEBADEFFECT,
           LEAD(MEDICINEBADEFFECT,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_MEDICINEBADEFFECT,
           LEAD(referralreason) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_referralreason,
           LEAD(referralreason,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_referralreason,
           LEAD(agencyanddept) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_agencyanddept,
           LEAD(agencyanddept,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_agencyanddept,
           LEAD(visitway) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitway,
           visitway,VISITEFFECT
    FROM mdc_hypertensionvisit 
    WHERE to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-04-01'' 
      AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-07-26''
)
WHERE next_next_visitdate IS NOT NULL 
  AND next_next_VISITEVALUATE != 1 
  AND next_VISITEVALUATE != 1 AND VISITEVALUATE != 1 
  AND next_visitdate - visitdate <= 14 
  AND next_next_visitdate - next_visitdate <= 14 
  AND (next_agencyanddept IS NOT NULL OR next_referralreason IS NOT NULL) 
  AND VISITEFFECT = 1 AND visitway IN (''1'',''2'')

-- 第五步:高危血压+转诊
UNION ALL
SELECT empiid
FROM mdc_hypertensionvisit
WHERE (constriction >= 180 OR diastolic >= 110)
  AND (referralreason IS NOT NULL OR agencyanddept IS NOT NULL)
  AND to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-04-01'' 
  AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-07-01''
  AND VISITEFFECT = 1
) cc

-- 第六步:校验随访内容完整性
WHERE EXISTS(
    SELECT empiid FROM (
        SELECT distinct z.empiid 
        FROM mdc_hypertensionvisit z
        LEFT JOIN face_log s ON z.empiid = s.empiid
        LEFT JOIN ehr_pasthistoryrecord t ON z.empiid = t.empiid
        LEFT JOIN mdc_hypertensionrecord r ON z.empiid = r.empiid
        WHERE z.visitdate IS NOT NULL
          AND z.constriction IS NOT NULL
          AND z.DIASTOLIC IS NOT NULL
          AND z.weight IS NOT NULL
          AND z.bmi IS NOT NULL
          AND z.smokecount IS NOT NULL
          AND z.drinkcount IS NOT NULL
          AND z.psychologychange IS NOT NULL
          AND z.obeydoctor IS NOT NULL
          AND z.medicine IS NOT NULL
          AND z.nextdate IS NOT NULL
          AND z.visitdoctor IS NOT NULL
          AND (z.traintimesweek + z.targettraintimesweek + z.trainminute + z.targettrainminute) IS NOT NULL
          AND z.VISITEFFECT = 1
          AND to_char(z.visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-04-01'' 
          AND to_char(z.visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-07-26''
          AND s.submitdate > z.visitDate - 19
          AND s.submitdate < z.visitdate + 19
          AND s.status = 1 AND s.facetype != 4
          AND t.confirmdate_gxy IS NOT NULL
          AND r.status = 0
          AND z.visitway IN (''1'',''2'')
        
        UNION ALL
        
        SELECT distinct z.empiid 
        FROM mdc_hypertensionvisit z
        LEFT JOIN TCS_SERVICESCORERECORD s ON z.empiid = s.empiid
        LEFT JOIN ehr_pasthistoryrecord t ON z.empiid = t.empiid
        LEFT JOIN mdc_hypertensionrecord r ON z.empiid = r.empiid
        WHERE z.visitdate IS NOT NULL
          AND z.constriction IS NOT NULL
          AND z.DIASTOLIC IS NOT NULL
          AND z.weight IS NOT NULL
          AND z.bmi IS NOT NULL
          AND z.smokecount IS NOT NULL
          AND z.drinkcount IS NOT NULL
          AND z.psychologychange IS NOT NULL
          AND z.obeydoctor IS NOT NULL
          AND z.medicine IS NOT NULL
          AND z.nextdate IS NOT NULL
          AND z.visitdoctor IS NOT NULL
          AND (z.traintimesweek + z.targettraintimesweek + z.trainminute + z.targettrainminute) IS NOT NULL
          AND z.VISITEFFECT = 1
          AND to_char(z.visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-04-01'' 
          AND to_char(z.visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-07-26''
          AND t.confirmdate_gxy IS NOT NULL
          AND r.status = 0
          AND z.visitway IN (''3'')
    ) dd 
    WHERE cc.empiid = dd.empiid
)
)
WHERE empiid IN (
    SELECT empiid FROM pub_visitplan 
    WHERE to_char(plandate,''yyyy-mm'') IN (''' || v_year_char || '-01'',''' || v_year_char || '-02'',''' || v_year_char || '-03'')
      AND visitid IS NOT NULL AND businesstype = ''1''
)
AND empiid IN (
    SELECT empiid FROM pub_visitplan 
    WHERE to_char(plandate,''yyyy-mm'') IN (''' || v_year_char || '-04'',''' || v_year_char || '-05'',''' || v_year_char || '-06'')
      AND visitid IS NOT NULL AND businesstype = ''1''
))';

    EXECUTE IMMEDIATE v_sql;
    DBMS_OUTPUT.PUT_LINE('视图 EJDGX_' || v_year_char || ' 创建成功');

    -- =========================================================================
    -- 4. 生成二季度整合视图:EJDGXY_年份(依赖YJDGXY_年份和EJDGX_年份)
    -- =========================================================================
    v_sql := 'CREATE OR REPLACE VIEW EJDGXY_' || v_year_char || ' AS
select distinct "EMPIID" from (
select empiid from (
    SELECT b.empiid 
    FROM YJDGXY_' || v_year_char || ' a, EJDGX_' || v_year_char || ' b 
    WHERE a.empiid = b.empiid

    UNION ALL

    SELECT empiid FROM (
        select empiid from (
            select distinct empiid from (
                select empiid from (
                    -- 第一步:第一次控制满意且二季度仅1次随访
                    SELECT empiid
                    FROM (
                        SELECT empiid, visitdate,
                               LEAD(visitdate) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitdate,
                               LEAD(visitdate,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_visitdate,
                               VISITEVALUATE,
                               LEAD(VISITEVALUATE) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_VISITEVALUATE,
                               LEAD(VISITEVALUATE,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_VISITEVALUATE,
                               MEDICINEBADEFFECT, 
                               LEAD(MEDICINEBADEFFECT) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_MEDICINEBADEFFECT,
                               LEAD(MEDICINEBADEFFECT,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_MEDICINEBADEFFECT,
                               LEAD(referralreason) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_referralreason,
                               LEAD(referralreason,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_referralreason,
                               LEAD(agencyanddept) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_agencyanddept,
                               LEAD(agencyanddept,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_agencyanddept,
                               visitway,VISITEFFECT
                        FROM mdc_hypertensionvisit 
                        WHERE to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-04-01'' 
                          AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-07-01''
                    )
                    WHERE VISITEVALUATE = 1 AND VISITEFFECT = 1 
                      AND next_visitdate IS NULL AND next_next_visitdate IS NULL
                      AND visitway IN (''1'',''2'')

                    -- 第二步:第二次随访控制满意(第一次不满意)
                    UNION ALL
                    SELECT empiid
                    FROM (
                        SELECT empiid, visitdate,
                               LEAD(visitdate) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitdate,
                               LEAD(visitdate,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_visitdate,
                               VISITEVALUATE,
                               LEAD(VISITEVALUATE) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_VISITEVALUATE,
                               LEAD(VISITEVALUATE,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_VISITEVALUATE,
                               MEDICINEBADEFFECT, 
                               LEAD(MEDICINEBADEFFECT) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_MEDICINEBADEFFECT,
                               LEAD(MEDICINEBADEFFECT,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_MEDICINEBADEFFECT,
                               LEAD(referralreason) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_referralreason,
                               LEAD(referralreason,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_referralreason,
                               LEAD(agencyanddept) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_agencyanddept,
                               LEAD(agencyanddept,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_agencyanddept,
                               LEAD(visitway) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitway,
                               visitway,VISITEFFECT
                        FROM mdc_hypertensionvisit 
                        WHERE to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-04-01'' 
                          AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-07-13''
                    )
                    WHERE next_visitdate IS NOT NULL 
                      AND next_VISITEVALUATE = 1 AND VISITEVALUATE != 1 
                      AND VISITEFFECT = 1 AND visitway IN (''1'',''2'')

                    -- 第三步:第三次随访控制满意(前两次不满意+有转诊)
                    UNION ALL
                    SELECT empiid
                    FROM (
                        SELECT empiid, visitdate,
                               LEAD(visitdate) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitdate,
                               LEAD(visitdate,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_visitdate,
                               VISITEVALUATE,
                               LEAD(VISITEVALUATE) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_VISITEVALUATE,
                               LEAD(VISITEVALUATE,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_VISITEVALUATE,
                               MEDICINEBADEFFECT, 
                               LEAD(MEDICINEBADEFFECT) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_MEDICINEBADEFFECT,
                               LEAD(MEDICINEBADEFFECT,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_MEDICINEBADEFFECT,
                               LEAD(referralreason) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_referralreason,
                               LEAD(referralreason,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_referralreason,
                               LEAD(agencyanddept) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_agencyanddept,
                               LEAD(agencyanddept,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_agencyanddept,
                               LEAD(visitway) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitway,
                               visitway,VISITEFFECT
                        FROM mdc_hypertensionvisit 
                        WHERE to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-04-01'' 
                          AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-07-26''
                    )
                    WHERE next_next_visitdate IS NOT NULL 
                      AND next_next_VISITEVALUATE = 1 
                      AND next_VISITEVALUATE != 1 AND VISITEVALUATE != 1 
                      AND next_visitdate - visitdate <= 14 
                      AND next_next_visitdate - next_visitdate <= 14 
                      AND (next_agencyanddept IS NOT NULL OR next_referralreason IS NOT NULL) 
                      AND VISITEFFECT = 1 AND visitway IN (''1'',''2'')

                    -- 第四步:连续三次控制不满意+第二次转诊
                    UNION ALL
                    SELECT empiid
                    FROM (
                        SELECT empiid, visitdate,
                               LEAD(visitdate) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitdate,
                               LEAD(visitdate,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_visitdate,
                               VISITEVALUATE,
                               LEAD(VISITEVALUATE) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_VISITEVALUATE,
                               LEAD(VISITEVALUATE,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_VISITEVALUATE,
                               MEDICINEBADEFFECT, 
                               LEAD(MEDICINEBADEFFECT) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_MEDICINEBADEFFECT,
                               LEAD(MEDICINEBADEFFECT,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_MEDICINEBADEFFECT,
                               LEAD(referralreason) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_referralreason,
                               LEAD(referralreason,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_referralreason,
                               LEAD(agencyanddept) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_agencyanddept,
                               LEAD(agencyanddept,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_agencyanddept,
                               LEAD(visitway) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitway,
                               visitway,VISITEFFECT
                        FROM mdc_hypertensionvisit 
                        WHERE to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-04-01'' 
                          AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-07-26''
                    )
                    WHERE next_next_visitdate IS NOT NULL 
                      AND next_next_VISITEVALUATE != 1 
                      AND next_VISITEVALUATE != 1 AND VISITEVALUATE != 1 
                      AND next_visitdate - visitdate <= 14 
                      AND next_next_visitdate - next_visitdate <= 14 
                      AND (next_agencyanddept IS NOT NULL OR next_referralreason IS NOT NULL) 
                      AND VISITEFFECT = 1 AND visitway IN (''1'',''2'')

                    -- 第五步:高危血压+转诊
                    UNION ALL
                    SELECT empiid
                    FROM mdc_hypertensionvisit
                    WHERE (constriction >= 180 OR diastolic >= 110)
                      AND (referralreason IS NOT NULL OR agencyanddept IS NOT NULL)
                      AND to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-04-01'' 
                      AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-07-14''
                      AND VISITEFFECT = 1
                ) cc

                -- 第六步:校验随访内容完整性
                WHERE EXISTS(
                    SELECT distinct empiid FROM (
                        SELECT distinct z.empiid 
                        FROM mdc_hypertensionvisit z
                        LEFT JOIN face_log s ON z.empiid = s.empiid
                        LEFT JOIN ehr_pasthistoryrecord t ON z.empiid = t.empiid
                        LEFT JOIN mdc_hypertensionrecord r ON z.empiid = r.empiid
                        WHERE z.visitdate IS NOT NULL
                          AND z.constriction IS NOT NULL
                          AND z.DIASTOLIC IS NOT NULL
                          AND z.weight IS NOT NULL
                          AND z.bmi IS NOT NULL
                          AND z.smokecount IS NOT NULL
                          AND z.drinkcount IS NOT NULL
                          AND z.psychologychange IS NOT NULL
                          AND z.obeydoctor IS NOT NULL
                          AND z.medicine IS NOT NULL
                          AND z.nextdate IS NOT NULL
                          AND z.visitdoctor IS NOT NULL
                          AND (z.traintimesweek + z.targettraintimesweek + z.trainminute + z.targettrainminute) IS NOT NULL
                          AND z.VISITEFFECT = 1
                          AND to_char(z.visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-04-01'' 
                          AND to_char(z.visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-07-14''
                          AND s.submitdate > z.visitDate - 19
                          AND s.submitdate < z.visitdate + 19
                          AND s.status = 1 AND s.facetype != 4
                          AND t.confirmdate_gxy IS NOT NULL
                          AND r.status = 0
                          AND z.visitway IN (''1'',''2'')
                        
                        UNION ALL
                        
                        SELECT distinct z.empiid 
                        FROM mdc_hypertensionvisit z
                        LEFT JOIN TCS_SERVICESCORERECORD s ON z.empiid = s.empiid
                        LEFT JOIN ehr_pasthistoryrecord t ON z.empiid = t.empiid
                        LEFT JOIN mdc_hypertensionrecord r ON z.empiid = r.empiid
                        WHERE z.visitdate IS NOT NULL
                          AND z.constriction IS NOT NULL
                          AND z.DIASTOLIC IS NOT NULL
                          AND z.weight IS NOT NULL
                          AND z.bmi IS NOT NULL
                          AND z.smokecount IS NOT NULL
                          AND z.drinkcount IS NOT NULL
                          AND z.psychologychange IS NOT NULL
                          AND z.obeydoctor IS NOT NULL
                          AND z.medicine IS NOT NULL
                          AND z.nextdate IS NOT NULL
                          AND z.visitdoctor IS NOT NULL
                          AND (z.traintimesweek + z.targettraintimesweek + z.trainminute + z.targettrainminute) IS NOT NULL
                          AND z.VISITEFFECT = 1
                          AND to_char(z.visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-04-01'' 
                          AND to_char(z.visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-07-14''
                          AND t.confirmdate_gxy IS NOT NULL
                          AND r.status = 0
                          AND z.visitway IN (''3'')
                    ) dd 
                    WHERE cc.empiid = dd.empiid
                )
            )
        ) 
        WHERE empiid IN (
            SELECT empiid FROM (
                SELECT min(visitdate) AS zxrq, empiid
                FROM mdc_hypertensionvisit
                WHERE to_char(visitdate,''yyyy'') = ''' || v_year_char || ''' 
                GROUP BY empiid
            ) 
            WHERE to_char(zxrq,''yyyy-mm-dd'') >= ''' || v_year_char || '-04-01'' 
              AND to_char(zxrq,''yyyy-mm-dd'') < ''' || v_year_char || '-07-01''
        )
    )
) 
WHERE empiid IN (
    SELECT empiid FROM mdc_hypertensionrecord 
    WHERE to_char(createdate,''yyyy-mm'') > ''' || v_year_char || '-03''
)
)
WHERE empiid IN (
    -- 一季度与二季度随访间隔62-118天
    SELECT b.empiid
    FROM (
        SELECT min(visitdate) AS yjdzxrq, empiid
        FROM mdc_hypertensionvisit
        WHERE to_char(visitdate,''yyyy-mm'') IN (''' || v_year_char || '-01'',''' || v_year_char || '-02'',''' || v_year_char || '-03'')
        GROUP BY empiid
    ) a
    RIGHT JOIN (
        SELECT min(visitdate) AS ejdzxrq, empiid
        FROM mdc_hypertensionvisit
        WHERE to_char(visitdate,''yyyy-mm'') IN (''' || v_year_char || '-04'',''' || v_year_char || '-05'',''' || v_year_char || '-06'')
        GROUP BY empiid
    ) b ON a.empiid = b.empiid
    WHERE b.ejdzxrq - a.yjdzxrq BETWEEN 62 AND 118

    UNION

    -- 一季度无随访,二季度新增患者
    SELECT b.empiid
    FROM (
        SELECT min(visitdate) AS yjdzxrq, empiid
        FROM mdc_hypertensionvisit
        WHERE to_char(visitdate,''yyyy-mm'') IN (''' || v_year_char || '-01'',''' || v_year_char || '-02'',''' || v_year_char || '-03'')
        GROUP BY empiid
    ) a
    RIGHT JOIN (
        SELECT min(visitdate) AS ejdzxrq, empiid
        FROM mdc_hypertensionvisit
        WHERE to_char(visitdate,''yyyy-mm'') IN (''' || v_year_char || '-04'',''' || v_year_char || '-05'',''' || v_year_char || '-06'')
        GROUP BY empiid
    ) b ON a.empiid = b.empiid
    WHERE a.empiid IS NULL

    UNION

    -- 随访计划中一季度与二季度间隔62-118天
    SELECT a.empiid
    FROM (
        SELECT visitdate AS ejdzxrq, empiid
        FROM pub_visitplan 
        WHERE visitid IS NOT NULL
          AND to_char(visitdate,''yyyy-mm'') IN (''' || v_year_char || '-04'',''' || v_year_char || '-05'',''' || v_year_char || '-06'')
          AND visitmeddle = ''0'' AND businesstype = ''1''
    ) a, (
        SELECT visitdate AS yjdzxrq, empiid
        FROM pub_visitplan 
        WHERE visitid IS NOT NULL
          AND to_char(visitdate,''yyyy-mm'') IN (''' || v_year_char || '-01'',''' || v_year_char || '-02'',''' || v_year_char || '-03'')
          AND visitmeddle = ''0'' AND businesstype = ''1''
    ) b
    WHERE a.empiid = b.empiid
      AND a.ejdzxrq - b.yjdzxrq BETWEEN 62 AND 118
)
';

    EXECUTE IMMEDIATE v_sql;
    DBMS_OUTPUT.PUT_LINE('视图 EJDGXY_' || v_year_char || ' 创建成功');

    -- =========================================================================
    -- 5. 生成三季度基础视图:SJDGXY_CS_年份(如SJDGXY_CS_2026)
    -- =========================================================================
    v_sql := 'CREATE OR REPLACE VIEW SJDGXY_CS_' || v_year_char || ' AS
select distinct empiid from (
select empiid from (
-- 第一步:第一次控制满意且三季度仅1次随访
SELECT empiid
FROM (
    SELECT empiid, visitdate,
           LEAD(visitdate) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitdate,
           LEAD(visitdate,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_visitdate,
           VISITEVALUATE,
           LEAD(VISITEVALUATE) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_VISITEVALUATE,
           LEAD(VISITEVALUATE,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_VISITEVALUATE,
           MEDICINEBADEFFECT, 
           LEAD(MEDICINEBADEFFECT) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_MEDICINEBADEFFECT,
           LEAD(MEDICINEBADEFFECT,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_MEDICINEBADEFFECT,
           LEAD(referralreason) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_referralreason,
           LEAD(referralreason,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_referralreason,
           LEAD(agencyanddept) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_agencyanddept,
           LEAD(agencyanddept,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_agencyanddept,
           visitway,VISITEFFECT
    FROM mdc_hypertensionvisit 
    WHERE to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-07-01'' 
      AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-10-01''
    )
WHERE VISITEVALUATE = 1 AND VISITEFFECT = 1 
  AND next_visitdate IS NULL AND next_next_visitdate IS NULL
  AND visitway IN (''1'',''2'')

-- 第二步:第二次随访控制满意(第一次不满意+14天内随访)
UNION ALL
SELECT empiid
FROM (
    SELECT empiid, visitdate,
           LEAD(visitdate) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitdate,
           LEAD(visitdate,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_visitdate,
           VISITEVALUATE,
           LEAD(VISITEVALUATE) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_VISITEVALUATE,
           LEAD(VISITEVALUATE,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_VISITEVALUATE,
           MEDICINEBADEFFECT, 
           LEAD(MEDICINEBADEFFECT) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_MEDICINEBADEFFECT,
           LEAD(MEDICINEBADEFFECT,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_MEDICINEBADEFFECT,
           LEAD(referralreason) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_referralreason,
           LEAD(referralreason,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_referralreason,
           LEAD(agencyanddept) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_agencyanddept,
           LEAD(agencyanddept,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_agencyanddept,
           visitway,VISITEFFECT
    FROM mdc_hypertensionvisit 
    WHERE to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-07-01'' 
      AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-10-13''
)
WHERE next_visitdate IS NOT NULL 
  AND next_VISITEVALUATE = 1 AND VISITEVALUATE != 1 
  AND VISITEFFECT = 1 AND visitway IN (''1'',''2'')
  AND next_visitdate - visitdate <= 14

-- 第三步:第三次随访控制满意(前两次不满意+有转诊)
UNION ALL
SELECT empiid
FROM (
    SELECT empiid, visitdate,
           LEAD(visitdate) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitdate,
           LEAD(visitdate,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_visitdate,
           VISITEVALUATE,
           LEAD(VISITEVALUATE) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_VISITEVALUATE,
           LEAD(VISITEVALUATE,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_VISITEVALUATE,
           MEDICINEBADEFFECT, 
           LEAD(MEDICINEBADEFFECT) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_MEDICINEBADEFFECT,
           LEAD(MEDICINEBADEFFECT,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_MEDICINEBADEFFECT,
           LEAD(referralreason) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_referralreason,
           LEAD(referralreason,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_referralreason,
           LEAD(agencyanddept) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_agencyanddept,
           LEAD(agencyanddept,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_agencyanddept,
           visitway,VISITEFFECT
    FROM mdc_hypertensionvisit 
    WHERE to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-07-01'' 
      AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-10-26''
)
WHERE next_next_visitdate IS NOT NULL 
  AND next_next_VISITEVALUATE = 1 
  AND next_VISITEVALUATE != 1 AND VISITEVALUATE != 1 
  AND next_visitdate - visitdate <= 14 
  AND next_next_visitdate - next_visitdate <= 14 
  AND (next_agencyanddept IS NOT NULL OR next_referralreason IS NOT NULL) 
  AND VISITEFFECT = 1 AND visitway IN (''1'',''2'')

-- 第四步:连续三次控制不满意+第二次转诊
UNION ALL
SELECT empiid
FROM (
    SELECT empiid, visitdate,
           LEAD(visitdate) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitdate,
           LEAD(visitdate,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_visitdate,
           VISITEVALUATE,
           LEAD(VISITEVALUATE) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_VISITEVALUATE,
           LEAD(VISITEVALUATE,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_VISITEVALUATE,
           MEDICINEBADEFFECT, 
           LEAD(MEDICINEBADEFFECT) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_MEDICINEBADEFFECT,
           LEAD(MEDICINEBADEFFECT,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_MEDICINEBADEFFECT,
           LEAD(referralreason) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_referralreason,
           LEAD(referralreason,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_referralreason,
           LEAD(agencyanddept) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_agencyanddept,
           LEAD(agencyanddept,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_agencyanddept,
           visitway,VISITEFFECT
    FROM mdc_hypertensionvisit 
    WHERE to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-07-01'' 
      AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-10-26''
)
WHERE next_next_visitdate        IS NOT NULL 
  AND next_next_VISITEVALUATE != 1 
  AND next_VISITEVALUATE != 1 AND VISITEVALUATE != 1 
  AND next_visitdate - visitdate <= 14 
  AND next_next_visitdate - next_visitdate <= 14 
  AND (next_agencyanddept IS NOT NULL OR next_referralreason IS NOT NULL) 
  AND VISITEFFECT = 1 AND visitway IN (''1'',''2'')

-- 第五步:高危血压+转诊
UNION ALL
SELECT empiid
FROM mdc_hypertensionvisit
WHERE (constriction >= 180 OR diastolic >= 110)
  AND (referralreason IS NOT NULL OR agencyanddept IS NOT NULL)
  AND to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-07-01'' 
  AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-10-01''
  AND VISITEFFECT = 1
) cc

-- 第六步:校验随访内容完整性
WHERE EXISTS(
    SELECT distinct empiid FROM (
        SELECT z.empiid 
        FROM mdc_hypertensionvisit z
        LEFT JOIN face_log s ON z.empiid = s.empiid
        LEFT JOIN ehr_pasthistoryrecord t ON z.empiid = t.empiid
        LEFT JOIN mdc_hypertensionrecord r ON z.empiid = r.empiid
        WHERE z.visitdate IS NOT NULL
          AND z.constriction IS NOT NULL
          AND z.DIASTOLIC IS NOT NULL
          AND z.weight IS NOT NULL
          AND z.bmi IS NOT NULL
          AND z.smokecount IS NOT NULL
          AND z.drinkcount IS NOT NULL
          AND z.psychologychange IS NOT NULL
          AND z.obeydoctor IS NOT NULL
          AND z.medicine IS NOT NULL
          AND z.nextdate IS NOT NULL
          AND z.visitdoctor IS NOT NULL
          AND (z.traintimesweek + z.targettraintimesweek + z.trainminute + z.targettrainminute) IS NOT NULL
          AND z.VISITEFFECT = 1
          AND to_char(z.visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-07-01'' 
          AND to_char(z.visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-10-26''
          AND s.submitdate > z.visitDate - 19
          AND s.submitdate < z.visitdate + 19
          AND s.status = 1 AND s.facetype != 4
          AND t.confirmdate_gxy IS NOT NULL
          AND r.status = 0
          AND z.visitway IN (''1'',''2'')
        
        UNION ALL
        
        SELECT z.empiid 
        FROM mdc_hypertensionvisit z
        LEFT JOIN TCS_SERVICESCORERECORD s ON z.empiid = s.empiid
        LEFT JOIN ehr_pasthistoryrecord t ON z.empiid = t.empiid
        LEFT JOIN mdc_hypertensionrecord r ON z.empiid = r.empiid
        WHERE z.visitdate IS NOT NULL
          AND z.constriction IS NOT NULL
          AND z.DIASTOLIC IS NOT NULL
          AND z.weight IS NOT NULL
          AND z.bmi IS NOT NULL
          AND z.smokecount IS NOT NULL
          AND z.drinkcount IS NOT NULL
          AND z.psychologychange IS NOT NULL
          AND z.obeydoctor IS NOT NULL
          AND z.medicine IS NOT NULL
          AND z.nextdate IS NOT NULL
          AND z.visitdoctor IS NOT NULL
          AND (z.traintimesweek + z.targettraintimesweek + z.trainminute + z.targettrainminute) IS NOT NULL
          AND z.VISITEFFECT = 1
          AND to_char(z.visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-07-01'' 
          AND to_char(z.visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-10-26''
          AND t.confirmdate_gxy IS NOT NULL
          AND r.status = 0
          AND z.visitway IN (''3'')
    ) dd 
    WHERE cc.empiid = dd.empiid
)
)';

    EXECUTE IMMEDIATE v_sql;
    DBMS_OUTPUT.PUT_LINE('视图 SJDGXY_CS_' || v_year_char || ' 创建成功');

    -- =========================================================================
    -- 6. 生成三季度整合视图:SANJDGXY_年份(依赖EJDGXY_年份和SJDGXY_CS_年份)
    -- =========================================================================
    v_sql := 'CREATE OR REPLACE VIEW SANJDGXY_' || v_year_char || ' AS
select distinct "EMPIID" from (
-- 二季度规范患者+三季度规范患者
SELECT b.empiid 
FROM EJDGXY_' || v_year_char || ' a, SJDGXY_CS_' || v_year_char || ' b 
WHERE a.empiid = b.empiid

UNION ALL

-- 三季度新增规范患者(无一季度随访记录)
SELECT empiid FROM (
    select empiid from (
        -- 第一步:第一次控制满意且三季度仅1次随访
        SELECT empiid
        FROM (
            SELECT empiid, visitdate,
                   LEAD(visitdate) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitdate,
                   LEAD(visitdate,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_visitdate,
                   VISITEVALUATE,
                   LEAD(VISITEVALUATE) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_VISITEVALUATE,
                   LEAD(VISITEVALUATE,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_VISITEVALUATE,
                   MEDICINEBADEFFECT, 
                   LEAD(MEDICINEBADEFFECT) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_MEDICINEBADEFFECT,
                   LEAD(MEDICINEBADEFFECT,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_MEDICINEBADEFFECT,
                   LEAD(referralreason) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_referralreason,
                   LEAD(referralreason,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_referralreason,
                   LEAD(agencyanddept) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_agencyanddept,
                   LEAD(agencyanddept,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_agencyanddept,
                   visitway,VISITEFFECT
            FROM mdc_hypertensionvisit 
            WHERE to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-07-01'' 
              AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-10-01''
        )
        WHERE VISITEVALUATE = 1 AND VISITEFFECT = 1 
          AND next_visitdate IS NULL AND next_next_visitdate IS NULL
          AND visitway IN (''1'',''2'')

        -- 第二步:第二次随访控制满意(第一次不满意)
        UNION ALL
        SELECT empiid
        FROM (
            SELECT empiid, visitdate,
                   LEAD(visitdate) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitdate,
                   LEAD(visitdate,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_visitdate,
                   VISITEVALUATE,
                   LEAD(VISITEVALUATE) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_VISITEVALUATE,
                   LEAD(VISITEVALUATE,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_VISITEVALUATE,
                   MEDICINEBADEFFECT, 
                   LEAD(MEDICINEBADEFFECT) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_MEDICINEBADEFFECT,
                   LEAD(MEDICINEBADEFFECT,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_MEDICINEBADEFFECT,
                   LEAD(referralreason) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_referralreason,
                   LEAD(referralreason,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_referralreason,
                   LEAD(agencyanddept) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_agencyanddept,
                   LEAD(agencyanddept,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_agencyanddept,
                   LEAD(visitway) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitway,
                   visitway,VISITEFFECT
            FROM mdc_hypertensionvisit 
            WHERE to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-07-01'' 
              AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-10-13''
        )
        WHERE next_visitdate IS NOT NULL AND next_next_visitdate IS NULL 
          AND next_VISITEVALUATE = 1 AND VISITEVALUATE != 1 
          AND VISITEFFECT = 1 AND visitway IN (''1'',''2'')

        -- 第三步:第三次随访控制满意(前两次不满意+有转诊)
        UNION ALL
        SELECT empiid
        FROM (
            SELECT empiid, visitdate,
                   LEAD(visitdate) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitdate,
                   LEAD(visitdate,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_visitdate,
                   VISITEVALUATE,
                   LEAD(VISITEVALUATE) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_VISITEVALUATE,
                   LEAD(VISITEVALUATE,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_VISITEVALUATE,
                   MEDICINEBADEFFECT, 
                   LEAD(MEDICINEBADEFFECT) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_MEDICINEBADEFFECT,
                   LEAD(MEDICINEBADEFFECT,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_MEDICINEBADEFFECT,
                   LEAD(referralreason) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_referralreason,
                   LEAD(referralreason,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_referralreason,
                   LEAD(agencyanddept) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_agencyanddept,
                   LEAD(agencyanddept,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_agencyanddept,
                   LEAD(visitway) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitway,
                   visitway,VISITEFFECT
            FROM mdc_hypertensionvisit 
            WHERE to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-07-01'' 
              AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-10-26''
        )
        WHERE next_next_visitdate IS NOT NULL 
          AND next_next_VISITEVALUATE = 1 
          AND next_VISITEVALUATE != 1 AND VISITEVALUATE != 1 
          AND next_visitdate - visitdate <= 14 
          AND next_next_visitdate - next_visitdate <= 14 
          AND (next_agencyanddept IS NOT NULL OR next_referralreason IS NOT NULL) 
          AND VISITEFFECT = 1 AND visitway IN (''1'',''2'')

        -- 第四步:连续三次控制不满意+第二次转诊
        UNION ALL
        SELECT empiid
        FROM (
            SELECT empiid, visitdate,
                   LEAD(visitdate) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitdate,
                   LEAD(visitdate,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_visitdate,
                   VISITEVALUATE,
                   LEAD(VISITEVALUATE) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_VISITEVALUATE,
                   LEAD(VISITEVALUATE,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_VISITEVALUATE,
                   MEDICINEBADEFFECT, 
                   LEAD(MEDICINEBADEFFECT) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_MEDICINEBADEFFECT,
                   LEAD(MEDICINEBADEFFECT,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_MEDICINEBADEFFECT,
                   LEAD(referralreason) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_referralreason,
                   LEAD(referralreason,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_referralreason,
                   LEAD(agencyanddept) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_agencyanddept,
                   LEAD(agencyanddept,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_agencyanddept,
                   LEAD(visitway) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitway,
                   visitway,VISITEFFECT
            FROM mdc_hypertensionvisit 
            WHERE to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-07-01'' 
              AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-10-26''
        )
        WHERE next_next_visitdate IS NOT NULL 
          AND next_next_VISITEVALUATE != 1 
          AND next_VISITEVALUATE != 1 AND VISITEVALUATE != 1 
          AND next_visitdate - visitdate <= 14 
          AND next_next_visitdate - next_visitdate <= 14 
          AND (next_agencyanddept IS NOT NULL OR next_referralreason IS NOT NULL) 
          AND VISITEFFECT = 1 AND visitway IN (''1'',''2'')

        -- 第五步:高危血压+转诊
        UNION ALL
        SELECT empiid
        FROM mdc_hypertensionvisit
        WHERE (constriction >= 180 OR diastolic >= 110)
          AND (referralreason IS NOT NULL OR agencyanddept IS NOT NULL)
          AND to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-07-01'' 
          AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-10-01''
          AND VISITEFFECT = 1
    ) cc

    -- 第六步:校验随访内容完整性
    WHERE EXISTS(
        SELECT distinct empiid FROM (
            SELECT z.empiid 
            FROM mdc_hypertensionvisit z
            LEFT JOIN face_log s ON z.empiid = s.empiid
            LEFT JOIN ehr_pasthistoryrecord t ON z.empiid = t.empiid
            LEFT JOIN mdc_hypertensionrecord r ON z.empiid = r.empiid
            WHERE z.visitdate IS NOT NULL
              AND z.constriction IS NOT NULL
              AND z.DIASTOLIC IS NOT NULL
              AND z.weight IS NOT NULL
              AND z.bmi IS NOT NULL
              AND z.smokecount IS NOT NULL
              AND z.drinkcount IS NOT NULL
              AND z.psychologychange IS NOT NULL
              AND z.obeydoctor IS NOT NULL
              AND z.medicine IS NOT NULL
              AND z.nextdate IS NOT NULL
              AND z.visitdoctor IS NOT NULL
              AND (z.traintimesweek + z.targettraintimesweek + z.trainminute + z.targettrainminute) IS NOT NULL
              AND z.VISITEFFECT = 1
              AND to_char(z.visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-07-01'' 
              AND to_char(z.visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-10-14''
              AND s.submitdate > z.visitDate - 19
              AND s.submitdate < z.visitdate + 19
              AND s.status = 1 AND s.facetype != 4
              AND t.confirmdate_gxy IS NOT NULL
              AND r.status = 0
              AND z.visitway IN (''1'',''2'')
            
            UNION ALL
            
            SELECT z.empiid 
            FROM mdc_hypertensionvisit z
            LEFT JOIN TCS_SERVICESCORERECORD s ON z.empiid = s.empiid
            LEFT JOIN ehr_pasthistoryrecord t ON z.empiid = t.empiid
            LEFT JOIN mdc_hypertensionrecord r ON z.empiid = r.empiid
            WHERE z.visitdate IS NOT NULL
              AND z.constriction IS NOT NULL
              AND z.DIASTOLIC IS NOT NULL
              AND z.weight IS NOT NULL
              AND z.bmi IS NOT NULL
              AND z.smokecount IS NOT NULL
              AND z.drinkcount IS NOT NULL
              AND z.psychologychange IS NOT NULL
              AND z.obeydoctor IS NOT NULL
              AND z.medicine IS NOT NULL
              AND z.nextdate IS NOT NULL
              AND z.visitdoctor IS NOT NULL
              AND (z.traintimesweek + z.targettraintimesweek + z.trainminute + z.targettrainminute) IS NOT NULL
              AND z.VISITEFFECT = 1
              AND to_char(z.visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-07-01'' 
              AND to_char(z.visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-10-14''
              AND t.confirmdate_gxy IS NOT NULL
              AND r.status = 0
              AND z.visitway IN (''3'')
        ) dd 
        WHERE cc.empiid = dd.empiid
    )
) 
WHERE empiid IN (
    SELECT empiid FROM (
        SELECT min(visitdate) AS zxrq, empiid
        FROM mdc_hypertensionvisit
        WHERE to_char(visitdate,''yyyy'') = ''' || v_year_char || ''' 
        GROUP BY empiid
    ) 
    WHERE to_char(zxrq,''yyyy-mm-dd'') >= ''' || v_year_char || '-07-01'' 
      AND to_char(zxrq,''yyyy-mm-dd'') < ''' || v_year_char || '-10-01''
)

UNION ALL

-- 二季度开始且三季度规范的患者(无一季度随访)
SELECT empiid FROM (
    SELECT a.empiid 
    FROM EJDGX_' || v_year_char || ' a, SJDGXY_CS_' || v_year_char || ' b 
    WHERE a.empiid = b.empiid
) abb 
WHERE NOT EXISTS(
    SELECT 1 FROM (
        SELECT distinct empiid 
        FROM mdc_hypertensionvisit 
        WHERE to_char(visitdate,''yyyy-mm'') IN (''' || v_year_char || '-01'',''' || v_year_char || '-02'',''' || v_year_char || '-03'')
    ) abc 
    WHERE abc.empiid = abb.empiid
)
)
WHERE empiid IN (
    -- 二季度与三季度随访间隔62-118天
    SELECT b.empiid
    FROM (
        SELECT min(visitdate) AS yjdzxrq, empiid
        FROM mdc_hypertensionvisit
        WHERE to_char(visitdate,''yyyy-mm'') IN (''' || v_year_char || '-04'',''' || v_year_char || '-05'',''' || v_year_char || '-06'')
        GROUP BY empiid
    ) a
    RIGHT JOIN (
        SELECT min(visitdate) AS ejdzxrq, empiid
        FROM mdc_hypertensionvisit
        WHERE to_char(visitdate,''yyyy-mm'') IN (''' || v_year_char || '-07'',''' || v_year_char || '-08'',''' || v_year_char || '-09'')
        GROUP BY empiid
    ) b ON a.empiid = b.empiid
    WHERE b.ejdzxrq - a.yjdzxrq BETWEEN 62 AND 118

    UNION

    -- 二季度无随访,三季度新增患者
    SELECT b.empiid
    FROM (
        SELECT min(visitdate) AS yjdzxrq, empiid
        FROM mdc_hypertensionvisit
        WHERE to_char(visitdate,''yyyy-mm'') IN (''' || v_year_char || '-04'',''' || v_year_char || '-05'',''' || v_year_char || '-06'')
        GROUP BY empiid
    ) a
    RIGHT JOIN (
        SELECT min(visitdate) AS ejdzxrq, empiid
        FROM mdc_hypertensionvisit
        WHERE to_char(visitdate,''yyyy-mm'') IN (''' || v_year_char || '-07'',''' || v_year_char || '-08'',''' || v_year_char || '-09'')
        GROUP BY empiid
    ) b ON a.empiid = b.empiid
    WHERE a.empiid IS NULL

    UNION

    -- 随访计划中二季度与三季度间隔62-118天
    SELECT a.empiid
    FROM (
        SELECT visitdate AS ejdzxrq, empiid
        FROM pub_visitplan 
        WHERE visitid IS NOT NULL
          AND to_char(visitdate,''yyyy-mm'') IN (''' || v_year_char || '-07'',''' || v_year_char || '-08'',''' || v_year_char || '-09'')
          AND visitmeddle = ''0'' AND businesstype = ''1''
    ) a, (
        SELECT visitdate AS yjdzxrq, empiid
        FROM pub_visitplan 
        WHERE visitid IS NOT NULL
          AND to_char(visitdate,''yyyy-mm'') IN (''' || v_year_char || '-04'',''' || v_year_char || '-05'',''' || v_year_char || '-06'')
          AND visitmeddle = ''0'' AND businesstype = ''1''
    ) b
    WHERE a.empiid = b.empiid
      AND a.ejdzxrq - b.yjdzxrq BETWEEN 62 AND 118
)
';

    EXECUTE IMMEDIATE v_sql;
    DBMS_OUTPUT.PUT_LINE('视图 SANJDGXY_' || v_year_char || ' 创建成功');

    -- =========================================================================
    -- 7. 生成四季度基础视图:SIJDGXY_CS_年份(如SIJDGXY_CS_2026)
    -- =========================================================================
    v_sql := 'CREATE OR REPLACE VIEW SIJDGXY_CS_' || v_year_char || ' AS
select distinct empiid from (
select empiid from (
-- 第一步:第一次控制满意且四季度仅1次随访
SELECT distinct empiid
FROM (
    SELECT empiid, visitdate,
           LEAD(visitdate) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitdate,
           LEAD(visitdate,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_visitdate,
           VISITEVALUATE,
           LEAD(VISITEVALUATE) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_VISITEVALUATE,
           LEAD(VISITEVALUATE,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_VISITEVALUATE,
           MEDICINEBADEFFECT, 
           LEAD(MEDICINEBADEFFECT) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_MEDICINEBADEFFECT,
           LEAD(MEDICINEBADEFFECT,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_MEDICINEBADEFFECT,
           LEAD(referralreason) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_referralreason,
           LEAD(referralreason,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_referralreason,
           LEAD(agencyanddept) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_agencyanddept,
           LEAD(agencyanddept,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_agencyanddept,
           visitway,VISITEFFECT
    FROM mdc_hypertensionvisit 
    WHERE to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-10-01'' 
      AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-12-31''
    )
WHERE VISITEVALUATE = 1 AND VISITEFFECT = 1 
  AND next_visitdate IS NULL AND next_next_visitdate IS NULL
  AND visitway IN (''1'',''2'')

-- 第二步:第二次随访控制满意(第一次不满意)
UNION
SELECT distinct empiid
FROM (
    SELECT empiid, visitdate,
           LEAD(visitdate) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitdate,
           LEAD(visitdate,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_visitdate,
           VISITEVALUATE,
           LEAD(VISITEVALUATE) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_VISITEVALUATE,
           LEAD(VISITEVALUATE,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_VISITEVALUATE,
           MEDICINEBADEFFECT, 
           LEAD(MEDICINEBADEFFECT) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_MEDICINEBADEFFECT,
           LEAD(MEDICINEBADEFFECT,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_MEDICINEBADEFFECT,
           LEAD(referralreason) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_referralreason,
           LEAD(referralreason,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_referralreason,
           LEAD(agencyanddept) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_agencyanddept,
           LEAD(agencyanddept,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_agencyanddept,
           LEAD(visitway) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitway,
           visitway,VISITEFFECT
    FROM mdc_hypertensionvisit 
    WHERE to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-10-01'' 
      AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-12-31''
)
WHERE next_visitdate IS NOT NULL AND next_next_visitdate IS NULL 
  AND next_VISITEVALUATE = 1 AND VISITEVALUATE != 1 
  AND VISITEFFECT = 1 AND visitway IN (''1'',''2'')

-- 第三步:第三次随访控制满意(前两次不满意+有转诊)
UNION
SELECT distinct empiid
FROM (
    SELECT empiid, visitdate,
           LEAD(visitdate) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitdate,
           LEAD(visitdate,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_visitdate,
           VISITEVALUATE,
           LEAD(VISITEVALUATE) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_VISITEVALUATE,
           LEAD(VISITEVALUATE,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_VISITEVALUATE,
           MEDICINEBADEFFECT, 
           LEAD(MEDICINEBADEFFECT) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_MEDICINEBADEFFECT,
           LEAD(MEDICINEBADEFFECT,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_MEDICINEBADEFFECT,
           LEAD(referralreason) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_referralreason,
           LEAD(referralreason,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_referralreason,
           LEAD(agencyanddept) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_agencyanddept,
           LEAD(agencyanddept,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_agencyanddept,
           LEAD(visitway) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitway,
           visitway,VISITEFFECT
    FROM mdc_hypertensionvisit 
    WHERE to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-10-01'' 
      AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-12-31''
)
WHERE next_next_visitdate IS NOT NULL 
  AND next_next_VISITEVALUATE = 1 
  AND next_VISITEVALUATE != 1 AND VISITEVALUATE != 1 
  AND next_visitdate - visitdate <= 14 
  AND next_next_visitdate - next_visitdate <= 14 
  AND (next_agencyanddept IS NOT NULL OR next_referralreason IS NOT NULL) 
  AND VISITEFFECT = 1 AND visitway IN (''1'',''2'')

-- 第四步:连续三次控制不满意+第二次转诊
UNION
SELECT distinct empiid
FROM (
    SELECT empiid, visitdate,
           LEAD(visitdate) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitdate,
           LEAD(visitdate,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_visitdate,
           VISITEVALUATE,
           LEAD(VISITEVALUATE) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_VISITEVALUATE,
           LEAD(VISITEVALUATE,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_VISITEVALUATE,
           MEDICINEBADEFFECT, 
           LEAD(MEDICINEBADEFFECT) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_MEDICINEBADEFFECT,
           LEAD(MEDICINEBADEFFECT,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_MEDICINEBADEFFECT,
           LEAD(referralreason) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_referralreason,
           LEAD(referralreason,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_referralreason,
           LEAD(agencyanddept) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_agencyanddept,
           LEAD(agencyanddept,2) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_next_agencyanddept,
           LEAD(visitway) OVER (PARTITION BY empiid ORDER BY visitdate) AS next_visitway,
           visitway,VISITEFFECT
    FROM mdc_hypertensionvisit 
    WHERE to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-10-01'' 
      AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-12-31''
)
WHERE next_next_visitdate IS NOT NULL 
  AND next_next_VISITEVALUATE != 1 
  AND next_VISITEVALUATE != 1 AND VISITEVALUATE != 1 
  AND next_visitdate - visitdate <= 14 
  AND next_next_visitdate - next_visitdate <= 14 
  AND (next_agencyanddept IS NOT NULL OR next_referralreason IS NOT NULL) 
  AND VISITEFFECT = 1 AND visitway IN (''1'',''2'')

-- 第五步:高危血压+转诊
UNION
SELECT distinct empiid
FROM mdc_hypertensionvisit
WHERE (constriction >= 180 OR diastolic >= 110)
  AND (referralreason IS NOT NULL OR agencyanddept IS NOT NULL)
  AND to_char(visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-10-01'' 
  AND to_char(visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-12-31''
  AND VISITEFFECT = 1
) cc

-- 第六步:校验随访内容完整性
WHERE EXISTS(
    SELECT empiid FROM (
        SELECT distinct z.empiid 
        FROM mdc_hypertensionvisit z
        LEFT JOIN face_log s ON z.empiid = s.empiid
        LEFT JOIN ehr_pasthistoryrecord t ON z.empiid = t.empiid
        LEFT JOIN mdc_hypertensionrecord r ON z.empiid = r.empiid
        WHERE z.visitdate IS NOT NULL
          AND z.constriction IS NOT NULL
          AND z.DIASTOLIC IS NOT NULL
          AND z.weight IS NOT NULL
          AND z.bmi IS NOT NULL
          AND z.smokecount IS NOT NULL
          AND z.drinkcount IS NOT NULL
          AND z.psychologychange IS NOT NULL
          AND z.obeydoctor IS NOT NULL
          AND z.medicine IS NOT NULL
          AND z.nextdate IS NOT NULL
          AND z.visitdoctor IS NOT NULL
          AND (z.traintimesweek + z.targettraintimesweek + z.trainminute + z.targettrainminute) IS NOT NULL
          AND z.VISITEFFECT = 1
          AND to_char(z.visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-10-01'' 
          AND to_char(z.visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-12-31''
          AND s.submitdate > z.visitDate - 19
          AND s.submitdate < z.visitdate + 19
          AND s.status = 1 AND s.facetype != 4
          AND t.confirmdate_gxy IS NOT NULL
          AND r.status = 0
          AND z.visitway IN (''1'',''2'')
        
        UNION
        
        SELECT distinct z.empiid 
        FROM mdc_hypertensionvisit z
        LEFT JOIN TCS_SERVICESCORERECORD s ON z.empiid = s.empiid
        LEFT JOIN ehr_pasthistoryrecord t ON z.empiid = t.empiid
        LEFT JOIN mdc_hypertensionrecord r ON z.empiid = r.empiid
        WHERE z.visitdate IS NOT NULL
          AND z.constriction IS NOT NULL
          AND z.DIASTOLIC IS NOT NULL
          AND z.weight IS NOT NULL
          AND z.bmi IS NOT NULL
          AND z.smokecount IS NOT NULL
          AND z.drinkcount IS NOT NULL
          AND z.psychologychange IS NOT NULL
          AND z.obeydoctor IS NOT NULL
          AND z.medicine IS NOT NULL
          AND z.nextdate IS NOT NULL
          AND z.visitdoctor IS NOT NULL
          AND (z.traintimesweek + z.targettraintimesweek + z.trainminute + z.targettrainminute) IS NOT NULL
          AND z.VISITEFFECT = 1
          AND to_char(z.visitdate,''yyyy-mm-dd'') >= ''' || v_year_char || '-10-01'' 
          AND to_char(z.visitdate,''yyyy-mm-dd'') < ''' || v_year_char || '-12-31''
          AND t.confirmdate_gxy IS NOT NULL
          AND r.status = 0
          AND z.visitway IN (''3'')
    ) dd 
    WHERE cc.empiid = dd.empiid
)
)
';

    EXECUTE IMMEDIATE v_sql;
    DBMS_OUTPUT.PUT_LINE('视图 SIJDGXY_CS_' || v_year_char || ' 创建成功');

    -- =========================================================================
    -- 8. 生成四季度整合视图:SIJDGXY_年份(依赖SANJDGXY_年份和SIJDGXY_CS_年份)
    -- =========================================================================
    v_sql := 'CREATE OR REPLACE VIEW SIJDGXY_' || v_year_char || ' AS
select distinct empiid from (
select distinct "EMPIID" from (
-- 三季度规范患者+四季度规范患者
SELECT b.empiid 
FROM SANJDGXY_' || v_year_char || ' a, SIJDGXY_CS_' || v_year_char || ' b 
WHERE a.empiid = b.empiid

UNION ALL

-- 四季度新增规范患者(首次随访在四季度)
SELECT empiid FROM SIJDGXY_CS_' || v_year_char || ' a 
WHERE EXISTS(
    SELECT 1 FROM (
        SELECT min(visitdate) AS zxrq, empiid
        FROM mdc_hypertensionvisit
        WHERE to_char(visitdate,''yyyy'') = ''' || v_year_char || ''' 
        GROUP BY empiid
    ) b 
    WHERE a.empiid = b.empiid
      AND to_char(b.zxrq,''yyyy-mm-dd'') >= ''' || v_year_char || '-10-01'' 
      AND to_char(b.zxrq,''yyyy-mm-dd'') < ''' || v_year_char || '-12-31''
)
) 
WHERE empiid IN (
    -- 校验健康体检完整性(体检项目非空)
    SELECT a.empiid 
    FROM HC_HEALTHCHECK a
    LEFT JOIN HC_ACCESSORYEXAMINATION b ON a.healthcheck = b.healthcheck
    LEFT JOIN HC_HEALTHASSESSMENT c ON a.healthcheck = c.healthcheck
    LEFT JOIN mdc_hypertensionrecord d ON a.empiid = d.empiid
    WHERE to_char(a.checkdate,''yyyy'') = ''' || v_year_char || '''
      AND a.checkdate >= d.createdate
      AND (b.lefteye IS NOT NULL OR b.righteye IS NOT NULL)
      AND b.reclefteye IS NOT NULL AND b.recrighteye IS NOT NULL
      AND c.abnormality IS NOT NULL
      AND c.mana IS NOT NULL
      AND a.otherdiseasesonedesc LIKE ''%高血%''

    UNION

    SELECT a.empiid 
    FROM HC_HEALTHCHECK a
    LEFT JOIN HC_ACCESSORYEXAMINATION b ON a.healthcheck = b.healthcheck
    LEFT JOIN HC_HEALTHASSESSMENT c ON a.healthcheck = c.healthcheck
    LEFT JOIN mdc_hypertensionrecord d ON a.empiid = d.empiid
    WHERE to_char(a.checkdate,''yyyy'') = ''' || v_year_char || '''
      AND a.checkdate < d.createdate
      AND (b.lefteye IS NOT NULL OR b.righteye IS NOT NULL)
      AND b.reclefteye IS NOT NULL AND b.recrighteye IS NOT NULL
      AND c.abnormality IS NOT NULL
      AND c.mana IS NOT NULL
)
AND empiid IN (
    -- 三季度与四季度随访间隔62-118天
    SELECT b.empiid
    FROM (
        SELECT min(visitdate) AS yjdzxrq, empiid
        FROM mdc_hypertensionvisit
        WHERE to_char(visitdate,''yyyy-mm'') IN (''' || v_year_char || '-07'',''' || v_year_char || '-08'',''' || v_year_char || '-09'')
        GROUP BY empiid
    ) a
    RIGHT JOIN (
        SELECT min(visitdate) AS ejdzxrq, empiid
        FROM mdc_hypertensionvisit
        WHERE to_char(visitdate,''yyyy-mm'') IN (''' || v_year_char || '-10'',''' || v_year_char || '-11'',''' || v_year_char || '-12'')
        GROUP BY empiid
    ) b ON a.empiid = b.empiid
    WHERE b.ejdzxrq - a.yjdzxrq BETWEEN 62 AND 118

    UNION

    -- 三季度无随访,四季度新增患者
    SELECT b.empiid
    FROM (
        SELECT min(visitdate) AS yjdzxrq, empiid
        FROM mdc_hypertensionvisit
        WHERE to_char(visitdate,''yyyy-mm'') IN (''' || v_year_char || '-07'',''' || v_year_char || '-08'',''' || v_year_char || '-09'')
        GROUP BY empiid
    ) a
    RIGHT JOIN (
        SELECT min(visitdate) AS ejdzxrq, empiid
        FROM mdc_hypertensionvisit
        WHERE to_char(visitdate,''yyyy-mm'') IN (''' || v_year_char || '-10'',''' || v_year_char || '-11'',''' || v_year_char || '-12'')
        GROUP BY empiid
    ) b ON a.empiid = b.empiid
    WHERE a.empiid IS NULL

    UNION

    -- 随访计划中三季度与四季度间隔62-118天
    SELECT a.empiid
    FROM (
        SELECT visitdate AS ejdzxrq, empiid
        FROM pub_visitplan 
        WHERE visitid IS NOT NULL
          AND to_char(visitdate,''yyyy-mm'') IN (''' || v_year_char || '-10'',''' || v_year_char || '-11'',''' || v_year_char || '-12'')
          AND visitmeddle = ''0'' AND businesstype = ''1''
    ) a, (
        SELECT visitdate AS yjdzxrq, empiid
        FROM pub_visitplan 
        WHERE visitid IS NOT NULL
          AND to_char(visitdate,''yyyy-mm'') IN (''' || v_year_char || '-07'',''' || v_year_char || '-08'',''' || v_year_char || '-09'')
          AND visitmeddle = ''0'' AND businesstype = ''1''
    ) b
    WHERE a.empiid = b.empiid
      AND a.ejdzxrq - b.yjdzxrq BETWEEN 62 AND 118
))
';

    EXECUTE IMMEDIATE v_sql;
    DBMS_OUTPUT.PUT_LINE('视图 SIJDGXY_' || v_year_char || ' 创建成功');

    -- =========================================================================
    -- 9. 执行完成提示
    -- =========================================================================
    DBMS_OUTPUT.PUT_LINE('=============================');
    DBMS_OUTPUT.PUT_LINE(v_year_char || '年高血压随访规范视图生成完成!');
    DBMS_OUTPUT.PUT_LINE('共生成7个视图:');
    DBMS_OUTPUT.PUT_LINE('1. YJDGXY_' || v_year_char || '(一季度基础视图)');
    DBMS_OUTPUT.PUT_LINE('2. EJDGX_' || v_year_char || '(二季度基础视图)');
    DBMS_OUTPUT.PUT_LINE('3. EJDGXY_' || v_year_char || '(二季度整合视图)');
    DBMS_OUTPUT.PUT_LINE('4. SJDGXY_CS_' || v_year_char || '(三季度基础视图)');
    DBMS_OUTPUT.PUT_LINE('5. SANJDGXY_' || v_year_char || '(三季度整合视图)');
    DBMS_OUTPUT.PUT_LINE('6. SIJDGXY_CS_' || v_year_char || '(四季度基础视图)');
    DBMS_OUTPUT.PUT_LINE('7. SIJDGXY_' || v_year_char || '(四季度整合视图)');
    DBMS_OUTPUT.PUT_LINE('=============================');

EXCEPTION
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('错误信息:' || SQLERRM);
        DBMS_OUTPUT.PUT_LINE('错误行号:' || SQLCODE);
        RAISE;  -- 抛出异常,便于调试
END CREATE_HYPERTENSION_VIEWS;
/

总结记录下问题:

为了判断哪里出了问题,我把其中一段sql拿出来执行;

sql 复制代码
-- 创建会话级临时表(仅当前会话可见,会话结束后数据自动清空)
CREATE GLOBAL TEMPORARY TABLE TMP_DYNAMIC_SQL (
    SQL_CONTENT CLOB,        -- 存储完整动态SQL
    CREATE_TIME DATE DEFAULT SYSDATE  -- 生成时间
) ON COMMIT PRESERVE ROWS;  -- 提交后保留数据(确保调用后能查询到)
/

-- 嵌入执行后 SQL_CONTENT 为有执行的sql
SELECT SQL_CONTENT FROM TMP_DYNAMIC_SQL;


    --:执行动态SQL(创建视图)
    
     -- ================= 新增:将动态SQL写入临时表 =================
    DELETE FROM TMP_DYNAMIC_SQL;  -- 清空历史数据(可选)
    INSERT INTO TMP_DYNAMIC_SQL (SQL_CONTENT) VALUES (v_sql);
    COMMIT;  -- 提交插入(确保后续能查询到)
    -- ============================================================

    EXECUTE IMMEDIATE v_sql;
    
    DBMS_OUTPUT.PUT_LINE('视图 YJDGXY_' || v_year_char || ' 创建成功');
    
    

-- 步骤4:异常处理(捕获错误并输出详情)
EXCEPTION
    WHEN OTHERS THEN
        -- 错误时也写入SQL(便于排查)
        DELETE FROM TMP_DYNAMIC_SQL;
        INSERT INTO TMP_DYNAMIC_SQL (SQL_CONTENT) VALUES (v_sql);
        COMMIT;  
    
        DBMS_OUTPUT.PUT_LINE('==================== 错误信息 ====================');
        DBMS_OUTPUT.PUT_LINE('错误代码: ' || SQLCODE);
        DBMS_OUTPUT.PUT_LINE('错误描述: ' || SQLERRM);
        DBMS_OUTPUT.PUT_LINE('执行的SQL(前2000字符): ' || SUBSTR(v_sql, 1, 2000));  -- 输出部分SQL便于排查
        RAISE;  -- 重新抛出错误(可选,根据需求决定是否中断)
END CREATE_HYPERTENSION_VIEWS;
/  -- 结束符必须单独一行!!!

EXECUTE IMMEDIATE 是 Oracle PL/SQL 中用于 动态执行动态 SQL 语句或匿名 PL/SQL 块的关键字。它允许在运行时动态构造 SQL 语句(字符串形式)并立即执行,适用于需要动态生成 SQL 的场景(如根据参数拼接表名、视图名或条件)。

核心作用

  • 执行动态生成的 SQL 语句 (如 CREATE VIEWSELECTINSERT 等),这些语句在编译时无法确定,需根据运行时参数拼接。
  • 执行匿名 PL/SQL 块(动态构造的 PL/SQL 代码片段)。

基本语法

plsql

复制代码
EXECUTE IMMEDIATE 动态SQL字符串
  [ INTO 变量列表 ]  -- 用于接收SELECT查询的结果(单行)
  [ USING 绑定变量列表 ]  -- 传递参数给动态SQL(避免SQL注入,推荐)
  [ RETURN INTO 变量 ]  -- 用于接收动态PL/SQL块的返回值

关键特性与使用场景

1. 动态执行 DDL 语句(如创建视图、表)

当需要根据参数动态生成 DDL(数据定义语言)时,必须使用 EXECUTE IMMEDIATE。例如你之前的存储过程中,根据年份参数 p_year 动态创建视图:

复制代码
v_sql := 'CREATE OR REPLACE VIEW YJDGXY_' || v_year_char || ' AS SELECT ...';
EXECUTE IMMEDIATE v_sql;  -- 执行动态生成的创建视图语句
2. 动态执行 DML 或查询语句(如 SELECT、INSERT)

对于需要动态条件或表名的 DML(数据操纵语言),EXECUTE IMMEDIATE 同样适用。例如根据参数查询不同表:

复制代码
v_table_name := 'EMP_' || v_year;  -- 动态表名:如EMP_2024
v_sql := 'SELECT COUNT(*) FROM ' || v_table_name || ' WHERE deptno = :dept';

-- 执行动态查询,用USING传递参数:dept,用INTO接收结果
EXECUTE IMMEDIATE v_sql INTO v_count USING 30;
  • :dept 是绑定变量,通过 USING 30 传递值,避免直接拼接字符串导致 SQL 注入风险。
  • INTO v_count 用于接收查询结果(仅适用于单行查询)。
3. 执行匿名 PL/SQL 块

可动态构造 PL/SQL 代码块并执行,例如动态调用函数:

复制代码
v_sql := 'BEGIN :result := MY_FUNC(:param); END;';  -- 动态PL/SQL块
EXECUTE IMMEDIATE v_sql USING OUT v_result, IN v_param;  -- 传递输入/输出参数
  • :result 是输出变量,用 OUT 关键字标识;:param 是输入变量,用 IN 标识(默认可省略)。

注意事项

  1. SQL 注入风险

    避免直接拼接用户输入或参数到动态 SQL 中(如 v_sql := 'SELECT * FROM emp WHERE name = ''' || user_input || ''''),可能导致 SQL 注入。应使用绑定变量:变量名 + USING 传递参数)。

  2. 换行符(CR/LF)敏感: (使用notepad++ 右键改成LF)

    动态 SQL 字符串中的换行符(CHR(10)/CHR(13))可能影响解析,尤其是混合 CRCHR(13))时,可能导致 ORA-00933 等错误。需确保动态 SQL 中仅使用 Oracle 兼容的换行符(CHR(10)),可通过 REPLACE(v_sql, CHR(13), '') 清除 CR

  3. 多行语句与分号

    动态 SQL 中若包含多行语句,需确保语法正确(如 CREATE VIEW 语句末尾无需分号,而匿名 PL/SQL 块需用分号结束)。

  4. 异常处理

    动态 SQL 的错误(如语法错、表不存在)会在执行时抛出,需用 EXCEPTION 块捕获(如 WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(SQLERRM))。

总结

EXECUTE IMMEDIATE 是 PL/SQL 中处理动态 SQL 的核心工具,尤其适用于需要根据运行时参数动态生成 SQL 的场景(如你之前根据年份创建视图)。使用时需注意绑定变量的正确使用、换行符的兼容性及异常处理,以避免语法错误和安全风险。

EXECUTE IMMEDIATE 执行的动态 SQL 中,分号的使用是否有影响,取决于执行的语句类型 (是 SQL 语句还是 PL/SQL 块),错误使用分号是导致 ORA-00933: SQL 命令未正确结束 的常见原因之一。

一、分号的影响:分场景说明

1. 执行单行 SQL 语句(如 CREATE VIEWSELECTINSERT 等)

禁止在动态 SQL 末尾加分号 ,否则会触发 ORA-00933 错误。

  • 原因:Oracle 解析单行 SQL 时,分号会被视为 "多余的结束符",导致语法错误。

  • 错误示例(动态创建视图): plsql

    复制代码
    -- 错误:动态SQL末尾多了分号
    v_sql := 'CREATE OR REPLACE VIEW YJDGXY_2024 AS SELECT empiid FROM mdc_hypertensionvisit;';
    EXECUTE IMMEDIATE v_sql;  -- 执行报错:ORA-00933
  • 正确示例:

    复制代码
    -- 正确:动态SQL末尾无分号
    v_sql := 'CREATE OR REPLACE VIEW YJDGXY_2024 AS SELECT empiid FROM mdc_hypertensionvisit';
    EXECUTE IMMEDIATE v_sql;  -- 执行成功
2. 执行多行 SQL 语句(如 UNION ALL 拼接的查询)

同样禁止在整个动态 SQL 末尾加分号 ,但语句内部的子句(如 WHEREFROM)中不能加分号。

  • 错误示例(多行查询):

    复制代码
    -- 错误:整个SQL末尾多了分号
    v_sql := 'SELECT empiid FROM t1 UNION ALL SELECT empiid FROM t2;';
    EXECUTE IMMEDIATE v_sql;  -- 报错:ORA-00933
  • 正确示例: plsql

    复制代码
    -- 正确:无末尾分号
    v_sql := 'SELECT empiid FROM t1 UNION ALL SELECT empiid FROM t2';
    EXECUTE IMMEDIATE v_sql;  -- 执行成功
3. 执行匿名 PL/SQL 块(BEGIN...END

必须在 END 后加分号 ,否则会触发 ORA-06550 错误。

  • 原因:PL/SQL 块的语法要求用 END; 标识结束,分号是必需的。

  • 错误示例(动态执行 PL/SQL 块): plsql

    复制代码
    -- 错误:END后缺少分号
    v_sql := 'BEGIN DBMS_OUTPUT.PUT_LINE(''Hello''); END';
    EXECUTE IMMEDIATE v_sql;  -- 报错:ORA-06550
  • 正确示例: plsql

    复制代码
    -- 正确:END后有分号
    v_sql := 'BEGIN DBMS_OUTPUT.PUT_LINE(''Hello''); END;';
    EXECUTE IMMEDIATE v_sql;  -- 执行成功

二、关键结论:分号使用准则

动态 SQL 类型 是否需要分号? 示例正确写法
单行 SQL(DDL/DML) 禁止在末尾加分号 CREATE VIEW ... AS SELECT ...
多行 SQL(如 UNION) 禁止在整个语句末尾加分号 SELECT ... UNION ALL SELECT ...
匿名 PL/SQL 块 必须在 END 后加分号 BEGIN ...; END;

三、为什么 "单独提取 SQL 执行时,带分号可能成功"?

在 SQL*Plus 或 IDE 的 SQL 窗口中,分号通常被用作 "语句分隔符"(告诉工具 "这是一条完整的 SQL"),而非 SQL 语句本身的一部分。例如:

  • 在 SQL 窗口中执行 CREATE VIEW ...; 时,工具会自动忽略末尾的分号,仅将 CREATE VIEW ... 发送给 Oracle 执行,因此不会报错。
  • 但在 EXECUTE IMMEDIATE 中,分号会被视为 SQL 语句的一部分,直接传递给 Oracle 解析,导致报错。

这也是 "动态 SQL 在存储过程中报错,单独提取后带分号执行却成功" 的常见原因之一。

总结

分号对 EXECUTE IMMEDIATE 的影响取决于执行的语句类型:

  • SQL 语句 :动态 SQL 中绝对不能带末尾分号 ,否则触发 ORA-00933
  • PL/SQL 块 :必须在 END 后带分号,否则触发 ORA-06550

在你的存储过程(动态创建视图)场景中,需确保拼接的 v_sql 末尾没有分号 ,这是修复 ORA-00933 错误的关键之一。

相关推荐
wyn200011282 小时前
KafKa学习笔记
笔记·学习·kafka
F_D_Z9 小时前
人工智能基础概念
笔记
liweiweili12610 小时前
基于金庸武侠小说人物关系设计的完整 SQL 语句,包括数据库创建、表结构定义和示例数据插入
数据库·sql·oracle
星梦清河13 小时前
宋红康 JVM 笔记 Day08|堆
jvm·笔记
我希望的一路生花13 小时前
Boris FX Samplitude Suite 2025.0.0 音频录制/编辑和母带处理
大数据·3d·oracle·sqlite·音视频·数据库开发
岩中竹16 小时前
广东省省考备考(第八十九天8.28)——判断推理(听课后强化训练)
笔记
AllyLi022416 小时前
CondaError: Run ‘conda init‘ before ‘conda activate‘
linux·开发语言·笔记·python
我不是星海19 小时前
Redis实战-优惠券秒杀解决方案总结大全
java·数据库·oracle
HPC_fac1305206781619 小时前
英伟达发布高效小模型Jet-Nemotron:基于PostNAS与JetBlock架构,准确率与吞吐量双突破
人工智能·笔记·深度学习·架构·数据挖掘·语音识别·gpu算力