pl/spl编程

pl/spl编程

1.pl/sql的特点:

– 1).结构化,模块化;
– 2).预加载大量sql指令,提高效率;
– 3).逻辑结构: 顺序 分支 循环
– 4).方便进行数据库移植;
– 5).可以在plsql中使用函数 存储过程 序列 DML等

2.pl/sql中变量

   --    1).数据类型  --> 与数据库表的字段(列)的数据类型有区别
   --      ①: 标量类型
   --        varchar2
   --        number(m,n) 
   --        boolean 
   --        date
   --	timestamp
   --      ②: LOB large Object 大对象类型
   --        CLOB
   --        BLOB
   --        BFILE
   --        NCLOB
   --      ③: 属性类型
   -- [schema].table_name.column_name%type --> 表示声明的变量与指定用户的指定表的指定列的数据类型一致;
   --        [schema].table_name%rowtype --> 表示声明的变量与指定数据表的一行的数据类型一致;
   --  声明变量的基本语法:  --> 匿名块
   --  declare
   --    --声明的内容: 变量  常量  游标 
   --  begin
   --    --逻辑代码
   --  end;

psl/sql中的运算符:
– 变量的命名规则:
– 不能超过30个字符
– 不能以字母开头
– 可以包含字母 数字 下划线 $ #
– 不能有空格
– 不能是oracle的关键字和保留字
– 声明一个number类型的值


```sql
conn li/li;
declare
  numd number(10,0):=123;
  xm varchar2(100):='dre';
  --Nclob类型
  test nclob:='fwrw2342sfwr';
  --声明属性数据类型的变量
  --myName li.table_li.li_name%type;
  --声明一个行属性数据类型的变量
 -- myRow table_li%rowtype;
 begin
 --显示变量num的值
  dbms_output.put_line('变量num的值是:'||numd||'xm的值是:'||xm);
  dbms_output.put_line(test);
end;

select * from SALES;
   
 
   select * from auto_part;
   -- alter session set nls_date_format='yyyy/mm/dd'; 
   alter session set nls_date_format='yyyy-mm-dd';


	create or replace function calSun (
			beginValue in number,endValue in number 
) return number 
is
		--声明部分
		i number(10,0):=0;
		result number(10,0):=0;
begin
		i:=beginValue;
		while i<=endValue loop
					result :=result+i;
					i:=i+1;
		end loop;
	  return result;
end;



drop function calSun;

	create or replace function calSum (
			beginValue in number,endValue in number 
) return number 
is
		--声明部分
		i number(10,0):=0;
		result number(10,0):=0;
begin
		i:=beginValue;--i=90;
		while
					i<=endValue loop  --ifi<=2
					result :=result+i;--循环
					i:=i+1;
		end loop;
	  return result;
end;

select calSum(1,100) as 和的值是  from dual;   
   
   
  --创建一个函数方法用于计算次方
  create or replace function calsud(
      ne in number ,ci in number
  ) return number
  is 
  --声明
    i number(10,0):=0;
    result number(10,0):=ne;
  begin
    while i<ci loop
        result:=result*ne;
        i:=i+1;
    end loop;
    return result;
  end;
  select 2*2*2 from dual;
  select calsud(2,3) from dual;
  --改变文档日期格式
 alter session set nls_date_format='yyyy/mm/dd';
 -- 创建一个函数去查询每个科目最近一次考试的平均分最高科目编号
 conn li/li;
  select * from result;
  --获取每个科目的平均分
  select * from subjcet;
  select subjectNO as 科目 ,avg(studentresult) from RESULT group by SUBJECTNO;
  --获取最近一次考试
  select max(examDate) from result ;
  --创建函数
  create or replace function getSub
  return number--无参就不用括号什么的
  --声明
    is
      subjectNO li.result.subjectNO%type;
    begin
      select subjectNo into subjectNo from RESULT where STUDENTNO in (
         select sNO from 
           (
          select sNO  ,max(f.fe) as 平均分 from (
                select subjectNO as sNo ,avg(studentresult) as fe from RESULT  group by SUBJECTNO
          )f group by f.sNo 
      ) 
      ) and EXAMDATE=(
           select max(examDate) from result
      );
      return subjectNO;
    end;
 select * from RESULT where STUDENTNO=getsub();
 
 --oracle中的函数 
-- 字符串函数
--	ASCII(X): 返回字符X的ASCII码
select ascii(SUBJECTNO) from SUBJCET;
select ascii('a')from dual;
select ascii('A')from dual;
--	CONCAT(X,Y): 连接字符串X和Y
select concat('erewr','234g') from dual;
--	INSTR(X,STR,[START]): 从X中查找str,可以指定从start开始
select instr('safdsgdsaf','s',4) from dual;
--	LENGTH(X): 返回X的长度
select length('fdsssssssssssss') from dual;
--	LOWER(X): X转换成小写
select lower('sdFJIe') from dual;
--	UPPER(X): X转换成大写
select upper('erewd')from dual;
--	LTRIM(X[,TRIM_STR]): 把X的左边截去trim_str字符串,缺省截去空格
select Ltrim('    rer                           ')from dual;
--	RTRIM(X[,TRIM_STR]): 把X的右边截去trim_str字符串,缺省截去空格
select rtrim('  rewr     ')from dual;
--	TRIM([TRIM_STR  FROM]X): 把X的两边截去trim_str字符串,缺省截去空格
select trim(' re fs ')from dual;
--	REPLACE(X,old,new): 在X中查找old,并替换成new
select replace('grtegdsgs','gds','urowureo') from dual;
--	SUBSTR(X,start[,length]): 返回X的字串,从start处开始,截取length个字符,缺省length,默认到结尾
select substr('jfowjflsjf',2,3)from dual;

-- 数学函数
--	ABS(X): X的绝对值
select abs(-243) from dual;
--	CEIL(X): 大于或等于X的最小值
select ceil(-12.9) from dual;
--	FLOOR(X): 小于或等于X的最大值
select floor(-12.9)from dual;


--	MOD(X,Y): X除以Y的余数
select mod(3,4)from dual;


alter session set nls_date_format='yyyy-mm-dd';
--	POWER(X,Y): X的Y次幂
select power(3,6)from dual;
--	ROUND(X[,Y]): X在第Y位四舍五入
select round(123.234,2)from dual;
--	SQRT(X): X的平方根
select sqrt(8)from dual;
--	TRUNC(X[,Y]): X在第Y位截断,直接截断,不进行四舍五入
select trunc(2.324)from dual;
-- 日期函数--dual双重的
--	ADD_MONTHS(d,n): 在某一个日期 d 上,加上指定的月数 n,返回计算后的新日期
select add_months(sysdate,12)from dual;
--	LAST_DAY(d): 返回指定日期当月的最后一天
select last_day(sysdate)from dual;
--	ROUND(d[,fmt]),返回一个以 fmt 为格式的四舍五入日期值,d 是日期,fmt 是格式模型
select round(sysdate,'year')from dual;
--	默认 fmt 为 DDD,即月中的某一天。
--	① 如果 fmt 为“YEAR”则舍入到某年的 1 月 1 日,即前半年舍去,后半年作为下一年。
--	② 如果 fmt 为“MONTH”则舍入到某月的 1 日,即前月舍去,后半月作为下一月。
--	③ 默认为“DDD”,即月中的某一天,最靠近的天,前半天舍去,后半天作为第二天。
--	④ 如果 fmt 为“DAY”则舍入到最近的周的周日,即上半周舍去,下半周作为下一周周日。
--	eg:SELECT SYSDATE,ROUND(SYSDATE),ROUND(SYSDATE,'day'),ROUND(SYSDATE,'month'),ROUND(SYSDATE,'year') FROM dual;
--	
--	EXTRACT(fmt FROM d),提取日期中的特定部分。
-- 	fmt 为:YEAR、MONTH、DAY、HOUR、MINUTE、SECOND。其中 YEAR、MONTH、DAY可以为 DATE 类型匹配,也可以与 TIMESTAMP 类型匹配;
--	但是 HOUR、MINUTE、SECOND 必须与 TIMESTAMP 类型匹配。HOUR 匹配的结果中没有加上时区,因此在中国运行的结果小 8 小时。
-- 	eg:SELECT SYSDATE "date",
-- 		EXTRACT(YEAR FROM SYSDATE)"year",
--       		EXTRACT(MONTH FROM SYSDATE)"month",
-- 		EXTRACT(DAY FROM SYSDATE)"day",
-- 		EXTRACT(HOUR FROM SYSTIMESTAMP)"hour",
-- 		EXTRACT(MINUTE FROM SYSTIMESTAMP)"minute",
-- 		EXTRACT(SECOND FROM SYSTIMESTAMP)"second"
--		FROM dual;  extract/ik'str(ae爱)kt/提取
select  extract(year from sysdate) from dual;
-- 转换函数
	--to_char(data,format)
	--data: 数字  日期   从数据库表中查询出来的列值  format: yyyy-mm-dd 
	select to_char(borndate,'yyyy-mm-dd') as 生日 from student;
	select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') as 当前日期时间 from dual;   
	select to_char(sysdate,'yyyy') as 当前日期的年份 from dual;   
	select to_char(sysdate,'mm') as 当前日期的月份 from dual;  
	select to_char(sysdate,'dd') as 当前日期的日 from dual;   
	select to_char(sysdate,'hh24') as 当前时间的小时   from dual;   
	select to_char(sysdate,'mi') as 当前时间的分钟 from dual;  
	select to_char(sysdate,'ss') as 当前时间的秒钟 from dual; 
	select to_char(1234.0558,'$9999999.99') as 货币字符串 from dual;
	select to_char(1234.0558,'C9999999.99') as 货币字符串 from dual;
	select to_char(1234,'xxxx') as 十六进制数据 from dual;
conn system/orcl;
conn Scott/tiger;
--分析函数
   --row_number
   --dense_rank
   --rank
   /*
      基本语法:函数名【(参数)】 over ([partition by 用于分区的列 order by 用于排序的列 asc|desc])
    	函数名称() over (分组 排序); 
   */
   --查询员工表
   select * from emp;
   select empno,ename,deptno,sal
            ,row_number() over (partition by deptno order by sal asc) as row_number分区排序,
            dense_rank() over (partition by deptno order by sal asc) as dense_rank分区排序,
            rank() over(partition by deptno order by sal asc)as rank分区排序
            from emp;
  --总结:
        --row_number()不管数据的大小否相同都会按序号排序,即如果有相同的数据则根据出现的次序依次递增。
        --dense_rank()如果遇见相同的数据则会出现并列的排名。并且不会空出下一个排名
        --rank()如果遇见相同的数据会出现并列的排名,但是会空出下一个排名
        
  alter session set nls_date_format='yyyy-mm-dd';
   --查询员工表中每个部门工资前三名的员工信息(工资前三名)
   select * from emp where empNO in 
   (
      select empNO from (
          --前三名
          select empNO,money from (
                 select empNO,emp.JOB,sal,row_number() over (partition by deptno order by sal asc) as money from emp order by JOB
           ) bv where money<=3
       )
    )order by sal desc;
   select job from emp;
   select sal from emp;
	--工资最高: 如果工资相同 --> 只能算一个
   select empNO,emp.JOB,sal,dense_rank() over (partition by deptno order by sal asc) as money from emp;
	--工资最高: 如果工资相同 --> 算多个
    select empNO,emp.JOB,sal,row_number() over (partition by deptno order by sal asc) as money from emp order by JOB;
  /*
  pl/sql编程中的异常: Exception
  
  基本语法
  declare
    -- 声明变量 游标 异常等
  begin
    --sql_statement;
  exception
    when exception_name then
      --异常1
    when exception_name then
      --异常2
    ...
    when others then
      --其他异常
  end;
*/  
--异常
conn li/li;
select * from student;


 declare
      num number:=19;
      res number:=12;
      sName li.Student.StudentName%type; 
      var varchar2(100):=null;
      --no_data_found
      --声明一个自定义异常
      data_is_null Exception;
 begin
   --计算结果
    res:=num/0;
   select StudentName into sName from Student where studetNo='101';
   --判断var变量的值,如果该值为null人为的抛出一个新的异常   
   
--    if var is null then
----      raise data_is_null;
--        --调用系统函数抛出异常
--        raise_application_error(-20111,'使用系统函数抛出的异常!');
--    end if;
--    exception 
--      when zero_divide then
--          dbms_output.put_line('异常编码: '||sqlcode||'异常信息: '||sqlerrm);
--      when no_data_found then
--         dbms_output.put_line('异常编码: '||sqlcode||'异常信息: '||sqlerrm);
--      when data_is_null then
--        dbms_output.put_line('数据为null');
--      when others
--       dbms_output.put_line('发生了其他异常!'||sqlcode||sqlerrm);
--end;

select * from student;
DECLARE
		sNo LI.STUDENT.STUDENTNO%type;
    SName LI.STUDENT.STUDENTNAME%type;
    --声明一个游标
    cursor one(idea VARCHAR2) is 
          select studentNo,studentName from student where studentNO <idea;
begin 
		--打开游标 游标属性:%isopen-->游标是否打开
		if not one%isopen THEN
			open one('110');
    end if;
   --循环提取游标中的数据
	loop
		--将游标中的数据提取出来设置给指定的变量
    fetch one into sNo,SName;
    --判断什么时候退出循环--》游标属性:%notfound
    exit when one%notfound;
    --显示从游标中提出的数据 游标属性:%rowcount;
    dbms_output.put_line('第'||one%rowcount||'行数据'||sNo||'<==>'||SName);
  end loop;
  end;
  
  
  
  DECLARE
	sNo LI.STUDENT.STUDENTNO%type;
  sName LI.STUDENT.STUDENTNAME%type;
  cursor twod(ide varchar2) IS
				select studentNo,studentName from student where studentNO < ide;
BEGIN
	 --打开游标
		IF twod%isopen THEN
			open twod('110');
		end if;
	--提取游标
   fetch twod into sNo,sName;
  dbms_output.put_line('第'||twod%rowcount||'行数据'||sNo||'<==>'||sName);
   while twod%found loop
   fetch twod into sNo,sName;
      dbms_output.put_line('第'||twod%rowcount||'行数据'||sNo||'<==>'||sName);
	end loop;
  end;
  --关闭游标
  --close twod;
 --EXCEPTION 
	--	when others then 
		--		 dbms_output.put_line(sqlcode || sqlerrm);

  
    
   
   
   
   
declare
  sNo LI.STUDENT.STUDENTNO%type;
  sName LI.STUDENT.STUDENTNAME%type;
  --声明一个游标
  cursor myCursor(xh varchar2) is select studentNo,studentName from Student where sNo < xh;
begin
  --打开游标  游标属性: %isopen  --> 判断游标是否打开
  if not myCursor%isopen then
    open myCursor('1023');
  end if;
  --循环提取游标中的数据
  --loop
    --将游标中的数据提取出来设置给指定的变量
  --  fetch myCursor into studentno,studentName;
    --判断什么时候退出循环 --> 游标属性: %notfound;
  --  exit when myCursor%notfound;
    --显示从游标中提出的数据  游标属性: %rowcount;
  --  dbms_output.put_line('第'||myCursor%rowcount || '行数据: ' ||studentNo || '<==>' || studentName);
 -- end loop;

  --使用while循环迭代游标中的数据  --> 游标属性: %found --> 如果游标中有数据返回true
  fetch myCursor into sNo, sName;
  dbms_output.put_line('第'||myCursor%rowcount || '行数据: ' ||sNo || '<==>' || sName);
  while myCursor%found  loop
   --提取
   fetch myCursor into sNo, sName;
   dbms_output.put_line('第'||myCursor%rowcount || '行数据: ' ||sNo || '<==>' || sName);
  end loop;
  --关闭游标
  close myCursor;
exception
  when others then
    dbms_output.put_line(sqlcode || sqlerrm);
end;

--用forin做一个无参的
declare 
 --声明游标
  cursor my is select studentNo,studentName from student where studentNO < '1023';
BEGIN
  --forin自动打开游标
  for itme in my loop
			dbms_output.put_line(item.studentNo || '<==>' || item.studentName);
	end loop;

end;


declare
  --备注: 如果游标需要参数,参数的数据类型只能有类型本身不能指定数据类型的范围
  cursor myCursor is select studentNo,studentName from student where studentNo < '1032';
begin
  --for循环  item 必须是: %rowtypes  自动开启游标(隐式打开游标)  自动关闭
  for item in myCursor loop
     dbms_output.put_line(item.studentNo || '<==>' || item.studentName);
  end loop;
end;

   
   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值