Oracle 中 execute immediate v_sql; 的用法详解

execute immediate v_sql 的几种常见用法

这是一个让你可以在数据库为所欲为(自己成语接龙一下~~手动滑稽) 的语法

学计算机的我们必然是先知道怎么用,再知道为什么要这样用。先 know how ?再 know why?。


我目前也只知道怎么用,至于为什么,emmmm。超纲了超纲了。如果读者已经熟练掌握 execute immediate v_sql 的用法,那……很抱歉,阅读以上内容花费了您宝贵的时间。您去找其他博客看吧,顺便收下我的膝盖(扑通~~~)。


execute immediate (立即执行),它可以动态执行SQL。类似JavaScript中的 eval();

话不多说先上干货


用法1
	v_sql:='select * from sys_users';
	execute immediate v_sql;

用法2
	v_sql:='select count(*) from sys_users';
	execute immediate v_sql into v_num;

用法3
	v_sql:= ' select t.user_id FROM sys_users t where t.user_name = :1';
	execute immediate v_sql into v_dname using v_item ;
	
用法4
	v_sql := 'BEGIN :1 := ' || 'sys_users_pkg.get_user_id' || '(:2,:3,:4,:5);END;';
  execute immediate v_sql using out v_user_id, in p_user_name, in p_password, 
    in p_parameter_other_1, p_parameter_other_2;
    
    相当于在存储过程或函数中调用复杂过程给变量赋值
    v_user_id := sys_users_pkg.get_user_id(p_user_name,p_password,...);

看到这里你肯定有很多疑问,如:

  • :1,:2 ,:3,:4,:5,代表什么?
  • using 关键字之后 inout怎么有时候有有时候没有,什么时候用in什么时候用out

语法分析

  • :1,:2 这样的字符代表占位符,在v_sql整个字符串中它代表的意义是需要等待指定的,我们可以使用using关键字指定 占位符 上是什么。
  • in 和 out 是 输入/输出的意思,in是默认的参数类型可以省略
  • 使用了using 但是没使用 in 或者out 关键字 那就是 in类型。
  • using aa 等价于 using in aa
  • using out aa 使用aa这个变量或字面量(没打错)去替换对应位置的占位符

小实验详解4个用法 (源代码可查阅附录)

先看下我们sys_users表的数据

select * from sys_users;

Oracle 中 execute immediate v_sql; 的用法详解_第1张图片


用法1:立即执行SQL语句 (crud都可以执行)

execute immediate v_sql;

场景:将用户 “路人甲” (用户id=3) 的用户名更换为 “STT”

update sys_users t set t.user_name = ‘STT’ where t.user_id = 3

DECLARE
  v_sql   VARCHAR2(2000) := ''; --字符串变量,存储欲执行的SQL语句
BEGIN
  v_sql := 'update sys_users t set t.user_name = '||'666'||' where t.user_id = 3';
  EXECUTE IMMEDIATE v_sql;
END;
--

注意:执行以上匿名代码块此时我们还未提交数据,在其他session中是无法看到我们的修改,必须在同一个SQL窗口中执行以下SQL查询数据

select * from sys_users;

Oracle 中 execute immediate v_sql; 的用法详解_第2张图片

用法2:立刻执行SQL语句,并赋值给某个变量

EXECUTE IMMEDIATE v_sql INTO 变量名;

场景:查询出sys_users表中的总行数 并赋值给变量 v_num

select count(*) from sys_users

DECLARE
  v_sql VARCHAR2(2000) := ''; --执行的sql
  v_num NUMBER := 0;
BEGIN
  v_sql := 'select count(*) from sys_users';
  -----------------------------------------
  EXECUTE IMMEDIATE v_sql
    INTO v_num;
  dbms_output.put_line('execute immediate用法2 执行成功,员工总数:' || v_num);
END;

执行结果
Oracle 中 execute immediate v_sql; 的用法详解_第3张图片

用法3:(用占位符传递参数给SQL),立刻执行SQL语句

EXECUTE IMMEDIATE v_sql INTO v_user_id USING IN v_user_name;

场景:通过用户名查用户id

SELECT t.user_id FROM sys_users t WHERE t.user_name = ‘苏涛涛’;

DECLARE
  v_sql       VARCHAR2(2000) := ''; --执行的sql
  v_user_name varchar2(10) := '苏涛涛';
  v_user_id   number :=0;
BEGIN
 v_sql:= ' SELECT t.user_id FROM sys_users t WHERE t.user_name = :1';
 execute immediate v_sql into v_user_id using v_user_name ;
 dbms_output.put_line(v_user_name||'的用户id为:'||v_user_id);
END;

执行结果
Oracle 中 execute immediate v_sql; 的用法详解_第4张图片

用法4:(用占位符传递参数给过程或函数),立刻执行SQL语句

场景:在存储过程或函数或匿名块中 传入用户名、密码查出用户id

SELECT t.user_id FROM sys_users t WHERE t.user_name = ‘苏涛涛’ > AND t.password = ‘MD5(123)’;

在一个匿名块中调用一个写好的程序包

DECLARE
  v_sql       VARCHAR2(2000);
  v_user_id   NUMBER;
  p_user_name VARCHAR2(20) := '苏涛涛';
  p_password  VARCHAR2(20) := 'MD5(123)';
  --以下参数仅为了演示用法,无实际用途
  p_parameter_other_1 VARCHAR2(20) := 'TEST1';
  p_parameter_other_2 VARCHAR2(20) := 'TEST2';
  p_parameter_other_3 VARCHAR2(20) := 'TEST3';
  p_parameter_other_4 VARCHAR2(20) := 'TEST4';
BEGIN
  v_sql := 'BEGIN :1 := ' || 'sys_users_pkg.get_user_id' || '(:2,:3,:4,:5,:6,:7);END;';
  EXECUTE IMMEDIATE v_sql
    USING OUT v_user_id, IN p_user_name, IN p_password, 
    IN p_parameter_other_1, 
    p_parameter_other_2, 
    p_parameter_other_3, 
    p_parameter_other_4;
  dbms_output.put_line('用户名和密码均正确,此用户用户id为' || v_user_id);
END;



每日一句:最好的种树时间,一个是10年前,一个是现在。

附录

附录1.建表语句


--创建用户表(表名SYS_USERS) 多说一句:表名在Oracle数据库中不区分大小写
create table SYS_USERS
(
  user_id     NUMBER,
  user_name   VARCHAR2(100),
  password    VARCHAR2(100),
  sex         VARCHAR2(1),
  enable_flag VARCHAR2(1)
);

--插入4条测试数据
insert into SYS_USERS (user_id, user_name, password, sex, enable_flag)
values (1, '苏涛涛', 'MD5(123)', 'F', 'Y');
insert into SYS_USERS (user_id, user_name, password, sex, enable_flag)
values (2, '宋文倩', 'MD5(MD5(456))', 'M', 'Y');
insert into SYS_USERS (user_id, user_name, password, sex, enable_flag)
values (3, '路人甲', '789', 'F', 'Y');
insert into SYS_USERS (user_id, user_name, password, sex, enable_flag)
values (4, '路人乙', '147', 'M', 'N');

附录2.sys_users_pkg 包源码

CREATE OR REPLACE PACKAGE sys_users_pkg IS

  FUNCTION get_user_id(p_user_name         VARCHAR2
                      ,p_password          VARCHAR2
                      ,p_parameter_other_1 VARCHAR2
                      ,p_parameter_other_2 VARCHAR2
                      ,p_parameter_other_3 VARCHAR2
                      ,p_parameter_other_4 VARCHAR2) RETURN NUMBER;

END sys_users_pkg;
/
CREATE OR REPLACE PACKAGE BODY sys_users_pkg IS
  FUNCTION get_user_id(p_user_name         VARCHAR2
                      ,p_password          VARCHAR2
                      ,p_parameter_other_1 VARCHAR2
                      ,p_parameter_other_2 VARCHAR2
                      ,p_parameter_other_3 VARCHAR2
                      ,p_parameter_other_4 VARCHAR2) RETURN NUMBER IS
    v_sql     VARCHAR2(1000);
    v_user_id NUMBER;
  BEGIN
    SELECT t.user_id
      INTO v_user_id
      FROM sys_users t
     WHERE t.user_name = p_user_name
       AND t.password = p_password;
    RETURN v_user_id;
  END;

END sys_users_pkg;
/


你可能感兴趣的:(数据库)