我有一个光标返回要在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输出。
答案 0 :(得分:4)
您的代码无效的原因是:
OPEN c1;
LOOP
EXIT WHEN c1%NOTFOUND;
EXIT WHEN (c1%ROWCOUNT <> p_SCBCount);
在执行提取之前,您正在测试c1%ROWCOUNT
。所以它的值是0;我猜测p_SCBCount
在那时不是零(因为你在DECLARE块中将它初始化为某个值),因此测试评估为true并且程序退出。
或者问题是:
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
(只是一个疯狂的猜测)。
但是,如果它确实用于实现某些真正的业务逻辑,您可以以某种方式将其添加到循环中。
答案 1 :(得分: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 = ' ||
答案 2 :(得分: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;
。我不认为这是你打算更新行数的意图。