0.场景
一句话就是执行字符串拼接起来的SQL。
1.创建3个过程
创建执行insert ,update ,delete 语句的过程;创建执行select的过程;创建一个过程把以上两个整合在一起,这样增删改查就齐活了。
1.1 创建执行DML的过程
这个比较简单,直接上plsql代码。
create or replace procedure p_exe_dml(sql_dml in varchar2) is
result varchar2(52);
rows number(17);
ls_sql6 varchar2(17);
begin
--sql语句过滤,只执行select,update,delete,insert 开头的sql
ls_sql6 := substr(lower(trim(sql_dml)),1,6);
if ls_sql6 not in ('insert','update','delete') then
htp.p( '支持的DML SQL(INSERT UPDATE DELETE);不支持:' || sql_dml);
return;
end if;
--执行sql
execute immediate sql_dml;
rows := sql%rowcount;
commit;
--影响的行数
result := '影响行数:' || to_char(rows);
htp.p(result);
end;
简单测试一下:
begin
p_exe_dml('insert into atop(p_id) values (-5217)');
p_exe_dml('update atop set f_dm = ''5217'' where p_id = -5217' );
end;
begin
p_exe_dml('delete atop where p_id=-5217');
end
输出结果在这里:
一切OK。
1.2 执行select的过程
这个稍微复杂一些,用到DBMS_SQL包。
create or replace procedure p_exe_select(select_str in varchar2) is
SYS_RC SYS_REFCURSOR;
ls_sql6 varchar2(17);
L_COLS NUMBER;
L_DESC DBMS_SQL.DESC_TAB;
L_CURS INTEGER;
L_VARCHAR VARCHAR2(521);
BEGIN
--sql语句过滤,只执行select 开头的sql
ls_sql6 := substr(lower(trim(select_str)),1,6);
if not(ls_sql6 = 'select') then
return;
end if;
OPEN SYS_RC FOR select_str;
--CAPITALEXTRACT(SYS_RC => SYS_RC);
L_CURS := DBMS_SQL.TO_CURSOR_NUMBER(SYS_RC);
DBMS_SQL.DESCRIBE_COLUMNS(C => L_CURS, COL_CNT => L_COLS,DESC_T => L_DESC);
FOR i IN 1..L_COLS LOOP
DBMS_SQL.DEFINE_COLUMN(L_CURS, i, L_VARCHAR, 4000);
END LOOP;
WHILE DBMS_SQL.FETCH_ROWS(L_CURS) > 0 LOOP
--DBMS_OUTPUT.PUT('Row ' || DBMS_SQL.LAST_ROW_COUNT || ': ');
htp.p('Row ' || DBMS_SQL.LAST_ROW_COUNT || ': ');
FOR i IN 1..L_COLS LOOP
DBMS_SQL.COLUMN_VALUE(L_CURS, i, L_VARCHAR);
--DBMS_OUTPUT.put( l_desc(i).col_name || ' = ' || L_VARCHAR || ';');
htp.p(l_desc(i).col_name || ' = ' || L_VARCHAR || ';');
END LOOP;
--dbms_output.put_line('');
htp.p(chr(13));
END LOOP;
DBMS_SQL.CLOSE_CURSOR(L_CURS);
END;
简单测试一下:
输出结果:
1.3 整合在一起
以上两个过程整合在一起。
create or replace procedure P_EXE_SQL(SQL_STR VARCHAR2) is
ls_sql6 varchar2(17);
begin
--sql语言过滤,只执行select,update,delete,insert 开头的sql
ls_sql6 := substr(lower(trim(SQL_STR)),1,6);
if ls_sql6 in ('insert','update','delete') then
p_exe_dml(SQL_STR);
elsif ls_sql6 = 'select' then
p_exe_select(SQL_STR);
end if;
end;
自己测试吧。