Когда курсор SQL загружает данные?
У меня есть следующий скрипт для обновления локальной таблицы, читая таблицу удаленного источника. Скрипт работает без ошибок. Этот пост должен уточнить, как работает курсор.
Я читаю данные из таблицы удаленного источника Source_Product
и изначально вставьте во временную таблицу VW_PRODUCT
, После этого я вставляю или обновляю PRODUCT
Таблица.
Мои вопросы
1) Когда product_cursor
загрузить данные? Это когда мы пытаемся прочитать курсор в цикле for? или когда когда-нибудь объявить курсор он загружает данные?
2) Этот скрипт запускается ежедневно. Если product_cursor
работает, как только он объявит, то VW_PRODUCT
имеет данные за предыдущий день. Потому что данные за сегодня не вставлены в VW_PRODUCT
таблица (запрос вставки доступен после объявления курсора). Итак product_cursor
не будет иметь никакой записи после minus
, Так как ysterday_data
minus
ysterday_data
это ноль. Так как же он может обновить или вставить последние данные в PRODUCT
в соответствии с приведенным ниже сценарием?
SET serveroutput ON SIZE 1000000;
DECLARE
CURSOR product_cursor
IS
SELECT V.PRODUCTID,
V.PACKAGEID'
V.ENDDATE
FROM VW_PRODUCT V
MINUS
SELECT E.PRODUCTID,
E.PACKAGEID,
E.ENDDATE
FROM PRODUCT E;
/*The delete data*/
CURSOR product_cursor_del
IS
SELECT E.PRODUCTID FROM PRODUCT E WHERE (E.ENDDATE > SYSDATE OR E.ENDDATE IS NULL)
MINUS
SELECT V.PRODUCTID FROM VW_PRODUCT V;
/* Variable Declaration*/
v_total NUMBER (10);
v_inserted NUMBER (10);
v_updated NUMBER (10);
v_deleted NUMBER (10);
v_rows_inserted NUMBER (10);
v_productid PRODUCT.PRODUCTID%TYPE;
v_count NUMBER (10);
v_commit_point NUMBER := 25;
BEGIN
v_total := 0;
v_count := 0;
v_inserted := 0;
v_updated := 0;
v_deleted := 0;
v_rows_inserted := 0;
EXECUTE IMMEDIATE 'TRUNCATE TABLE VW_PRODUCT';
INSERT INTO VW_PRODUCT
SELECT * FROM Source_Product;
SELECT COUNT (*)
INTO v_rows_inserted
FROM VW_PRODUCT;
COMMIT;
/*delete data*/
FOR product_rec IN product_cursor_del
LOOP
BEGIN
v_total := v_total + 1;
update product set enddate = sysdate
WHERE productid = product_rec.productid and enddate is null;
v_deleted := v_deleted + 1;
v_count := v_count + 1;
IF (v_count >= v_commit_point)
THEN
COMMIT;
v_count := 0;
END IF;
EXCEPTION
WHEN OTHERS
THEN
BEGIN
DBMS_OUTPUT.put_line ( 'Exception with product: ' );
END;
END;
END LOOP;
FOR product_rec IN product_cursor
LOOP
BEGIN
v_total := v_total + 1;
SELECT productid
INTO v_productid
FROM product
WHERE productid = product_rec.productid;
update PRODUCT
set PACKAGEID = product_rec.PACKAGEID,
ENDDATE = product_rec.ENDDATE
WHERE PRODUCTID = product_rec.PRODUCTID;
v_updated := v_updated + 1;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
INSERT INTO PRODUCT
(PRODUCTID,PACKAGEID,ENDDATE)
VALUES
(product_rec.PRODUCTID,
product_rec.PACKAGEID,
product_rec.ENDDATE);
v_inserted := v_inserted + 1;
v_count := v_count + 1;
IF (v_count >= v_commit_point)
THEN
COMMIT;
v_count := 0;
END IF;
WHEN OTHERS
THEN
raise_application_error ('Error );
END;
END LOOP;
IF (v_total >= 1)
THEN
COMMIT;
END IF;
END;
/
1 ответ
В двух словах, чтобы ответить на ваши основные вопросы,
- Курсор не хранит какой-либо набор результатов, это указатель, используемый для извлечения строк из набора результатов.
- Память не используется на этапе объявления.
- Это оператор FETCH, когда вы фактически используете курсор. Оператор FETCH извлекает строки из результирующего набора и помещает их в область в памяти. Вы можете выбрать строки по одному, несколько за раз или все сразу.
Оператор FETCH выполняет следующие операции:
- Считывает данные для текущей строки в наборе результатов в выходные переменные PL/SQL.
- Перемещает указатель на следующую строку в наборе результатов.
Посмотрите на работу с курсорами.