1、申明与赋值

1.程序块结构

  1. declare
  2. -- 申明部分
  3. begin
  4. -- 执行部分
  5. end;
  6. -- 写一个空的程序快
  7. declare
  8. -- 申明部分
  9. begin
  10. -- 执行部分
  11. null;
  12. end;

2.最简单的程序

declare
-- 申明部分
begin
-- 执行部分 
dbms_output.put_line('hello world');
end;

3.定义变量 变量赋值 变量是可变的

-- 已知长宽求周长

declare

-- 申明部分

v_long number;

v_wide number;

v_Perimeter number;

begin

-- 执行部分 

v_long:= 5;

v_wide:= 3;

v_Perimeter:= (v_long + v_wide)*2;

dbms_output.put_line('v_Perimeter = '||v_Perimeter);

end;



-- 申明变量的时候可以直接赋值么  赋初始值

declare

-- 申明部分

v_long number:= 5;

v_wide number:= 3;

v_Perimeter number;

begin

-- 执行部分 

v_Perimeter:= (v_long + v_wide)*2;

dbms_output.put_line('v_Perimeter = '||v_Perimeter);

end;



-- 变量是可变的

declare

-- 申明部分

v_long number:= 5;

v_wide number:= 3;

v_Perimeter number;

begin

-- 执行部分 

v_long := 8;

dbms_output.put_line('v_long = '||v_long);

v_Perimeter:= (v_long + v_wide)*2;

dbms_output.put_line('v_Perimeter = '||v_Perimeter);

end;

4.定义常量 constant

-- 已知半径求面积

declare

-- 申明部分

v_pi constant number:= 3.14;

v_r  number:= 3;

v_area number;

begin

-- 执行部分 

v_area:= v_pi*v_r*v_r;

dbms_output.put_line('v_area = '||v_area);

end;



-- 特性 常量必须赋初始值  常量是不可变的

declare

-- 申明部分

v_pi constant number;

v_r  number:= 3;

v_area number;

begin

-- 执行部分 

v_pi:= 3.14;

v_area:= v_pi*v_r*v_r;

dbms_output.put_line('v_area = '||v_area);

end;

5.字符/日期数据类型的变量

declare

-- 申明部分

v_name varchar2(30):='张三';

v_date date:= sysdate;

begin

-- 执行部分 

v_date:= to_date('20210101','yyyymmdd');

dbms_output.put_line('v_name = '||v_name);

dbms_output.put_line('v_date = '||v_date);

end;

6.隐式游标及其特性

-- 只能返回一行数据 返回多行或者没有数据都会报错

-- 语法 select into

declare

-- 申明部分

v_name varchar2(30);

v_sal  number;

begin

-- 执行部分 

select ename,sal into v_name,v_sal from emp where empno = 7499;

dbms_output.put_line('v_name = '||v_name);

dbms_output.put_line('v_sal = '||v_sal);

dbms_output.put_line(v_name||' 薪水是 '||v_sal);

end;



-- 特性1 返回多行数据会报错

declare

-- 申明部分

v_name varchar2(30);

v_sal  number;

begin

-- 执行部分 

select ename,sal into v_name,v_sal from emp ;

dbms_output.put_line(v_name||' 薪水是 '||v_sal);

end;



-- 特性2 没有数据会报错



declare

-- 申明部分

v_name varchar2(30);

v_sal  number;

begin

-- 执行部分 

select ename,sal into v_name,v_sal from emp where  empno = 1;

dbms_output.put_line(v_name||' 薪水是 '||v_sal);

end;



-- 防报错 加聚合函数

declare

-- 申明部分

v_name varchar2(30);

v_sal  number;

begin

-- 执行部分 

select max(ename),max(sal) into v_name,v_sal from emp ;

dbms_output.put_line(v_name||' 薪水是 '||v_sal);

end;

7.%type / %rowtype 定义数据类型

-- %TYPE:引用数据库中的某列的数据类型或某个变量的数据类型。

declare

-- 申明部分

v_name emp.ename%type;

begin

-- 执行部分 

select ename into v_name from emp where empno = 7499;

dbms_output.put_line(v_name);

end;



-- %ROWTYPE:引用数据库中的一行(所有字段)作为数据类型。

declare

-- 申明部分

v_all emp%rowtype;

begin

-- 执行部分 

select ename,sal into v_all.ename,v_all.sal from emp where empno = 7499;

dbms_output.put_line(v_all.ename);

dbms_output.put_line(v_all.sal);

end;

2、IF判断

if

-- if判断

-- if 条件 then 结果 end if

-- 一个分支 如果 SMITH 的工资小于1000 输出努力

declare
v_sal number;
begin
   select sal into v_sal from emp where ename = 'SMITH'; 
     if v_sal < 1000 
       then dbms_output.put_line('努力');
     end if;
end;



-- 两个分支 如果 SMITH 的工资小于500 输出努力 否则输出很棒

declare
v_sal number;
begin
   select sal into v_sal from emp where ename = 'SMITH'; 
     if v_sal < 500 
       then dbms_output.put_line('努力');
       else dbms_output.put_line('很棒');
     end if;
end;



-- 尽量少些 else
declare
v_sal number;
begin
   select sal into v_sal from emp where ename = 'SMITH'; 
     if v_sal < 500 
         then  dbms_output.put_line('努力');
     elsif v_sal >= 500
         then  dbms_output.put_line('很棒');
     end if;
end;



-- 多个分支 如果 SMITH 的工资小于500 输出努力  工资[500,2000) 输出可以  工资大于等于2000输出很棒
declare
v_sal number;
begin
   select sal into v_sal from emp where ename = 'SMITH'; 
     if v_sal < 500 
         then  dbms_output.put_line('努力');
     elsif v_sal >= 500 and v_sal < 2000
         then  dbms_output.put_line('可以');
     elsif v_sal >= 2000
         then  dbms_output.put_line('很棒'); 
     end if;
end;



-- 换一种写法
declare
v_sal number;
begin
   select sal into v_sal from emp where ename = 'SMITH'; 
     if v_sal < 500 
         then  dbms_output.put_line('努力');
     elsif v_sal >= 500 and v_sal < 2000
         then  dbms_output.put_line('可以');
     else dbms_output.put_line('很棒'); 
     end if;
end;



-- 比较难理解的写法
declare
v_sal number;
begin
   select sal into v_sal from emp where ename = 'SMITH'; 
     if v_sal < 500 
         then  dbms_output.put_line('努力');
     elsif v_sal < 2000
         then  dbms_output.put_line('可以');
     elsif v_sal >= 2000
         then  dbms_output.put_line('很棒'); 
     end if;
end;

case

-- 一个分支 如果 SMITH 的工资小于1000 输出努力
declare
v_sal number;
begin
   select sal into v_sal from emp where ename = 'SMITH'; 
     case when v_sal < 1000 
       then dbms_output.put_line('努力');
     end case;
end;



-- 两个分支 如果 SMITH 的工资小于500 输出努力 否则输出很棒
declare
v_sal number;
begin
   select sal into v_sal from emp where ename = 'SMITH'; 
  case when v_sal < 500 
       then dbms_output.put_line('努力');
       else dbms_output.put_line('很棒');
     end case;
end;



-- 尽量少些 else
declare
v_sal number;
begin
   select sal into v_sal from emp where ename = 'SMITH'; 
     case when v_sal < 500 
            then  dbms_output.put_line('努力');
          when v_sal >= 500
            then  dbms_output.put_line('很棒');
     end case;
end;



-- 多个分支 如果 SMITH 的工资小于500 输出努力  工资[500,2000) 输出可以  工资大于等于2000输出很棒
declare
v_sal number;
begin
   select sal into v_sal from emp where ename = 'SMITH'; 
     case when v_sal < 500 
            then  dbms_output.put_line('努力');
          when v_sal >= 500 and v_sal < 2000
           then  dbms_output.put_line('可以');
          when v_sal >= 2000
           then  dbms_output.put_line('很棒'); 
     end case;
end;



-- 换一种写法
declare
v_sal number;
begin
   select sal into v_sal from emp where ename = 'SMITH'; 
     case when v_sal < 500 
            then  dbms_output.put_line('努力');
          when v_sal >= 500 and v_sal < 2000
            then  dbms_output.put_line('可以');
            else dbms_output.put_line('很棒'); 
     end case;
end;



-- 比较难理解的写法
declare
v_sal number;
begin
   select sal into v_sal from emp where ename = 'SMITH'; 
     case when v_sal < 500 
           then  dbms_output.put_line('努力');
          when v_sal < 2000
           then  dbms_output.put_line('可以');
          when v_sal >= 2000
           then  dbms_output.put_line('很棒'); 
     end case;
end;





-- 建表造数
create table emp_1207 as select * from emp;
select * from emp_1207;
-- 条件后面 你想做什么事情就可以做什么事情

-- 把他的奖金改成 3000
declare
v_sal number;
begin
   select sal into v_sal from emp_1207 where ename = 'SMITH'; 
     if v_sal > 500 
         then  update emp_1207 set comm = 3000 where  ename = 'SMITH';
               commit;
     end if;
end;



-- 删除 30部门的数据
declare
v_sal number;
begin
   select sal into v_sal from emp_1207 where ename = 'SMITH'; 
     if v_sal > 500 
         then  delete from emp_1207  where deptno = 30;
               commit;
     end if;
end;

3、FOR循环

-- 循环的语法  loop  end loop
declare
begin
   loop
   end loop;
end;


-- 死循环 无条件循环
declare
begin
   loop
     null;
   end loop;
end;



-- for 循环
-- 自然数求和 1..100  5050

declare
v_a   number:= 0;
v_sum number:= 0;
begin
  for i in 1..100 loop
     v_a:= v_a + 1;  -- 每循环一次加1
     v_sum:= v_sum + v_a;
   end loop;
   dbms_output.put_line(v_sum);
end;



-- 看过程
declare
v_a   number:= 0;
v_sum number:= 0;
begin
  for i in 1..100 loop
     v_a:= v_a + 1;  -- 每循环一次加1
     v_sum:= v_sum + v_a;
     dbms_output.put_line(v_a||'  '||v_sum);  -- 循环100次这里就输出100次
   end loop;
   dbms_output.put_line(v_sum);
end;



-- 代码简化一下
declare
v_sum number:= 0;
begin
  for i in 1..100 loop
     v_sum:= v_sum + i;
     dbms_output.put_line(i); -- 看i的变化
   end loop;
   dbms_output.put_line(v_sum);
end;





-- while 循环  基本上没有人这么写
declare
v_a   number:= 0;
v_sum number:= 0;
begin
  while v_a < 100 loop
     v_a:= v_a + 1;  -- 每循环一次加1
     v_sum:= v_sum + v_a;
     dbms_output.put_line(v_a);
   end loop;
   dbms_output.put_line(v_sum);
end;



-- 无条件循环  exit  退出条件在循环体里面

declare
v_a   number:= 0;
v_sum number:= 0;
begin
   loop
     v_a:= v_a + 1;  -- 每循环一次加1
     v_sum:= v_sum + v_a;
   --  exit when v_a = 100; -- 第一种退出方式
   -- 第二种退出方式
     if v_a = 100 then exit;
     end if;
   end loop;
   dbms_output.put_line(v_sum);
end;

4、两数交换

declare
a number:= 10;
b number:= 5;
c number;
begin
   c:= a;   -- c=10  a=10
   a:= b;   -- c=10  a=5 b=5
   b:= c;   -- c=10  a=5 b=10 
   dbms_output.put_line('a='||a);
   dbms_output.put_line('b='||b);
end;


-- 两表交换 建表造数
select * from emp_1207;
select * from emp_1207_bak;
select * from emp_1207_tmp;

create table emp_1207 as select * from emp;
create table emp_1207_bak as select * from emp_1207;
delete from emp_1207_bak where deptno = 20;
commit;

-- 交换表名
alter table emp_1207     rename to emp_1207_tmp;
alter table emp_1207_bak rename to emp_1207;
alter table emp_1207_tmp rename to emp_1207_bak;

5、求和 求奇偶

declare 
v_sum_j number := 0;
v_sum_o number:= 0;
v_sum number := 0;
begin
  for i in 1..100 loop
    if mod(i,2) =1
      then v_sum_j := v_sum_j + i;
     elsif mod(i,2) =0
       then v_sum_o := v_sum_o + i;
     end if;
   v_sum := v_sum + i;
   end loop;
   dbms_output.put_line('v_sum_j = '||v_sum_j);

   dbms_output.put_line('v_sum_o = '||v_sum_o);

   dbms_output.put_line('v_sum = '||v_sum);

end;

6、动态sql

-- 动态sql  execute immediate
-- 建表造数
drop table emp_4;
create table emp_4 as select * from emp e;
select * from emp_4;
select * from emp_5;


--  ddl,truncate 不能直接用,要包装起来
declare
begin

 -- execute immediate '';

 -- truncate table emp_4;

 -- execute immediate 'truncate table emp_4';  -- 工作中天天要用的



  -- create table emp_5 as select e.* from emp_4 e where 1=2;

  -- execute immediate 'create table emp_5 as select e.* from emp_4 e where 1=2';

  -- alter table emp_5 add  aaa number;

 -- execute immediate 'alter table emp_5 add  aaa number';

   -- alter table emp_5 modify  aaa varchar2(50);

  -- execute immediate 'alter table emp_5 modify  aaa varchar2(50)';

    -- alter table emp_5 drop column aaa 

 -- execute immediate 'alter table emp_5 drop column aaa ';

  -- alter table emp_5 rename column deptno to bbb;

 -- execute immediate 'alter table emp_5 rename column deptno to bbb';

  -- alter table emp_5 rename to emp_4;

 -- execute immediate 'alter table emp_5 rename to emp_4';

 -- drop table emp_4;

 execute immediate 'drop table emp_4';

end;

7、存储过程

-- 存储过程   procedure  sp


-- 建表造数
drop table emp_bak;
create table emp_bak as select * from emp where 1 = 2;
select * from emp_bak;



-- 最简单的程序过程
create procedure sp_emp_bak is
begin
  insert into emp_bak
    select * from emp where deptno = 10;
  commit;
end;

-- 如果有就替换
create or replace procedure sp_emp_bak is
begin
  insert into emp_bak
    select * from emp where deptno = 10;
  commit;
end;


-- 测试过程
-- 第一步 编译  执行这个sp的代码  仅仅是把这个代码存到我们的数据库 
-- 第二步 调用

          1.在对象这先找到要测试的sp>选择对应的sp右键>测试

          2.sql窗口选择对应的sp右键>测试

          3.直接sql窗口写调用语句



begin sp_emp_bak; end;