※錯誤的例子
CREATE OR REPLACE FUNCTION dynamic_sql(xxx_table VARCHAR2) RETURN NUMBER IS
xxx_count NUMBER;
BEGIN
SELECT COUNT(*) INTO xxx_count FROM USER_TABLES WHERE TABLE_NAME = UPPER(xxx_table);
IF xxx_count = 0 THEN
CREATE TABLE xxx_table(
ID NUMBER,
NAME VARCHAR2(10),
CONSTRAINT XXX_PK_' || xxx_table || ' PRIMARY KEY(ID)
);
END IF;
SELECT COUNT(*) INTO xxx_count FROM xxx_table;
RETURN xxx_count;
END;
BEGIN
DBMS_OUTPUT.PUT_LINE(dynamic_sql('xxx'));
END;
※執行時,出現「PLS-00103: 發現了符號 "CREATE" 當您等待下列事項之一發生時:~~」,也就是沒辦法直接在裡面寫CREATE,所以修改如下:
※EXECUTE IMMEDIATE
※範例一
CREATE OR REPLACE FUNCTION dynamic_sql(xxx_table VARCHAR2) RETURN NUMBER IS
xxx_count NUMBER;
dynamic_create VARCHAR2(100);
BEGIN
SELECT COUNT(*) INTO xxx_count FROM USER_TABLES WHERE TABLE_NAME = UPPER(xxx_table);
IF xxx_count = 0 THEN
dynamic_create := 'CREATE TABLE ' || xxx_table || -- 注意CREATE TABLE後要加空格
'(
ID NUMBER,
NAME VARCHAR2(10),
CONSTRAINT XXX_PK_' || xxx_table || ' PRIMARY KEY(ID)
)';
EXECUTE IMMEDIATE dynamic_create;
END IF;
dynamic_create := 'SELECT COUNT(*) FROM ' || xxx_table; -- 注意FROM後要加空格
EXECUTE IMMEDIATE dynamic_create INTO xxx_count;
RETURN xxx_count;
END;
※執行時如果出現權限不足,使用sys登入
CONN sys as SYSDBA-->密碼
GRANT CREATE ANY TABLE TO 帳號名稱
※CONSTRAINT一定要加xxx_table,不然執行第二次會發現名字重覆
※範例二
DECLARE dynamic_sql VARCHAR2(200); xxx_count NUMBER; BEGIN SELECT COUNT(*) INTO xxx_count FROM USER_TABLES WHERE TABLE_NAME='XXX_TABLE'; IF xxx_count = 0 THEN dynamic_sql := ' CREATE TABLE XXX_TABLE( id NUMBER PRIMARY KEY, name VARCHAR2(10) )'; EXECUTE IMMEDIATE dynamic_sql; ELSE dynamic_sql := 'TRUNCATE TABLE XXX_TABLE'; EXECUTE IMMEDIATE dynamic_sql; END IF; dynamic_sql := ' BEGIN FOR i IN 1..10 LOOP INSERT INTO XXX_TABLE VALUES(i, ''xxx'' || i); END LOOP; END;'; EXECUTE IMMEDIATE dynamic_sql; COMMIT; END;
※XXX_TABLE一定要大寫
※BEGIN~END字串裡最後一定要有「;」
※因為已經是在「'」裡面,所以裡面要用時,只好用跳脫字元,兩個「'」就是一個「'」
※dynamic_sql我本來設100,但出「ORA-06502: PL/SQL: 數字或值錯誤: 字元字串緩衝區太小」這個錯,所以加到200就ok了
※USING
USING只能用在DML,可以依照順序對應到自定的參數※用法
DECLARE dynamic_sql VARCHAR2(200); xxx_deptno DEPT.DEPTNO%TYPE := 80; xxx_dname DEPT.DNAME%TYPE := 'aaa'; xxx_loc DEPT.LOC%TYPE := 'bbb'; BEGIN dynamic_sql := ' INSERT INTO DEPT VALUES(:p1, :p2, :p3) '; EXECUTE IMMEDIATE dynamic_sql USING xxx_deptno, xxx_dname, xxx_loc; COMMIT; END;
※USING xxx_deptno, xxx_dname, xxx_loc,可以直接將值寫在裡面,如
USING 80, 'aaa', 'bbb',如果有null,要用空,如USING 80, 'aaa', '',
不能顯示的寫NULL,如USING 80, 'aaa', NULL
※和巢狀表配合使用
DECLARE
dynamic_sql VARCHAR2(200);
TYPE dno IS TABLE OF DEPT.DEPTNO%TYPE NOT NULL;
TYPE dna IS TABLE OF DEPT.DNAME%TYPE NOT NULL;
xxx_nested dno := dno(10, 20, 30);
ooo_nested dna := dna('apple', 'banana', 'strawberry');
BEGIN
dynamic_sql := '
UPDATE DEPT SET dname = :p1 WHERE deptno = :p2
';
FOR i IN 1..xxx_nested.LAST LOOP
EXECUTE IMMEDIATE dynamic_sql USING ooo_nested(i), xxx_nested(i);
END LOOP;
-- COMMIT;
END;
※COMMIT我先註解掉,不然會蓋掉原有的值
※查詢
DECLARE dynamic_sql VARCHAR2(200); xxx_eno EMP.EMPNO%TYPE := 7499; xxx_emp EMP%ROWTYPE; BEGIN dynamic_sql := ' SELECT * FROM EMP WHERE EMPNO = :p1 '; EXECUTE IMMEDIATE dynamic_sql INTO xxx_emp USING xxx_eno; DBMS_OUTPUT.PUT_LINE(xxx_emp.empno || ' ' || xxx_emp.ename); END;
沒有留言:
張貼留言