我正在尝试做一个像下面这样的游标,在不同的方法中挣扎而没有结果。似乎,我自己无法做到,并决定向你寻求帮助。 下面的代码显示了我想要实现的目标,而不是现成的方法。请帮忙。
我不知道这很重要但请注意,我需要在循环中更新CUSTOMERS。我还需要在此循环中从引用客户的另一个表中选择一些数据,然后将内容插入第三个表并更新客户表。
DECLARE
CURSOR MY_CURSOR
IS
SELECT CUSTOMERID FROM CUSTOMERS WHERE ACTIVE = 1 ;
MY_RECORD MY_CURSOR%ROWTYPE;
BEGIN
FOR MY_RECORD IN MY_CURSOR
LOOP
DECLARE TEMPORARY_TABLE TABLE (A DATE, B NUMBER, C VARCHAR)
INSERT INTO @TEMPORARY_TABLE(A,B,C) (SELECT CREATEDDATE, ID, NAME FROM ACCOUNT WHERE CUSTOMER = MY_RECORD.CUSTOMERID)
INSERT INTO SOME_EVENT_TABLE(ID, NAME, DATE, ACCOUNT_ID) VALUE (some_seq.NEXTVAL, @TEMPORARY_TABLE[C], @TEMPORARY_TABLE[A], @TEMPORARY_TABLE[B])
UPDATE CUSTOMERS SET LAST_ACCOUNT_CHECK_NAME=@TEMPORARY_TABLE(C), LAST_INSERTED_EVENT_ID = some_seq.CURRVAL WHERE ID = MY_RECORD.CUSTOMERID
END LOOP;
COMMIT;
END;
答案 0 :(得分:1)
首先,您不能像在SQL Server中那样在Oracle中声明临时表。但是,无论如何,你真的不需要它。
这样的事情应该有效:
FOR MY_RECORD IN MY_CURSOR LOOP
FOR R IN (SELECT CREATEDDATE, ID, NAME
FROM ACCOUNT WHERE CUSTOMER = MY_RECORD.CUSTOMERID) LOOP
INSERT INTO some_event_table(ID, NAME, DATE, ACCOUNT_ID)
VALUES (some_seq.NEXTVAL, R.NAME, R.CREATEDATE, R.ID);
UPDATE customers
SET last_account_check_name = R.name
, last_inserted_event_id = some_seq.CURRVAL
WHERE id = MY_RECORD.CUSTOMER_ID;
END LOOP;
END LOOP;
COMMIT;
答案 1 :(得分:0)
SQL中的逐行操作非常低效。如果以基于集合的方式执行此操作,您将获得更好的性能。
INSERT INTO some_event_table(ID, NAME, DATE, ACCOUNT_ID)
SELECT some_seq.NEXTVAL, a.name, a.createdate, a.id
FROM ACCOUNT a
INNER JOIN customers c ON c.customerid = a.customerid
WHERE c.active = 1;
UPDATE customers
SET last_account_check_name =
( SELECT a.name FROM account a WHERE a.customerid = c.customerid ),
last_inserted_event_id = some_seq.CURRVAL
WHERE c.active = 1;
可能存在并发性问题(如果在两个语句之间更新客户会发生什么?),但这可能足以满足您的需求。