Вы можете выполнять операции DML внутри функции Oracle PL / SQL и, , хотя обычно это не очень хорошая практика, вызывать ее из SQL . Функция должна быть помечена прагмой AUTONOMOUS_TRANSACTION
, а транзакция должна быть зафиксирована или откатана до выхода из функции (см. AUTONOMOUS_TRANSACTION Pragma ).
Вы должны знать, что такого рода функции, вызываемые из SQL, могут резко ухудшить производительность ваших запросов . Я рекомендую использовать его только для целей аудита .
Вот пример скрипта, начинающегося с вашей функции:
CREATE TABLE TBL_PERSON (NAME_UPPER VARCHAR2(30));
CREATE TABLE TMP_PERSON (NAME VARCHAR2(30));
INSERT INTO TBL_PERSON (NAME_UPPER) VALUES ('KING');
CREATE OR REPLACE FUNCTION TEST_FUNC(U_ID IN VARCHAR2)
RETURN VARCHAR2
IS
PRAGMA AUTONOMOUS_TRANSACTION; -- Needed to be called from SQL
V_MESSAGE VARCHAR2(2000);
CURSOR C_PERSON (V_ID VARCHAR2) IS
SELECT NAME_UPPER
FROM TBL_PERSON
WHERE NAME_UPPER = V_ID;
BEGIN
FOR C_PERSON_CURSOR IN C_PERSON(U_ID)
LOOP
INSERT INTO TMP_PERSON(NAME) VALUES (C_PERSON_CURSOR.NAME_UPPER);
V_MESSAGE := SQL%ROWCOUNT
|| ' Person record successfully inserted into TMP_PERSON table';
END LOOP;
COMMIT; -- The current autonomous transaction need to be commited
-- before exiting the function.
RETURN V_MESSAGE;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
END;
/
PROMPT Call the TEST_FUNC function and insert a new record into TMP_PERSON table
SELECT TEST_FUNC('KING') FROM DUAL;
PROMPT Content of the TMP_PERSON table
COL NAME FOR A30
SELECT * FROM TMP_PERSON;
При запуске предыдущего скрипта мы получаем следующий вывод:
Table created.
Table created.
1 row created.
Function created.
Calling the TEST_FUNC function and insert a new record into TMP_PERSON table
TEST_FUNC('KING')
------------------------------------------------------------
1 Person record successfully inserted into TMP_PERSON table
Content of the TMP_PERSON table
NAME
------------------------------
KING