oracle 正在查找有关编写PLSQL以确定正在执行的SQL DML操作的帮助

63lcw9qa  于 2023-03-17  发布在  Oracle
关注(0)|答案(1)|浏览(205)

我想编写一个PLSQL过程,它接受一个SQL字符串作为参数,并确定该SQL语句是SELECT、INSERT、UPDATE或DELETE语句还是OTHER语句,如果不是上述语句(例如,如果它是DDL语句),或者它可能返回DDL,但可能仍然需要“OTHER”。
在任何情况下,因为SQL当然会变得非常复杂并且变化很大,所以我认为唯一的方法是利用Oracle内置的SQL解析引擎(如果该功能公开的话)。
数据库管理系统_SQL库https://docs.oracle.com/en/database/oracle/oracle-database/19/arpls/DBMS_SQL.html#GUID-C96D5BAA-29A9-4AB5-A69E-E31228ECC9E9
想办法,但我想我会看看是否还有人在这方面有经验...

bnl4lu3b

bnl4lu3b1#

也许你可以使用解释计划表来得到它。类似这样:

CREATE OR REPLACE PROCEDURE GET_DML_OP(p_SQL IN VarChar2) AS 
BEGIN
    Declare
        mCmd        VarChar2(4000) := 'EXPLAIN PLAN SET STATEMENT_ID = ''proc_get_dml_op_'' FOR ' || p_SQL;
        mRow        NUMBER(3) := 0;
        CURSOR c IS 
          select PLAN_TABLE_OUTPUT from table(dbms_xplan.display('plan_table', 'proc_get_dml_op_'));
        mExplain    VarChar2(4000);
    Begin
        Begin
            Execute Immediate mCmd;
        Exception
            When OTHERS Then 
                DBMS_OUTPUT.PUT_LINE('OTHER  OR  *** SQLERRM: ' || SQLERRM || ' ***');
                DELETE FROM PLAN_TABLE WHERE STATEMENT_ID = 'proc_get_dml_op_';
        End;
        For r In c LOOP
            mRow := mRow + 1;
            If mRow <= 8 THEN
                mExplain := TRIM(SubStr(r.PLAN_TABLE_OUTPUT, InStr(r.PLAN_TABLE_OUTPUT, '|', 1, 2) + 1, InStr(r.PLAN_TABLE_OUTPUT, '|', 1, 3) - InStr(r.PLAN_TABLE_OUTPUT, '|', 1, 2) - 1  ));
                If SubStr(mExplain, 1, 6) IN('INSERT', 'UPDATE', 'DELETE', 'SELECT', 'MERGE ') THEN
                    DBMS_OUTPUT.PUT_LINE(mExplain);
                    DELETE FROM PLAN_TABLE WHERE STATEMENT_ID = 'proc_get_dml_op_';
                    GoTo EndIt;
                End If;
            End If;
        END LOOP;
        DELETE FROM PLAN_TABLE WHERE STATEMENT_ID = 'proc_get_dml_op_';
      <<EndIt>>
        Null;
    End;
END GET_DML_OP;

如果用一些sql语句调用该过程...

SET SERVEROUTPUT ON
BEGIN
    GET_DML_OP('SELECT * FROM A_TABLE_NAME');
    GET_DML_OP('WITH a AS (Select 1 "NMBR", ''A'' "LTTR" FROM DUAL) Select * From a');
    --
    GET_DML_OP('UPDATE A_TABLE_NAME SET PATH = ''999'' Where PATH Is Null');
    GET_DML_OP('INSERT INTO A_TABLE_NAME VALUES(''xxx'', ''yy'', ''zzz'')');
    GET_DML_OP('DELETE FROM A_TABLE_NAME WHERE PATH Is Null');
    --
    GET_DML_OP('ALTER TABLE A_TABLE_NAME MODIFY(PATH VarChar2(50))');
    GET_DML_OP('MERGE INTO emp e USING dept d ON (e.deptno = d.deptno) WHEN MATCHED THEN UPDATE SET e.COMM = null');
END;
/

R e s u l t :
anonymous block completed
SELECT STATEMENT
SELECT STATEMENT
UPDATE STATEMENT
INSERT STATEMENT
DELETE STATEMENT
OTHER  OR  *** SQLERRM: ORA-00900: invalid SQL statement ***
MERGE STATEMENT

相关问题