2010-11-04 24 views
6

tôi không thể thuyết phục lý do tại sao tôi không thể thêm hoạt động DML bên Oracle Chức năng đặc biệt bên trong con trỏ vòng lặp. Tôi cảm thấy Oracle không hỗ trợ hoạt động DML bên trong vòng lặp con trỏ.không thể thực hiện thao tác DML bên trong một truy vấn

Làm cách nào tôi có thể thực hiện Nếu tôi cần chèn vào bảng bên trong vòng lặp con trỏ? Tạo thủ tục lưu trữ mới bên trong nó hoặc cái gì khác?

Thông báo Lỗi: không thể thực hiện thao tác DML bên trong một truy vấn

Đây là chức năng của tôi,

CREATE OR REPLACE FUNCTION TEST_FUNC(U_ID IN VARCHAR2) 
RETURN VARCHAR2 
IS 
    V_MESSAGE VARCHAR2(30); 
    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); 
    END LOOP; 

    RETURN V_MESSAGE; 

EXCEPTION 
WHEN OTHERS THEN 
    raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM); 
END; 

Trả lời

11

Bạn thể sử dụng DML bên trong một hàm PL/SQL - không có vấn đề. Tuy nhiên, chức năng chỉ có thể được gọi từ PL/SQL, không phải từ SQL - tức là nó có thể được gọi như thế này:

declare 
    l_message varchar2(30); 
begin 
    l_message := test_func('123'); 
end; 

... nhưng không như thế này:

select test_func(empno) from emp; 

Điều đó dẫn đến thông báo lỗi bạn đã đăng.

Nhiều người (kể cả tôi) không thích các chức năng có "tác dụng phụ" như thế này, nhưng đó là vấn đề thực tiễn và tiêu chuẩn tốt nhất, không phải là vấn đề kỹ thuật.

+0

Cảm ơn, Đó là những gì tôi đang yêu cầu. – ppshein

11

Bạn có thể thực hiện các hoạt động DML bên trong một hàm Oracle PL/SQL và mặc dù đây không phải là thực tiễn tốt, hãy gọi nó từ SQL. Chức năng phải được đánh dấu bằng pragma AUTONOMOUS_TRANSACTION và giao dịch phải được cam kết hoặc quay trở lại trước khi thoát khỏi chức năng (xem AUTONOMOUS_TRANSACTION Pragma).

Bạn nên lưu ý rằng loại hàm này được gọi từ SQL có thể làm giảm đáng kể hiệu suất truy vấn của bạn. Tôi khuyên bạn chỉ sử dụng nó chỉ cho mục đích kiểm toán.

Dưới đây là một đoạn mã ví dụ bắt đầu từ hàm của bạn:

 
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; 

Khi chạy kịch bản trước đó chúng tôi nhận được kết quả như sau:

 
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 
+2

+1. Ngoài các vấn đề về hiệu năng và giao dịch, cũng rất khó để biết chính xác số lần hàm sẽ thực thi. Ví dụ, câu lệnh này không gọi hàm nào cả: chọn * từ hai nơi tồn tại (chọn test_func ('KING') từ kép); SQL là khai báo và không có cách nào để đảm bảo chính xác cách truy vấn sẽ thực thi. –

Các vấn đề liên quan