-1

我有一个光标来返回要使用的记录EXECUTE IMMEDIATE

 CURSOR c1
 IS
 SELECT crs_cust.CUSTOMER_ID AS CUSTOMER_ID, subset.NEW_CUSTOMER_REFERENCE_ID AS 
 CUSTOMER_REF_ID FROM CRS_CUSTOMERS crs_cust INNER JOIN 
 DAY0_SUBSET subset ON 
 crs_cust.CUSTOMER_ID=subset.CURRENT_CUSTOMER_ID;

EXECUTE IMMEDIATE以下块中的查询未执行。

OPEN c1;
 LOOP
  EXIT WHEN c1%NOTFOUND;
  EXIT WHEN (c1%ROWCOUNT <> p_SCBCount);
   FOR i in c1 LOOP
     EXECUTE IMMEDIATE 'UPDATE CRS_CUSTOMERS SET REF_ID = ' || i.CUSTOMER_REF_ID ||'WHERE CUSTOMER_ID = ' || i.CUSTOMER_ID; 
     p_TotalUpdatedCRS := p_TotalUpdatedCRS + 1;

     EXECUTE IMMEDIATE 'UPDATE CRS_REVIEWS SET 
     REF_ID = ' || i.CUSTOMER_REF_ID || 'WHERE CUSTOMER_ID = ' || i.CUSTOMER_ID; 
     EXECUTE IMMEDIATE 'UPDATE CRS_EVENT SET REF_ID = ' || i.CUSTOMER_REF_ID || 'WHERE UNIQUE_ID = ' || i.CUSTOMER_ID;
     EXECUTE IMMEDIATE 'UPDATE ALERT_HEADER SET CUSTOMER_SOURCE_REF_ID = ' || i.CUSTOMER_REF_ID || 'WHERE CUSTOMER_ID = ' || i.CUSTOMER_ID; 
 END LOOP;
    DBMS_OUTPUT.PUT_LINE ('The total updates to CRS table = ' || p_TotalUpdatedCRS); 
END LOOP;      
 CLOSE c1; 

当我使用 SQL 开发人员执行程序时,也不会打印出 DBMS 输出。

4

3 回答 3

4

你的代码什么都不做的原因是这样的:

OPEN c1;
 LOOP
  EXIT WHEN c1%NOTFOUND;   
  EXIT WHEN (c1%ROWCOUNT <> p_SCBCount);

c1%ROWCOUNT您在执行 fetch 之前进行测试。所以它的值为0;我猜p_SCBCount当时不为零(因为您将其初始化为 DECLARE 块中的某个值),以便测试评估为真并且程序退出。

或者,问题是这样的:

OPEN c1;
 LOOP
   ...
   FOR i in c1 LOOP

我们不能将FOR ... IN与显式游标一起使用。您已打开光标。然后FOR试图再次打开它投掷ORA-06511: PL/SQL: cursor already open。如果你没有看到这个错误,你必须有一个异常处理程序来抑制它(例如WHEN others then null;)。

基本上外部循环是完全没有必要的,你应该丢弃它。

很少需要显式循环控制:只需使用FOR ... IN构造并让 Oracle 控制流程。

同样不必要的是所有的动态SQL。SQL 使用变量,因此您只需要编写引用游标属性的静态 SQL:

 FOR i in (SELECT crs_cust.CUSTOMER_ID AS CUSTOMER_ID
                 , subset.NEW_CUSTOMER_REFERENCE_ID AS CUSTOMER_REF_ID 
           FROM CRS_CUSTOMERS crs_cust 
           INNER JOIN  DAY0_SUBSET subset
           ON crs_cust.CUSTOMER_ID=subset.CURRENT_CUSTOMER_ID )
 LOOP
     UPDATE CRS_CUSTOMERS 
     SET REF_ID = i.CUSTOMER_REF_ID
     WHERE CUSTOMER_ID = i.CUSTOMER_ID; 
     p_TotalUpdatedCRS := p_TotalUpdatedCRS + 1;

     UPDATE CRS_REVIEWS
     SET REF_ID =  i.CUSTOMER_REF_ID
     WHERE CUSTOMER_ID =  i.CUSTOMER_ID; 

     UPDATE CRS_EVENT 
     SET REF_ID = i.CUSTOMER_REF_ID 
     WHERE UNIQUE_ID = i.CUSTOMER_ID;

     UPDATE ALERT_HEADER 
     SET CUSTOMER_SOURCE_REF_ID = i.CUSTOMER_REF_ID 
     WHERE CUSTOMER_ID = i.CUSTOMER_ID; 
END LOOP;
DBMS_OUTPUT.PUT_LINE ('The total updates to CRS table = ' || p_TotalUpdatedCRS); 

我不确定c1%ROWCOUNT <> p_SCBCount. 我的预感是它是多余的,因为FOR LOOP控制精确地获取。事实上,我怀疑你添加它是为了避免嵌套循环的副作用;我怀疑你只介绍了嵌套循环,因为你是原始代码PLS-00376: illegal EXIT/CONTINUE statement; it must appear inside a loop(只是一个疯狂的猜测)。

但是,如果它确实用于实现一些真正的业务逻辑,您可以以某种方式将其添加到循环中。

于 2018-04-17T06:46:24.003 回答
1

您的代码中没有任何动态;为什么要打扰它?

这是一个应该可以工作的代码(除非我打错了,因为我没有你的表格):

DECLARE
   l_cnt   NUMBER := 0;
BEGIN
   FOR cur_r
      IN (SELECT crs_cust.customer_id,
                 subset.new_customer_reference_id AS customer_ref_id
            FROM crs_customers crs_cust
                 INNER JOIN day0_subset subset
                    ON crs_cust.customer_id = subset.current_customer_id)
   LOOP
      UPDATE crs_customers
         SET ref_id = cur_r.customer_ref_id
       WHERE customer_id = cur_r.customer_id;

      l_cnt := l_cnt + SQL%ROWCOUNT;

      UPDATE crs_reviews
         SET ref_id = cur_r.customer_ref_id
       WHERE customer_id = cur_r.customer_id;

      UPDATE crs_event
         SET ref_id = cur_r.customer_ref_id
       WHERE unique_id = cur_r.customer_id;

      UPDATE alert_header
         SET customer_source_ref_id = cur_r.customer_ref_id
       WHERE customer_id = cur_r.customer_id;
   END LOOP;

   DBMS_OUTPUT.put_line ('The total updates to CRS table = ' || l_cnt);
END;

至于您当前的问题:WHEN OTHERS您的代码中是否有异常处理程序(您没有发布它)?如果是这样,请将其删除

此外,这是错误的(只是一个例子;到处都有):

SET REF_ID = ' || i.CUSTOMER_REF_ID || 'WHERE UNIQUE_ID = ' || 
                                        ^
                                        a space missing here; should be

                                    ||' WHERE UNIQUE_ID = ' ||
于 2018-04-17T06:38:35.643 回答
0

我认为你根本不需要任何循环。这段代码应该做同样的事情:

UPDATE CRS_CUSTOMERS 
SET REF_ID = 
    (SELECT subset.NEW_CUSTOMER_REFERENCE_ID
    FROM CRS_CUSTOMERS crs_cust 
        INNER JOIN DAY0_SUBSET subset ON crs_cust.CUSTOMER_ID = subset.CURRENT_CUSTOMER_ID
    WHERE CUSTOMER_ID = crs_cust.CUSTOMER_ID)
WHERE CUSTOMER_ID =ANY 
    (SELECT crs_cust.CUSTOMER_ID
    FROM CRS_CUSTOMERS crs_cust 
        INNER JOIN DAY0_SUBSET subset ON crs_cust.CUSTOMER_ID = subset.CURRENT_CUSTOMER_ID);    

p_TotalUpdatedCRS := SQL%ROWCOUNT;


UPDATE CRS_REVIEWS 
SET REF_ID = 
    (SELECT subset.NEW_CUSTOMER_REFERENCE_ID
    FROM CRS_CUSTOMERS crs_cust 
        INNER JOIN DAY0_SUBSET subset ON crs_cust.CUSTOMER_ID = subset.CURRENT_CUSTOMER_ID
    WHERE CUSTOMER_ID = crs_cust.CUSTOMER_ID)
WHERE CUSTOMER_ID =ANY 
    (SELECT crs_cust.CUSTOMER_ID
    FROM CRS_CUSTOMERS crs_cust 
        INNER JOIN DAY0_SUBSET subset ON crs_cust.CUSTOMER_ID = subset.CURRENT_CUSTOMER_ID);    

UPDATE CRS_EVENT
SET REF_ID = 
    (SELECT subset.NEW_CUSTOMER_REFERENCE_ID
    FROM CRS_CUSTOMERS crs_cust 
        INNER JOIN DAY0_SUBSET subset ON crs_cust.CUSTOMER_ID = subset.CURRENT_CUSTOMER_ID
    WHERE CUSTOMER_ID = crs_cust.CUSTOMER_ID)
WHERE CUSTOMER_ID =ANY 
    (SELECT crs_cust.CUSTOMER_ID
    FROM CRS_CUSTOMERS crs_cust 
        INNER JOIN DAY0_SUBSET subset ON crs_cust.CUSTOMER_ID = subset.CURRENT_CUSTOMER_ID);    

UPDATE ALERT_HEADER 
SET CUSTOMER_SOURCE_REF_ID = 
    (SELECT subset.NEW_CUSTOMER_REFERENCE_ID
    FROM CRS_CUSTOMERS crs_cust 
        INNER JOIN DAY0_SUBSET subset ON crs_cust.CUSTOMER_ID = subset.CURRENT_CUSTOMER_ID
    WHERE CUSTOMER_ID = crs_cust.CUSTOMER_ID)
WHERE CUSTOMER_ID =ANY 
    (SELECT crs_cust.CUSTOMER_ID
    FROM CRS_CUSTOMERS crs_cust 
        INNER JOIN DAY0_SUBSET subset ON crs_cust.CUSTOMER_ID = subset.CURRENT_CUSTOMER_ID);    

DBMS_OUTPUT.PUT_LINE ('The total updates to CRS table = ' || p_TotalUpdatedCRS); 

请注意,p_TotalUpdatedCRS := p_TotalUpdatedCRS + 1;无论是否有更新(一行或多行),您都会运行。我不认为这是您的意图,因为您喜欢打印更新的行数。

于 2018-04-17T09:33:21.803 回答