Oracle语法

PL/SQL和T-SQL都是扩展SQL的一种方言。

PL/SQL的支持者有oracle、MySql等。

T-SQL的支持者有Sql Server、Sybase等。
SQL Monitor(oracle语句追踪工具)

GRANT SELECT, DELETE, INSERT, UPDATE ON ESCMOWNER.FSR_GEN_PPO_LOG TO ESCMUSER;
CREATE PUBLIC SYNONYM FSR_GEN_PPO_LOG FOR ESCMOWNER.FSR_GEN_PPO_LOG;

语法区别
PL/SQL用";"分割每一條語句,T-SQL用回車分割一條語句。
如ORACLE中sql语句可以用分号结尾,且不区分大小写。
SQL SERVER中sql语句不能用分号结尾,且对表等区分大小写。

执行查询时
PLSQL执行查询的时候,FROM子句是必须的,而SQL SERVER不一定
如ORACLE中: select 25 from dual
而SQL SERVER中: select 2
5

字符串连接
Oracle用|| 符号作为连接符,而SQL Server的连接符是加号:+ 。
Oracle查询如下所示:Select ‘Name’ || ‘Last Name’ From tableName
SQL Server查询如下:Select ‘Name’ + ‘Last Name

日期
Oracle取得日期和采用如下方式:SYSDATE
SQL Server则是这样的:GETDATE()
Oracle日期:Select sysdate from dual
SQL Server:Select getdate()

select * from product_component_version --查询Oracle数据库版本

实例(instance),他指的就是Oracle 的进程和内存。提到数据库(database)时,则是说保存数据的物理文件。可以从多个实例访问一个数据库,但是一个实例一次只能访问一个数据库。
————————————————
版权声明:本文为CSDN博主「事后诸葛亮」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zq9017197/article/details/5840714

https://github.com/xyp-hf/Oracle/blob/master/
https://xyp-hf.github.io/2017/10/27/第一节:Vue-js框架是什么,为什么选择它?/

SQL (Struct Query Language 结构化查询语言) 的分类 select 语句 (查询语句 DQL)
DDL (data define language 数据定义语言)
create table 建表
drop table 删表
alter table 改表

DML (data manapulation language 数据操作语言)
insert 插入
delect 删除
alter table 该表

TCL (transation control language 事物控制语句)
commit 提交
rollback 回滚
savepoiont 保存点

DCL (data control language 数据控制语句)
grant 授权
revoke 回收权限

使用sqlplus 登录oracle

sqlplus system/密码@别人的ip地址
sqlplus escmuser/FS7GM222@192.168.7.222:1521/epps

https://www.cnblogs.com/zhou__zhou/archive/2010/03/19/sqlplus.html

select userenv('lang') from dual;
select table_name from user_tables;
SELECT * FROM DBA_TABLES WHERE TABLE_NAME='TMP_TEST'
select text from user_source where name='GETMIN'
select * from dual;
SELECT SYSDATE FROM dual;
to_char(start_date,'yyyy-mm-dd hh24:mi:ss')
to_date('2008-08-08 20:08:08','yyyy-mm-dd hh24:mi:ss')

id 自增--序列.nextval

rowid

rownum

临时表,缓存表
https://www.cnblogs.com/kerrycode/p/3285936.html

package

存储过程

视图--create or replace view 视图名 as select语句;

事务

赋权,同义词

1.Oracle查询语句-from
如何从表中查询一个字段对应的内容 select 字段名 from 表名;
如何查询多个字段对应的内容 select 字段名1,字段名2,字段名3 from 表名;
查询 s_emp 表中所有的字段对应的内容 select * from s_emp;
sql 中的数学运算 + - * /
字符串的连接 Oracle 中字符串的拼接 使用 || ,如字符串 || 字符串 || 字符串 select first_name || last_name from s_emp;
NULL 值的处理 nvl(par1, par2) 当par1 为NULL 时会返回par2的值,否则返回 par1 本身
数据的排重 (重复的数据值留一份) distinct

2.Oracle查询语句-where字句
where字句的作用 限制表中数据的返回,符合where条件的数据被选中,不符合where条件的数据被过滤掉。
where的语法格式 select 字段名 from 表名 where 条件;
两个极限条件 1 = 1 恒等 永真 1 != 1 恒假 永假

数字类型的表单

字符类型的表达
常见的条件运算符 等于 = 不等于 != ^= <>

4.sql提供的条件运算符
表达闭区间的运算符 [a,b] where 字段名 between a and b;
表达一个字段的值 出现在某个列表内 where 字段名 in 列表;
空值判断运算符 除了 is null 运算符 其他运算符 对 NULL值判断无效
模糊查询运算符 where 字段 like '统配符' 统配串 中最关键 是 两个 统配符: - 代表任意一个字符 % 代表 0-n 个字符串
特例:
user_table 中有一个字段 table_name 代表表名
select table_name from user_tables;
找出所有的以 S_ 开头的表名
select table_name from user_tables where table_name like 'S_%'; (X)

要把 _ 处理成普通字符 不让他代表任意一个字符才行
所以应该这样写
select table_name from user_tables where table_name like 'S\_%' escape '\';
逻辑运算符 (多条件连接)
	与    where a and b;      其实就是把java中的 && 换成了 and
------------------------------------------------------------------------------------------
如:显示 s_emp 表中 每个员工的 id first_name salary 要求salary在[1400,2500]中
select id,first_name,salary from  s_emp where salary>=1400 and salary<=2500;

或 的逻辑运算符就是 把java中的 || 换成 or
------------------------------------------------------------------------------------------
如:查询s_emp 表的员工 在 31部门 或者在 41部门   或者在 50  最终显示 id  first_name dept_id
select id,first_name,dept_id from s_emp where dept_id=31 or dept_id=41 or dept_id=50;

 非             !        not 
------------------------------------------------------------------------------------------
对立面 
 =                       !=   <>  ^=     
 >                        <=
 <                       >= 
 between a and b         not  between  a  and  b 
 in                      not  in     ( where  id  not in (1,3,5)   id!=1  and id!=3 and id!=5)
 like                    not  like    
 is null                 is  not null 

 除了is null 之外,其他运算符 都要主要null值的问题

5.Oracle的排序
6.Oracle单行函数
单行函数:
针对sql语句影响的每一行 都做处理 并且针对每一行都会返回一个结果
sql语句影响多少行就返回多少个结果
组函数:
针对sql语句影响的所有行 只返回一个结果
无论sql影响多少行 只返回一个结果

单行函数:
select first_name,upper(first_name) name from s_emp where id=1;
select first_name,upper(first_name) name from s_emp where id=1;
select first_name,upper(first_name) name from s_emp where id=1;

组函数:
select count(first_name) cname from s_emp where id=1;
select count(first_name) canme from s_emp where id>1;
select  count(first_name) cname  from  s_emp where  id<1;

Oracle数据库中 处理字符串的单行函数
upper(par1) 变大写 如: select upper('hello') from dual;
lower(par2) 变小写 如: select lower('HEllo') from dual;

initcap(par1) 每个单词首字母变大写 如: select initcap('one world one dream') from dual;
length(par1) 求长度 如:select length('hello') from dual;
concat(par1,par2) 连接两个字符串 如: select concat('a','b') from dual;
nvl(par1,par2) nvl 可以处理任何类型 要求par1 和 par2 类型保持一致
substr(par1,par2,par3)
		par1	要处理的字符串或者字段
		par2	截取的位置 编号从1 开始        可是负数 -1 代表最后一个字符
		par3	截取的长度
		select substr('hello',0,2) from dual;
		select substr('hello',1,2) from dual;
		select  substr('hello',2,2)  from dual;

replace(par1,par2,par3)
     par1     要处理的字符串
	 par2     被替换的内容
	 par3     替换成什么
如:select replace('one' world one dream','one','two') from dual;

处理数字的函数
round(par1,par2)	四舍五入
	 par1      要处理的数字
	 par2      处理的精确 默认是0 可以省略
保留小数点后一位 看第二位小数
	select round(9.58,1) from dual;
对小数点前一位进行四舍五入
	select round(9.58,-1) from dual;
------------------------------------------------------------------------------------------
trunc(par1,par2) 截取函数
		  par1 	    要处理的数字
	 	  par2      处理的精度  默认是 0,可以省略
	select trunc(9.58) from dual;
	select trunc(12.88) from dual;
保留小数点后一位 不看第二位
select trunc(9.58,1) from dual;
对小数点前一位 进行截取
select trunc(9.58,-1) from dual;

格式显示函数
to_char(par1,par2)
	 	par1 要处理的数据,还可以处理日期
	 	par2 是显示格式 以字符串形式出现 可以省略 如果省略代表把某个类型变成 字符串类型 

		FM       格式的开头 是format格式的缩写 可以省略
		¥       美元符号
		L        本地货币符号 ¥
		9        小数点前面 代表 0-9 的任意数字
		         小数点后面 代表 1-9 的任意数字
		0        小数点前面代表 强制显示前导零 如 12345 => 012,234
		         小数点后面代表 0-9 的任意数字
		,	     千分位分隔符
		.		 小数点

		select salary,to_char(salary,'FM$099,999.99') from s_emp;
		select salary,to_char(salary,'FM$099,999.00') from s_emp;

		select to_char(12345.86,'$099,999.99') from dual;
		select to_char(12345.86,'$099,999.00') from dual;

		如果使用 L  则看的是 环境变量 NLS_LANG 
		select  to_char(12345.86,'L099,999.00') from dual;

 函数嵌套

7.Oracle多表查询
8.Oracle的外连接
外连接的特点
外连接的结果集 等于 内连接的结果集 加上 匹配不上的记录一个也不能少
(+) (+)的意思是 (+)所在的字段 对面的表的数据全部被匹配出来。
找出所有的普通员工?
select distinct m.id,m.first_name from s_emp e,s_emp m where e.manager_id(+) = m.id and e.manager_id is null;
内连接 符合连接条件的数据被选中 不符合的被过滤掉
等值连接 员工和对应的部门 部门和对应的地区
非等值连接 工资 和工资级别
自连接 谁是领导

外连接   外连接的结果集 等于 内连接的结果集 加上匹配不上的记录 
    (+)  (+)所在的字段的表的对面的表的数据全部被匹配出来  本质上使用null 记录     
    自连接     谁是普通员工
    等值连接   找出新增的部门
    非等值连接  找出超出工资统计范围的员工 

9.表连接的SQL99-标准
sql99 的内连接标准
语法格式:
from a表 join b 表 on 表的连接条件 where 过滤条件;
from a表 inner join b 表 on 表的连接条件 where 过滤条件;
sql99 外连接标准
语法格式:
a 表 left outer join b表 on 连接条件 where 过滤条件;
a 表 right outer join b表 on 连接条件 where 过滤条件;
a 表 full outer join b表 on 连接条件 where 过滤条件;
全外连接
全外连接 只是一个逻辑概念 全外连接的结果集 等于 左外连接的结果集 加上右外连接的结果集
然后排除重复的记录。

全外连接 在Oracle 中 是怎么实现的?
	全外连接 不是通过两端 加 (+) 实现的,而是通过  union   实现的
	union 是可以合并两个结果集 然后排重
	union  all    是 合并两个结果集 不排重 

select id from  s_emp  union  select id from s_emp;
select id from  s_emp  union  all select id from s_emp;

10.Oracle的组函数
组函数 是 对一组数据处理之后 只返回一个结果
常见的组函数
count(par1) 统计数据的个数
max(par1) 统计最大值
min(par1) 统计最小值
avg(par1) 统计平均值
sum(par1) 统计和

11.Oracle的分组
分组的概念
分组 就按照一定的标准 把数据分成若干部分
语法格式
select 字段
from 表名
where 条件
group by 分组标准 having 组函数的过滤条件
order by 排序标准 排序方式;
sql语句的执行顺序
from where group by having select order by

12.Oracle的子查询

13.Oracle的建表、删表、改表
建表
create table 表名(
字段名1 类型,
字段名2 类型,
字段名3 类型
);
------------------------------------------------------------------------------------------
类型: number 数字类型
varchar2(n) 变长字符串类型
char(n) 定长字符串
date 日期类型

删除表  drop  table  表名;
修改表
	删除某个字段
	alter  table  表名 drop  column  字段名
	如:
	alter   table  student100 drop  column sdate;

	增加一个字段
	alter  table  表名  add    字段名   类型;
	如:
	alter  table  student100 add  sdate  date;

14.DML-data-manipulation-language
插入语句 insert into
1.1.1 全字段插入 插入数据的顺序和 desc 表名之后的顺序相同
insert into 表名 values(值1,值2,值3);
commit;

删除语法
	delete  from  表名  where 条件;
	commit;

修改数据
	update  表名  set 字段名=值  where 条件;
	update  表名   set 字段名=值,字段名2=值2  where 条件;
	commit;

15.TCL-(transaction-control-language)
事务的概念:事务又叫做交易 开发中希望把多个sql操作 看成一个逻辑整体,这些sql 要求同时成功或者同时失败。
可以完成一个事务的语句:commit; 提交 确认 rollback; 回滚 撤销
事务四大特性 (了解)
原子性 事务中的语句是一个逻辑整体不可分割
一致性 同时成功 同时失败 状态要保持一致
隔离性 一个事务中的操作 在没有提交之前 数据的变化 对另外一个事务而言不可见。
持久性 状态的持久
保存点
引入它就是为了打破事务的原子性
insert into student100 values(1,'test1','111',sysdate);
savepoint a;
insert into student100 values(2,'test2','222',sysdate);
savepoint b;
insert into student100 values(3,'test3','3333',sysdate);
rollback to b;
commit;

16.Oracle中的日期类型
默认的日期类型 dd-MON-yy 表现默认是两年 实际上存储了四位
如何按照指定格式 显示日期
to_char(par1,par2) par1是要处理的日期
par2 日期格式 日期格式
yyyy 四位年 mm 月 dd 日
hh 12小时制 hh24 24小时制 mi 分钟 ss 秒
day 星期几 MON 英文月的缩写 month 英文月的全写
------------------------------------------------------------------------------------------
select id,first_name,to_char(start_date,'yyyy-mm-dd hh24:mi:ss') start_date from s_emp order by start_date;

如何插入一个日期
	之前学过  null    和 sysdate   sysdate 代表系统时间 
	如何插入未来的时间  或者 过去的时间点
	2008-08-08 20:08:10
	insert into  student100(id,sdate) values(3,'08-AUG-08');
	默认只能放入 年 月 日,时分秒信息是  0 
	如果需要时分秒信息 则使用  to_date 就可以了
	to_date(par1,par2)   par1 是一个日期字符串   par2 是日期的格式 
	insert into  student100(id,sdate) values(4,to_date('2008-08-08 20:08:08','yyyy-mm-dd hh24:mi:ss'));
	select  id,to_char(sdate,'yyyy-mm-dd hh24:mi:ss') from  student100;
	2012-12-22  23:59:59

日期的调整
	select  to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;
	调整一天   默认按照天为单位

	select  to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),
	        to_char(sysdate+1,'yyyy-mm-dd hh24:mi:ss') from dual;

	调整一个小时的一半   默认按照天为单位
	select  to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),
	        to_char(sysdate+1/(24*2),'yyyy-mm-dd hh24:mi:ss') from dual;
	select  to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),
	        to_char(sysdate-1/(24*2),'yyyy-mm-dd hh24:mi:ss') from dual;

特殊的调整
	按照月为单位 调整 
	add_months(par1,par2)   par1 要调整的日期    par2 调整的月数  可以是负数
	select  to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),
	        to_char(add_months(sysdate,1),'yyyy-mm-dd hh24:mi:ss') from dual;

	select  to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),
	        to_char(add_months(sysdate,-1),'yyyy-mm-dd hh24:mi:ss') from dual;

	对日期进行 截取     默认以天为单位截取 
	select  to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),
	        to_char(trunc(sysdate),'yyyy-mm-dd hh24:mi:ss') from dual; 
	 
	select  to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),
	        to_char(round(sysdate),'yyyy-mm-dd hh24:mi:ss') from dual;  

	select  to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),
	        to_char(trunc(sysdate,'hh'),'yyyy-mm-dd hh24:mi:ss') from dual; 

	select  to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),
	        to_char(trunc(sysdate,'mm'),'yyyy-mm-dd hh24:mi:ss') from dual; 

	select  to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),
	        to_char(trunc(sysdate,'yy'),'yyyy-mm-dd hh24:mi:ss') from dual;	        

给你一个时间 获取到这个时间对应的月的最后的一天的最后一秒对应的时间点
	select  to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),
	        to_char(add_months(trunc(sysdate,'mm'),1)-1/(24*60*60),
	                 'yyyy-mm-dd hh24:mi:ss') from dual; 

17.Oracle的约束
约束--约束是 对数据库表中字段加的限制,有了约束之后 可以让我们的数据更加准确 和 完整
约束种类
主键约束 primary key pk
如果给表的某个字段加了主键约束 则这个字段的值 不能重复,并且字段的值不能为 null.
一张表只能有一个主键。
唯一性约束 unique uk
如果给表的字段加了唯一性约束 则 这个字段的值不能重复。
注意 唯一性约束 无法区分两个 null 值
非空约束 not null nn
如果给表的字段增加了 非空约束 则这个字段的值不能是 null 值
检查约束 check ck
如果给表的字段增加了 检查约束 则这个字段必须符合检查条件 符合检查条件的数据
才能进入数据库。
外键约束 references foreign key fk

约束的实现
	  列级约束:在定义表的某一列时  直接在这一列的后面加约束限制 叫列级约束。
	  表级约束:在定义完表的所有列之后 再选择某些列加约束限制。

主键的列级约束实现
	  建立一张 订单表  myorder   
	  id      number    pk
	  oname  varchar2(30)
	  create   table  myorder(
	         id    number   primary  key,
	         name varchar2(30) 
	   );
	  insert into myorder  values(1,'test1');
	  insert into myorder  values(1,'test1')
	  *
	 ERROR at line 1:
	 ORA-00001: unique constraint (SYSTEM.SYS_C007619) violated
	 如果不给约束起名字  则系统会自动给约束进行一个命名  保证约束的名字不重复
	 但是这个名字 不方便记忆  并且 不方便排错 以及以后的约束管理。


如何给约束命名
	 constraint    约束的名字     约束对应的英文
	 约束的名字构成:  表名_字段名_约束简写


检查约束 需要把检查约束的条件写入()
	在上面的表的基础上 加一个字段 omoney number 要求omoney 大于35 
	------------------------------------------------------------------------------------------
	drop   table    order100;
	create  table  order100(
	        id     number  constraint  order100_id_pk  primary key,
	        ono  varchar2(30)  constraint  order100_ono_uk  unique,
	        odate  date   constraint  order100_odate_nn  not null,
	        omoney   number   constraint  order100_omoney_ck  check(omoney > 35)        
	 );


主键的表级约束实现
	create   table    order200(
	       id    number,
	       ono   varchar2(30),
	       odate  date,
	       omoney   number , constraint   order200_id_pk   primary  key(id)
	 );

	表级约束最大的优势就在于可以做联合约束
	create   table    order300(
	       id    number,
	       ono   varchar2(30),
	       odate  date,
	       omoney   number , constraint   order300_idono_pk   primary  key(id,ono)
	 );    
	1    'a'
	1    'b'


	建立一张 订单表 叫 order1001  
	 id     number     pk
	 ono    varchar2(30)  uk
	 odate  date       nn     列级约束 (因为不支持表级)
	 omoney   number    ck   要求大于35 
	 除了  odate之外 其它的字段需要使用 表级约束   
	 create table   order1001(
	        id   number,
	        ono    varchar2(30),
	        odate   date   not null,
	        omoney   number, 
	        constraint   order1001_id_pk  primary  key(id),
	        constraint   order1001_ono_uk  unique(ono),
	        constraint   order1001_omoney_ck  check(omoney>35)
	  );

18.Oracle的外键
概念
涉及到两张表 一张叫 父表(主表) 另一张叫子表(从表)
子表:定义了外键的表 一定是子表
子表中外键字段的取值 要受限于父表中某个字段的取值,要么取父表字段对应的值 要么取null值。
语法 考虑外键

	建表
		 先建父表   后建子表  除非先不考虑主外键关系(先建表 后加外键)
		 create table   parent100(
		         id        number    constraint  parent100_id_pk   primary  key,
		         name   varchar2(30) 
		 );       
		 create  table   child100(
		         id         number   constraint  child100_id_pk    primary key,
		         name   varchar2(30),
		         fid        number   constraint   child100_fid_fk   references  parent100(id) 
		 );
		 ------------------------------------------------------------------------------------------
		 1.2.2  插入数据 
		 先插入父表对应的数据  后插入子表对应的数据    除非子表的外键值 使用 null 值 
		 insert  into  parent100 values(1,'p1');
		 insert  into   parent100 values(2,'p2');
		 commit;
		 insert into  child100  values(1,'c1',1);    
		 commit;
		 ------------------------------------------------------------------------------------------
		 1.2.3  删除数据 
		 先删除子表中对应的数据  再删除父表中的数据   除非你使用级联 
		 delete   from  parent100 where id=1; 
		 delete   from  parent100 where id=2; 
		 ------------------------------------------------------------------------------------------
		 1.2.4 删除表 
		 先删子表 后删父表 除非使用 cascade constraints
		 drop  table  parent100;
		 ------------------------------------------------------------------------------------------
		 ERROR at line 1:
		 ORA-02449: unique/primary keys in table referenced by foreign keys
		 cascade  constraints   表示先解除主外键关系  这样可以删表时不考虑顺序 
		 drop  table  parent100  cascade  constraints; 
	级联
		   on delete  cascade    级联删除  
		   on  delete set null     级联置空
		   把上面的操作 加在外键上 	

	先建表 后加约束 (外键)
		  create    table   emp100(
		     id       number   constraint  emp100_id_pk   primary key,
		     name   varchar2(30),
		     salary   number,
		     dept_id    number
		   ); 

		  alter table   emp100  add  constraint   emp100_dept_id_fk   foreign   key(dept_id) references    dept100(id);

19.Oracle数据库中的其它对象
序列 sequence
1.1 作用
用来产生主键值的 保证产生不重复的数字
------------------------------------------------------------------------------------------
1.2 如何创建序列
create sequence 序列名;
序列名 表名_字段名_seq;
------------------------------------------------------------------------------------------
1.3 如何使用
序列名.nextval 偶尔使用 序列名.currval
举例:
create table testseq(
id number constraint testseq_id_pk primary key,
name varchar2(30)
);
create sequence testseq_id_seq;
insert into testseq values(testseq_id_seq.nextval,'test'||testseq_id_seq.currval);
------------------------------------------------------------------------------------------
1.4 删除序列
drop sequence 序列名;

索引 index (了解)	   
		2.1  作用 
	    加速查询的  
	    3亿   
	    不使用索引     500s 
	    使用索引         0.01s   
		------------------------------------------------------------------------------------------  
	    2.2  原理 
	    索引 底层使用树状结构   通过消耗大量的空间 和  时间 来达到加速查询的目的。
		------------------------------------------------------------------------------------------
	    2.3  如何建立 
	    create  index   索引名    on  表名(字段名);
	    注意不要在 主键 和 唯一性字段上 加索引  因为系统已经自动建立过索引了。
	    create  table  emp222   as select id,first_name name,salary from s_emp;                   
	    set timing on;
	    create  index    emp222_name_index    on emp222(name);
		------------------------------------------------------------------------------------------
	    2.4  删除索引
	    drop  index   索引名;
	    drop   index  emp222_name_index;

视图 view
	     3.1  本质 
	     视图的本质 就是一条sql 语句的select语句。
	     相对于 视图对应的数据而言  视图本身的空间可以忽略不计。
		 ------------------------------------------------------------------------------------------
	     3.2 语法 
	     create   or   replace    view  视图名   as  select语句;
		 ------------------------------------------------------------------------------------------
	     3.3  举例
	     create   or   replace    view  myview  as   select  id,first_name name,salary  from s_emp;
		 ------------------------------------------------------------------------------------------
	     3.4 作用 
	     可以对同一份物理数据 作出不同表现  可以用来做权限的管理 
	     可以用来简化子查询 

20.Oracle数据库分页技术
分页
rownum 行编号 这个字段叫伪列
------------------------------------------------------------------------------------------
select rownum,first_name,salary from s_emp;

		一页显示 11 条数据  显示第一页数据
		select  rownum,first_name,salary  from  s_emp  where  rownum < 12; 


		一页显示 11 条数据  显示第二页数据
		select  rownum,first_name,salary  from  s_emp  where  rownum < 23 and rownum > 11;


		通过子查询 把rownum  变成一个普通的字段
			select r,first_name,salary 
					from (select  rownum  r,first_name,salary  from  s_emp  
		         			where  rownum < 23 ) where r > 11;	


		一页显示 11 条数据  显示第三页数据
			select r,first_name,salary 
					from (select  rownum  r,first_name,salary  from  s_emp  where  rownum < 3*11+1 ) 
									where r > (3-1)*11;

		按照某个字段排序之后 显示 第几页数据
		按照salary  排序  显示  first_name  salary 
		select   first_name,salary from  s_emp    order by salary;


		按照salary  排序 一页显示11 条数据 显示 第二页数据
		select * from(select rownum r,first_name,salary from 
		    (select   first_name,salary from  s_emp    order by salary) where rownum < 2*11+1
		)where r > (2-1)*11 ;


		最内层:负责排序
		中间层:负责编号   和 起别名  以及部分数据的过滤
		最外层:负责使用别名进行过滤 

		按照salary  排序 一页显示11 条数据 显示 第三页数据   
		select * from(select rownum r,t.* from 
		    (select   first_name,salary from  s_emp    order by salary) t where rownum < 3*11+1
		 )where r > (3-1)*11 ;

21.PLSQL-过程化
PLSQL(procedure language / struct query language)
PLSQL 过程化sql,就是可以像写java程序一样,去完成数据库的操作
jdbc 使用java程序访问数据库
plsql 简介
plsql 是在标准sql的基础上 增加了 过程化处理语言,它是在客户端操作服务端的一门语言
PLSQL的特点
结构化 模块化编程
良好的可扩展性
良好的可维护性
提高了程序的性能
不便于向异构数据库移植
plsql扩展了sql那些内容
变量和数据类型
控制语句 --- 分支语句 循环语句 goto
过程和函数
对象和方法
plsql的程序结构
declare
/* 申明区
用来定义变量 和 类型的 /
begin
/
执行区
用来执行plsql语句 和 sql语句的
*/
exception
-- 异常处理区
-- 当程序执行出错自动进入这个区处理
end;
/
第一个plsql程序
begin
dbms_output.put_line('hello plsql!');
end;
/

	执行 plsql程序
		命令行下的 sqlplus
		图形界面工具 plsqldeveloper sqldeveloper
		无论使用 哪种开发工具 必须设置 set serveroutput on;

	标识符
		给变量 类型 过程 函数 游标等命名的

	变量
		9.1 语法
		declare
			变量名 类型;
		begin
		类型:
			基本类型 number varchar2(n) char(n) date boolean binary_integer
			复合类型 record table cursor
			参考类型 ref
			大数据类型 BLOB CLOB FILE 一般使用,使用字符串存储路径即可

		------------------------------------------------------------------------------------------
		9.2 举例
		定义两个变量 分别是 数字类型 和 字符串类型
		declare
			var_id number;
			var_name varchar2(30);
		begin
			dbms_output.put_line(var_id||':'var_name);
		end;
		/
		变量没有赋值 则值一定是null
		------------------------------------------------------------------------------------------
		9.3 变量的赋值
		declare
				var_id number:=123;
				var_name varchar2(30):='zhangsan';
		begin
				dbms_output.put_line(var_id||':'||var_name);
		end;
		/
		------------------------------------------------------------------------------------------
		9.4 定义两个变量 分别 和 s_emp 表中的id 和first_name对应的类型保持一致
		然后分别给两个变量赋值成 1 testcarmen 最后打印这两个变量饿值
		declare
			id number(7);
			first_name varchar2(25);
		begin
			id:=1;
			first_name:='testcarmen';
			dbms_output.put_line(id||':'||first_name);
		end;
		/
		------------------------------------------------------------------------------------------
		9.5 可以使用 表名.字段名 % type 来获取表中字段对应的类型
		declare
		       var_id        s_emp.id%type;
		       first_name    s_emp.first_name%type;	
		begin
			var_id:=2;
			/* 使用sql 语句 给变量 first_name 赋值 */
			select first_name into first_name from s_emp where id=var_id;
		end;
		/
		------------------------------------------------------------------------------------------
		9.6 变量的修饰
		constant 代表修饰成常量
		not null 修饰成非空

		declare
			var_id constant s_emp.id%type:=1;
			first_name s_emp.first_name%type not null:='abc';
		begin
			-- var_id:=1;
			dbms_output.put_line(var_id||':'||first_name);
		end;
		/

22.PLSQL 变量
变量
1.1 使用plsql 定义两个变量 分别和 s_emp 表中的 id 和 first_name 的类型保持一致,并且给 和 id 类型相同 的变量赋值成 10,
使用 sql 语句给 first_name类型相同的那个变量赋值 并 输出这个变量的值。

	declare
	    /* 获取变量名 表名.字段名%type; */
	    var_id s_emp.id%type;
	    var_name s_emp.first_name%type;
	begin
	    var_id:=10;
	    select  first_name   into  var_name  from  s_emp  where id=var_id;
	    dbms_output.put_line(var_name); 
	end;
	/ 
	set serveroutput on;
	1.2 如果想把 id = 10 的员工的 first_name salary dept_id 这三个数据查询出来
	declare
	       /* 获取变量名 表名.字段名%type */
	       var_name s_emp.first_name%type;
	       var_salary s_emp.salary%type;
	       var_dept_id s_emp.dept_id%type;
	begin
	        select first_name,salary,dept_id into var_name,var_salary,var_dept_id from s_emp where id=10;
	        dbms_output.put_line(var_name||':'||var_salary||':'||var_dept_id);
	end;
	/
	1.3使用 recod 类型,可以组织多个变量
	recode 类型的语法 ----- 定义一个recode 类型

	declare
		type 类型名 is record(
	        字段名 类型,
	        字段名 类型,
	        字段名 类型
		);
	    变量名 类型名;
	begin
	declare
	     type emptype is record(
	      var_name    s_emp.first_name%type,
	      var_salary   s_emp.salary%type,
	      var_dept_id   s_emp.dept_id%type
	     );
	     /* 使用上面的emptype 定义一个变量 */
	     var_emp smptype;
	begin
		select first_name,salary,dept_id into var_emp
		      from s_emp where  id=10;
		dbms_output.put_line(var_emp.var_name||':'||var_emp.var_salary||':'||var_emp.var_dept_id);

	end;
	/
	把s_dept 表中的所有字段 包装成一个record 类型,然后使用sql 把 id = 50 的信息存入这个变量中 打印这个变量的信息

	declare
	        TYPE depttype  IS  RECORD(
	                id     s_dept.id%type,
	                name  s_dept.name%type,
	                region_id  s_dept.region_id%type   
	        );  
	        var_dept   depttype;
	begin 
	        select  *  into  var_dept  from  s_dept where id=50;
	        dbms_output.put_line(var_dept.id||':'||var_dept.name);         
	end;
	/ 
	1.4 如何把 s_epm 表中所有的字段 包装成一个record类型 然后 把id=25 所有的员工信息放入这个类型对应的变量中,打印 其中的 id first_name salary
	表名%rowtype 实际上获取的是 字段名 和 字段顺序 完全和表头相同的一个记录类型

	declare
	     var_emp s_emp%rowtype;
	begin
		select * into var_emp from s_emp where id=25;
		dbms_output.put_line(var_emp.id||':'||var_emp.first_name||':'||var_emp.salary);
	end;
	/
	1.5 table类型
	类似于java数组 或者Map<Integer,Object>

	1.5.1 语法
	TYPE 类型名 is table of 元素类型 index by binary_integer;
	变量名 类型名;
	变量名(下标) 下标任意
	变量名(下标):=值;
	1.5.2 定一一个装 数字的 table类型 使用这个类型定义一个变量 用来存放 9 5 2 7 0 这个五个数字,最后显示下标为 1 的数据。
	declare
	    type numstyle is table of number index by binary_integer;
		var_nums numstype;
	begin
	    var_nums(-1):=9;
	    var_nums(0):=5;
	    var_nums(1):=2;
	    var_nums(2):=7;
	    var_nums(3):=0;
		dbms_output.put_line(var_nums(1));

	end;
	/
	1.5.3 下标连续时 如何遍历 table 类型的变量
	declare
		type numstype is table of number index by binary_integer;
		var_nums numstype;
		var_index binary_integer:=-1;
	begin
		var_nums(-1):=9;
		var_nums(0):=5;
	    var_nums(1):=2;
	    var_nums(2):=7;
	    var_nums(3):=0;
	    dbms_output.put_line(var_nums(var_index));
	    var_index:=var_index+1;
	    dbms_output.put_line(var_nums(var_index));
	    var_index:=var_index+1;
	    dbms_output.put_line(var_nums(var_index));
	    var_index:=var_index+1;
	    dbms_output.put_line(var_nums(var_index));
	    var_index:=var_index+1;
	    dbms_output.put_line(var_nums(var_index));
	end;
	/
	1.5.4 下标不连续时 如何遍历?
	迭代器的核心思想
		可以根据上一个元素的信息 获取到 下一个元素相关的信息
	变量名.first()	获取最小的下标
	变量名.next(下标) 根据一个元素的下标,可以获取下一个元素的下标
	变量名.last()    获取最大的下标
	变量名.count()   获取元素个数
	declare
		type numstyle is table of number index by binary_integer;
		var_nums numstyle;
		var_index binary_interger:=-1;
	begin
	    var_nums(-1):=9;
	    var_nums(0):=5;
	    var_nums(11):=2;
	    var_nums(2):=7;
	    var_nums(3):=0;
	    var_index:=var_nums.first();
	    dbms_output.put_line(var_nums(var_index));
	    var_index:=var_nums.next(var_index);
	    dbms_output.put_line(var_nums(var_index));
	    var_index:=var_nums.next(var_index);
	    dbms_output.put_line(var_nums(var_index));
	    var_index:=var_nums.next(var_index);
	    dbms_output.put_line(var_nums(var_index));
	    var_index:=var_nums.next(var_index);
	    dbms_output.put_line(var_nums(var_index));
		dbms_output.put_line(var_nums.count());
	end;
	/
	1.6、变量的作用域 和 可见性
	全局不能访问 局部 局部可以访问全局
	declare
		var_m number:=1;
	begin
		var_n number:=100;
	end;
	/
	如果需要全局访问局部可以使用标记
	<<abc>>
	declare
		var_m number:=1;
	begin
			declare
					var_m number:=100;
			begin
					dbms_output.put_line(var_m);
					dbms_output.put_line(abc.var_m);
			end;
	end;
	/

23.PLSQL 控制语句
控制语句
1.1 分支语句
1.1.1 语法
------------------------------------------------------------------------------------------
if a > b then

end if;
------------------------------------------------------------------------------------------
if a > b then

    else

end if;
------------------------------------------------------------------------------------------
if a > b then

elsif a > c then

elsif a > c then

elsif a > d then

end if;
------------------------------------------------------------------------------------------
if a > b then

elsif a > c then

else

end if;
------------------------------------------------------------------------------------------
1.1.2  练习
定义两个整数变量并赋值,然后打印两个变量的最大值
declare
	var_x number:=20;
	var_y number:=30;
begin
	if var_x < var_y then
		dbms_output.put_line(var_y);
	else
		dbms_output.put_line(var_x);
	end if;
end;
/
1.1.3 练习
定义三个整数变量,并赋值,然后打印三个变量的最大值 
declare
	var_x number:=20;
	var_y number:=30;
	var_z number:=40;
begin
	if var_x < var_y then
		if var_y < var_z then
		else
		end if;
	else
		if var_x < var_z then
		else
		end if;
	end if;
end;
/
------------------------------------------------------------------------------------------
declare
		var_x number:=20;
		var_y number:=30;
		var_z number:=40;
		var_max number;
begin
		var_max:=var_z;
		if var_max < var_x then
			var_max:=var_x;
		end if;
		if var_max < var_y then
			var_max:=var_y;
		end if;
		dbms_output.put_line(var_max);
end;
/
1.1.4   null 值的判断
declare
	var_x number;
	var_y number;
begin
	if var_x < var_y then
		dbms_output.put_line('var_x < var_y');	
	elsif  var_x > var_y then
		dbms_output.put_line('var_x > var_y');
	elsif  var_x = var_y then
		dbms_output.put_line('var_x = var_y');
	elsif var_x is null and var_y is null then
		dbms_output.put_line('var_x is null and var_y is null');
	else
		dbms_output.put_line('other');
	end if;
end;
/
------------------------------------------------------------------------------------------
declare
      var_x   number;
      var_y   number;
begin
      if  var_x < var_y  then 
           dbms_output.put_line('var_x < var_y');
      end if;  
      if  var_x > var_y  then
           dbms_output.put_line('var_x > var_y');
      end if;
      if  var_x =  var_y  then 
            dbms_output.put_line('var_x = var_y');
      end if;
      if  var_x  is  null and var_y  is  null  then 
            dbms_output.put_line('var_x  is  null and var_y  is  null');  
      end if;    
end;
/
1.2 循环语句
1.2.1  简单循环
loop
	---循环的代码
end loop;
1.2.2  如何结束一个循环 循环中出现下面的语句之一可结束循环
exit when 结束循环的条件;
------------------------------------------------------------------------------------------
if 结束循环的条件 then
   exit;
end if;
1.2.3 使用简单循环 把一个变量的值 从1 输出到 10
declare
	var_i number:=1;
begin
	loop
		dbms_output.put_line(var_i);
		exit when var_i=10;
		var_i:=var_i+1;
	end loop;
end;
/
------------------------------------------------------------------------------------------
declare
      var_i   number:=1;
begin
      loop
             dbms_output.put_line(var_i);
             if   var_i=10  then 
                     dbms_output.put_line('game over');
                     exit;
             end if; 
             var_i:=var_i+1;
      end loop;
end;
/
1.2.4 while 循环
while 循环条件 loop
	--- 循环语句
end loop;
------------------------------------------------------------------------------------------
把一个变量的值 从 1 输出 到 10
declare
	var_i number:=1;
begin
	while var_i <= 10 loop
		dbms_output.put_line(var_i);
		var_i:=var_i+1;
	end loop;
end;
/
------------------------------------------------------------------------------------------
把一个变量的值 从 10 输出 到 1
declare
	var_i number:=10;
begin
	while var_i > 0 loop
		dbms_output.put_line(var_i);
		var_i:=var_i-1;
	end loop;
end;
1.2.5 for 循环
for 变量 in 区间 loop

end loop;
闭区间的表达是 a..b
注意: 不用对变量 进行加操作 这个变量其实只能读 不能写
------------------------------------------------------------------------------------------
举例:
begin
	for var_i in 1..10 loop
		dbms_output.put_line(var_i);
	end loop;
end/
------------------------------------------------------------------------------------------
反向输出 在in 后面加上reverse即可
begin
	for var_i in reverse 1..10 loop
		dbms_output.put_line(var_i);
	end loop;
end;
/
------------------------------------------------------------------------------------------
for循环中自定义的变量只能读不嫩写
begin
     for  var_i   in  reverse 1..10  loop
            dbms_output.put_line(var_i);
            -- var_i:=100;
            exit  when   var_i=5;
     end loop;
end;
/  
1.2.6  循环的嵌套
declare
	var_x number;
	var_y number;
begin
	var_x:=1;
	while var_x < 4 loop
		var_y:=y;
			while var_y < 4 loop
				dbms_output.put_line(var_y);
				var_y:=var_y+1;
			end loop;
		var_x:=var_x+1;
	end loop;
end;
/
因为 exit  退出的是当前循环 就是内层循环 所以 输出三次 1  2 
------------------------------------------------------------------------------------------
  declare
    var_x    number;
    var_y    number;
 begin
        var_x := 1;
        while  var_x < 4  loop
               var_y:=1;
               while  var_y  <  4  loop
                      dbms_output.put_line(var_y);
                      if  var_y = 2  then
                            exit;
                      end if; 
                      var_y:=var_y+1;
               end loop;
               var_x:=var_x+1;
        end loop; 
 end;
 / 
------------------------------------------------------------------------------------------
 declare
        var_x    number;
        var_y    number;
 begin
        var_x := 1;
        while  var_x < 4  loop
               var_y:=1;
               while  var_y  <  4  loop
                      dbms_output.put_line(var_y);
                      if  var_y = 2  then
                            var_x:=4;
                            exit;
                      end if; 
                      var_y:=var_y+1;
               end loop;
               dbms_output.put_line('sha che .....');
               var_x:=var_x+1;
        end loop; 
 end;
 / 
------------------------------------------------------------------------------------------
 declare
        var_x    number;
        var_y    number;
 begin
        var_x := 1;
        <<outerloop>>
        while  var_x < 4  loop
               var_y:=1;
               while  var_y  <  4  loop
                      dbms_output.put_line(var_y);
                      if  var_y = 2  then
                            exit outerloop;
                      end if; 
                      var_y:=var_y+1;
               end loop;
               dbms_output.put_line('sha che .....');
               var_x:=var_x+1;
        end loop; 
 end;
 / 
1.3 控制语句 ------ goto 语句 (了解)
1.3.1 语法
goto 标签名;
------------------------------------------------------------------------------------------
1.3.2 练习
declare
	var_x number;
begin
	var_x:=-1;
	<<myloop>>
	if var_x < 11 then
		dbms_output.put_line(var_x);
		var_x:var_x+1;
		goto myloop;
	end if;
end;
/
1.3.3  练习 使用goto结束外层循环
begin
	<<outerloop>>
	for var_x in 1..3 loop
		for var_y in 1..3 loop
			dbms_output.put_line(var_y);
			if var_y = 2 then
				exit outerloop;
			end if;
		end loop;
	end loop;
end;
/
------------------------------------------------------------------------------------------
使用goto 结合标签 结束多重循环 必须放在代码块上,如果下面没有代码块补上null
    begin
        for var_x  in 1..3 loop
               for var_y in 1..3 loop
                      dbms_output.put_line(var_y);
                      if var_y = 2 then 
                             goto  outerloop;
                      end if;
               end loop;
        end loop;
         <<outerloop>>  
         dbms_output.put_line('game over');
	end;
	/
------------------------------------------------------------------------------------------
    begin
        for var_x  in 1..3 loop
               for var_y in 1..3 loop
                      dbms_output.put_line(var_y);
                      if var_y = 2 then 
                             goto  outerloop;
                      end if;
               end loop;
        end loop;
         <<outerloop>>  
         null;
	end;
	/

24.PLSQL 游标
游标 cursor
1.1 作用
用来存放多条数据的一个结果集
1.2 游标的使用步骤
使用步骤
定义游标
declare
cursor 游标名 is select语句;
begin
打开游标
open 游标名;
提取数据 操作数据
fetch 游标名 into 变量
关闭游标
close 游标名;
1.3 举例
查询 s_emp表中 id first_name salary 放入一个游标中 然后提取游标中前两条数据并进行打印。

		declare
		    cursor empcursor is select id,first_name,salary from s_emp;
		    type emptype is record(
		        id s_emp.id%type,
		        first_name s_emp.first_name%type,
		        salary s_emp.salary%type
		    );
		    var_emp emptype;
		begin
		    oper empcursor;
		    fetch empcursor into var_emp;
		    dbms_output.put_line(var_emp.id||':'||var_emp.first_name||':'||var_emp.salary);
		    fetch  empcursor into  var_emp;   
		    dbms_output.put_line(var_emp.id||':'||var_emp.first_name||':'||var_emp.salary);  
		    close empcursor;
		end;
		/
		------------------------------------------------------------------------------------------
		   declare
		      cursor  empcursor is  select id,first_name,salary from s_emp;  
		      var_emp   empcursor%rowtype;
		       begin
		      open  empcursor;
		      fetch  empcursor into  var_emp;
		      dbms_output.put_line(var_emp.id||':'||var_emp.first_name||':'||var_emp.salary); 
		      fetch  empcursor into  var_emp;   
		      dbms_output.put_line(var_emp.id||':'||var_emp.first_name||':'||var_emp.salary);  
		      close  empcursor;   
		       end;
		       /  
	1.4 如何提取游标中所有的数据
		游标的属性
		游标名%found      当提取游标数据时  如果提取到了新数据 则这个属性返回true   如果没有提取到
		      新数据 则这个属性返回false。但这个属性使用有两个前提 第一游标必须处于打开状态 否则返回
		      非法游标  第二 游标必须fetch  否则这个属性返回 null值。
		游标名%notfound     当提取游标数据时  如果提取到了新数据 则这个属性返回false   如果没有提取到
		      新数据 则这个属性返回true。但这个属性使用有两个前提 第一游标必须处于打开状态 否则返回
		      非法游标  第二 游标必须fetch  否则这个属性返回 null值。

		简单循环 结合notfound属性
		declare
		    cursor  empcursor is  select id,first_name,salary from s_emp;  
		    var_emp   empcursor%rowtype;
		begin
		    open empcursor;
		    loop
		        fetch empcurror into var_emp;
		        /* 提取不到新数据时 结束循环 */
		        exit when epmcursor%notfound;
		        dbms_output.put_line(var_emp.id||':'||var_emp.first_name||var_emp.salary);
		    end loop;
		    close empcursor;
		end;
		/
		------------------------------------------------------------------------------------------
		把上面的游标遍历 改成 使用 while 循环  结合 found 属性遍历
		   declare
		      cursor  empcursor is  select id,first_name,salary from s_emp;  
		      var_emp   empcursor%rowtype;
		   begin
		          open  empcursor;
		          fetch  empcursor into  var_emp;   
		          while  empcursor%found loop        
		                 dbms_output.put_line(var_emp.id||':'||var_emp.first_name||':'||var_emp.salary);  
		                 fetch  empcursor into  var_emp;
		          end  loop;
		          close  empcursor;   
		   end;
		   / 
		------------------------------------------------------------------------------------------
		for 询函 遍历游标
		for循环又叫智能循环 它可以自动定义变量 自动打开游标 自动提取数据 自动关闭游标

		   declare
		          cursor  empcursor is  select id,first_name,salary from s_emp;  
		   begin
		          for  var_emp in empcursor  loop        
		                 dbms_output.put_line(var_emp.id||':'||var_emp.first_name||':'||var_emp.salary);  
		          end  loop;   
		   end;
		   / 



	1.5 游标的其它属性
		游标名 % isopen   判断游标是否处于打开状态  打开的游标返回  true   关闭的游标返回false.
	    注意打开的游标不能再打开   关闭的游标不能再关闭。

		游标名 % rowcount   游标指针偏移量  (了解)
	    游标必须打开 否则报错   游标指针默认在第一条数据之前
	1.6 带参游标
		定义游标时 可以给游标 设计参数
		游标的参数 可以在游标对应的查询语句中使用
		只要在打开游标时 传入实参即可
		注意:plsql 中 参数不能加长度修饰 但是可以使用%type

		   declare
		          cursor  empcursor(var_id   s_emp.id%type) is  select id,first_name,salary 
		                  from s_emp where  id>var_id;  
		          var_emp   empcursor%rowtype;
		   begin
		          open  empcursor(20);
		          loop        
		                 fetch  empcursor into  var_emp;   
		                 /* 提取不到新数据时 结束循环  */
		                  exit  when  empcursor%notfound; 
		                 dbms_output.put_line(var_emp.id||':'||var_emp.first_name||':'||var_emp.salary);  
		          end  loop;
		          close  empcursor;   
		   end;
		   /  
		------------------------------------------------------------------------------------------
		 for 循环能否 遍历带参游标  
		 declare
		        cursor  empcursor(var_id   s_emp.id%type) is  select id,first_name,salary 
		                from s_emp where  id>var_id;  
		 begin
		        for   var_emp  in  empcursor(15)   loop
		                dbms_output.put_line(var_emp.id||':'||var_emp.first_name);
		        end  loop;
		 end;
		   /  
	1.7 把每个员工的 名字 和 对应部门编号 以及 部门的名字 放入一个游标中
		然后提取这个游标中的所有数据 打印
		declare
		         cursor   empdeptcursor  is  select   first_name,dept_id,name from 
		                s_emp,s_dept where dept_id=s_dept.id;
		  begin
		         for  var_t    in  empdeptcursor  loop
		                dbms_output.put_line(var_t.first_name||':'||var_t.dept_id||':'||var_t.name);
		         end loop;                 
		  end;
		  / 
		------------------------------------------------------------------------------------------
		把每个员工的 员工编号 名字  和  对应部门编号  以及 部门的名字 放入一个游标中 然后提取这个游标中的所有数据 打印 

		  declare
		         cursor   empdeptcursor  is  select  s_emp.id eid, first_name,dept_id,name,s_dept.id did from  s_emp,s_dept where dept_id=s_dept.id;
		  begin
		         for  var_t    in  empdeptcursor  loop
		                dbms_output.put_line(var_t.eid||':'||var_t.first_name||':'||var_t.dept_id
		                ||':'||var_t.name);
		         end loop;                 
		  end;
		  / 

25.PLSQL中如何使用sql?
1、PLSQL中如何使用sql?
DML(insert delete update) TCL(commit rollback savepoint) 可以直接在plsql中使用
------------------------------------------------------------------------------------------
select 语句要么和 into 结合使用(查询的数据只有一个结果)
如果select语句返回多行数据 则需要和游标结合使用
------------------------------------------------------------------------------------------
DDL(create drop alter) 不能直接在plsql中使用 需要使用动态sql
------------------------------------------------------------------------------------------
begin
create table dsql(id number primary key);
end;
/
2、动态sql
2.1 概念
在程序执行的过程中 sql语句可以根据条件发生改变。
2.2 如何实现?
只要把sql语句变换成字符串即可, 并使用 execute immediate 执行字符串
------------------------------------------------------------------------------------------
declare sqlstr varchar2(200):='create table dsql(id number primary key)';
begin
sqlstr:=replace(sqlstr,')','');
sqlstr:=sqlstr || ' ,name varchar2(30))';
dbms_output.put_line(sqlstr);
execute immediate sqlstr;
end;
/
3、其实DML select语句 等都可以使用 动态sql
3.1 参考游标的概念
select 语句的动态sql ------ 参考游标
参考游标的核心思想 就是 游标对应的sql语句 是一个动态拼接的字符串。
------------------------------------------------------------------------------------------
3.2 参考游标的使用步骤
定义一个参考游标类型
type 参考游标类型名 is ref cursor;
使用参考游标类型 定义游标变量;
游标名 参考游标类型名;
把游标变量 和 拼接的字符串 关联起来;
------------------------------------------------------------------------------------------
3.3 举例
declare
sqlstr varchar2(300);
type myrefcursor is ref cursor;
empcursor myrefcursor;
type emptype is record(
id s_emp.id%type,
name s_emp.first_name%type,
salary emp.salary%type
);
var_emp emptype;
begin
sqlstr:='select id,first_name,salary from s_emp';
sqlstr:=sqlstr || 'where salary > 1500';
sqlstr:=sqlstr || 'and id > 5';
open empcursor for sqlstr;
loop
fetch empcursor into var_emp;
exit when empcursor%notfound;
dbms_output.put_line(var_emp.id||':'||var_emp.name||':'||var_emp.salary);
end loop;
close empcursor;
end;
/
------------------------------------------------------------------------------------------
3.4 参考游标中的占位符 :bn 开头的叫占位符 使用using 可以传入实参
declare
sqlstr varchar2(300);
type myrefcursor is ref cursor;
empcursor myrefcursor;
type emptype is record(
id s_emp.id%type;
name s_emp.first_name%type;
salary s_emp.salary%type;
);
var_emp emptype;
begin
sqlstr:='select id,first_name,salary from s_emp ';
sqlstr:=sqlstr || 'where salary>:b0 ';
sqlstr:=sqlstr||' and id > :b1 ';
open empcursor for sqlstr using 1000,3;
loop
fetch empcursor into var_emp;
exit when empcursor%notfound;
dbms_output.put_line(var_emp.id||':'||var_emp.name||':'||var_emp.salary);
end loop;
close empcursor;
end;
/

26.PLSQL中的异常机制
概念
在程序执行过程 出现的错误
举例
declare
var_name s_emp.first_name%type;
begin
select first_name into var_name from s_emp where id=44;
dbms_output.put_line(var_name);
exception
when others then
dbms_output.put_line('have exception');
end;
/
预定义了 一些常见的操作异常
declare
var_name s_emp.first_name%type;
begin
select first_name into var_name from s_emp where id=4;
dbms_output.put_line(var_name);
select first_name into var_name from s_emp where id>4;
dbms_output.put_line(var_name);
exception
when NO_DATA_FOUND then
dbms_output.put_line('no emp found');
when TOO_MANY_ROWS then
dbms_output.put_line('too many emp');
when others then
dbms_output.put_line('have exception');
end;
/
当写plsql程序 时要分析程序可能会出现哪些异常 然后根据系统预定义的异常
进行相应的处理 程序的最后一般使用 others 作为最后的异常捕获处理。

用户自定义异常
	1.定义异常
	根据系统中  可能出现问题  使用异常描述出来 

	2.抛出异常 
	用户根据 条件 抛出   满足什么样的条件 就抛出什么样的异常 

	3.捕获异常 

	4.处理异常 
	针对不同异常  作出相应的处理 
举例
	declare
        empexception     exception;
        deptexception     exception;
	begin
	         if  1=2  then 
	              raise   empexception; 
	         end if;
	         if  1=1  then 
	              raise  deptexception; 
	         end if; 
	         dbms_output.put_line('app continue');                  
	exception
	          when   empexception  then
	          dbms_output.put_line('emp exception');
	          when   deptexception  then
	          dbms_output.put_line('dept exception');     
	end;
	/ 

27.PLSQL中过程
1、概念
对完成某一个功能的 一组 sql 语句和 plsql语句的一个逻辑整体。
这个逻辑整体有一个名字 对应 数据库中的逻辑。
2、复用
3、定义两个整数变量 选出 两个变量的最大值
declare
var_x number:=20;
var_y number:=30;
begin
if var_x < var_y then
dbms_output.put_line(var_y);
else
dbms_output.put_line(var_x);
end if;
end;
/
------------------------------------------------------------------------------------------
create or replace procedure getmax(var_x number,var_y number)
is
begin
if var_x < var_y then
dbms_output.put_line(var_y);
else
dbms_output.put_line(var_x);
end if;
end;

4、调用
	call    getmax(1,10);
	------------------------------------------------------------------------------------------
	execute  getmax(200,300);
	------------------------------------------------------------------------------------------
	通过plsql程序来调用 
	  begin
	     getmax(101,999); 
	  end;
	  / 

5、写一个存储过程 可以完成两个参数最小值的选取 并使用匿名块调用
	create  or  replace   procedure  getmin(var_x number:=1,var_y  number:=2) 
	is
	begin
	   if  var_x  < var_y  then 
	         dbms_output.put_line(var_x);
	   else
	         dbms_output.put_line(var_y); 
	   end if;
	end;
	/     
	call  getmin();  
	execute  getmin;
	execute  getmin();
	------------------------------------------------------------------------------------------
	当不需要给参数传值时  call 必须使用()   execute 可以省略()
	如果参数有默认值  则可以不给参数传值  不传值则使用参数的默认值  传值则会替代掉默认值
	execute getmin(8899,9988);
	查看公司文档 搜索默认值  也可以测试得出默认值  最后还可以查看存储过程源代码
	select text  from user_source  where  name='GETMIN';

6、调用别人的存储过程 一般会先查看存储过程
	desc    过程名;
	desc    getmin;   
	SQL> desc   getmin;
	------------------------------------------------------------------------------------------
	PROCEDURE getmin
	 Argument Name                  Type                    In/Out Default?
	 ------------------------------ ------------        ----------- ------ --------
	 VAR_X                          NUMBER                         IN     DEFAULT
	 VAR_Y                          NUMBER                         IN     DEFAULT
	 查看一个存储过程 可以获取 
	 参数的名字
	 参数的类型 




	 参数的模式 
	------------------------------------------------------------------------------------------

	in    默认的   代表参数只负责给存储过程传入值
	out   代表只给存储过程传出值 
	in out   代表参数即给存储过程传入值  又给存储过程传出值 
	 参数的默认值

	 public static  void    getnum(int x){
	     x=10001;
	   }
	  public static  void    getString(String x){
	     x=x+"abc"
	   }
	  public  static  void  getStringBuf(StringBuffer  y){
	    y.append("cba");
	  }
	  static  main(String[] args){
	     String  x = new String ("nba");
	     getString(x);
	     x
	     StringBuffer  y  = new StringBuffer("nba");
	     getStringBuf(y);
	     y
	   }

7、参数的模式
	 in      只负责给存储过程 传入参数值 
	 create  or replace  procedure  getnum(var_x   number )
	 is
	 begin
	       dbms_output.put_line(var_x);  
	        var_x:=10001;
	 end;
	 /
	 通过show errors  可以看到 var_x  只能读不能写 证明它只负责传入 不负责传出

	 out  参数   只负责给存储过程 传出参数值 
	 设计一个存储过程  有三个整数参数  打印前两个参数的最大值   并且把前两个参数的和存入第三个参数中 
	 create  or replace  procedure  getmax_and_sum(var_x  number,var_y  number,
	        var_z  out number)
	 is
	 begin
	         if  var_x < var_y  then
	               dbms_output.put_line(var_y);
	         else
	               dbms_output.put_line(var_x); 
	         end   if;
	         var_z:=var_x+var_y;
	 end;
	 / 
	 注意:out 修饰的参数 必须是变量         
	 declare
	         var_z   number:=0;            
	 begin
	         getmax_and_sum(1,100,var_z);
	         dbms_output.put_line(var_z);
	 end;
	 /

	 in  out  参数   即负责给存储过程传入参数值  又负责传出值 
	 设计一个存储过程  有两个整数参数  打印两个参数的最大值   并且把两个参数的和存入第二个参数中         
	 create  or replace  procedure  getmax_and_sum(var_x  number,var_y  in  out   number)
	 is
	 begin
	         if  var_x < var_y  then
	               dbms_output.put_line(var_y);
	         else
	               dbms_output.put_line(var_x); 
	         end   if;
	         var_y:=var_x+var_y;
	 end;
	 /  

	 按照参数的位置赋值
	 declare
	       var_t    number:=99;
	 begin
	       getmax_and_sum(100,var_t);
	       dbms_output.put_line(var_t);
	 end;
	 / 

	按照参数的名字赋值 
	declare
	       var_t    number:=99;
	begin
	       getmax_and_sum(var_y=>var_t,var_x=>100);
	       dbms_output.put_line(var_t);
	end;
	/

8、设计一个存储过程 第一个参数代表从1 加到的数 第二个参数 用来存储前n项的和 调用这个存储过程 看计算是否正确
	 create  or  replace  procedure   getNumN(var_n   number,var_sum  out  number)  
	 is
	 begin
	         var_sum:=(1+var_n)*var_n/2;
	 end;
	 /
	-----------------------------------------------------------------------------------------
	declare
	        var_s    number:=0;
	begin
	        getNumN(100,var_s);
	        dbms_output.put_line(var_s);           
	end;
	 /

28.PLSQL 函数
1、函数 和 过程的区别
第一 关键字不同 函数是Function 过程是 procedure
第二 函数有返回值类型 和 返回值 过程没有
第三 调用方式不同 过程可以直接在plsql中调用 函数必须组成表达式才能调用
2、函数的语法
create or replace function 函数名(参数列表) return 具体的type
is
begin
if 条件 then
return 值;
end if;
return 值;
end;
/
3、设计一个plsql 函数 有两个整数参数 返回两个参数的最大值
create or replace function getmax(var_x number,var_y number) return number
is
begin
if var_x < var_y then
return var_y;
end if;
return var_x;
end;
/
4、如何调用
select getmax(1,100) from dual;
begin
dbms_output.put_line(getmax(200,999));
if 100<getmax(1,999) then
dbms_output.put_line('call function');
end if;
end;

5、要求设计一个plsql 的函数 有两个整数参数 返回两个参数的最大值 并且 把两个参数的和存入第二个参数中。 调用函数 验证功能。
	create  or replace  function  getmax_and_sum(
     var_x   number,var_y  in  out number)return  number
	is
	begin
	      if  var_x  < var_y then 
	          var_y:=var_x+var_y;
	          return  var_y-var_x;
	      else 
	          var_y:=var_x+var_y;
	          return  var_x;
	      end  if;  
	end;
	/
	------------------------------------------------------------------------------------------
	create  or replace  function  getmax_and_sum(
	      var_x   number,var_y  in  out number)return  number
	is 
	      var_t   number;
	begin
	      var_t:=var_y;
	      var_y:=var_x+var_y;
	      if  var_x  < var_t then 
	             return  var_t;
	       else 
	             return  var_x;
	       end  if;  
	end;
	/ 
	------------------------------------------------------------------------------------------
	declare
	       var_y   number:=1;
	       var_x   number:=99;
	       var_res  number:=0;
	begin
	       var_res:=getmax_and_sum(var_x,var_y);
	       dbms_output.put_line(var_res);
	       dbms_output.put_line(var_y);           
	end;
	/

29.包 package
1、系统提供的包
dbms_output 输出包
dbms_output.put_line('hello');
dbms_random 随机数包
select dbms_random.value(1,100) from dual;
select trunc(dbms_random.value(1,100)) from dual;
dbms_job 定时任务包
可以定时调用存储过程
dbms_lob 操作大数据类型的包 比如 blob 和 clob 类型

2、用户可以自定义包
	无论是系统的包 还是自定义的包    使用包中的数据记得在数据前加 包名点即可 
	mypack    -----   getmax 
	mypack.getmax(1,100)

30、PLSQL 触发器
1、DML 级别的触发器
当进行dml(insert delete update)操作时,这些操作可以被数据库管理系统捕获到,捕获到这些行为之后 可以根据操作 进行相应的处理。
2、语法
create or replace trigger 触发器的名字 before|after dml(insert |delete | update)
on 表名 | for each row
declare
begin
end;
/
3、 举例
create table emp300 as select id,first_name name,salary from s_emp;
col name for a20;
为 emp300 这张表建立一个更新操作之后的 触发器
create or replace trigger emp300_after_update after update on emp300
declare
begin
dbms_output.put_line('warning you update emp300');
end;
/
update emp300 set salary=salary+100 where id=1;
update emp300 set salary=salary+100 where id<1;
update emp300 set salary=salary+100 where id>1;
无论sql语句影响多少行数据 上面的触发器 都会被触发一次 这种触发器 叫 语句级触发器。

4、开发中 比较有意义的是 针对每一行 都触发 这样才能获取到数据的具体变化
	行级触发器 —- 针对sql语句影响的每一行都触发 for each row
	 create  or  replace  trigger   emp300_after_update  after  update   on  emp300  for each row
	 declare
	 begin
	        dbms_output.put_line(:old.id||':'||:old.salary);            
	        dbms_output.put_line('warning   you update emp300');
	        dbms_output.put_line(:new.id||':'||:new.salary); 
	 end;
	 /                  
	 update  emp300 set salary=salary+100 where id=1;
	 update  emp300 set salary=salary+100 where id<1;
	 update  emp300 set salary=salary+100 where id>1; 

	 update       :old                 :new
	 delete       :old 
	 insert                            :new 

	触发器中不能使用  事务控制语句

	 create  or  replace  procedure   getNumN(var_n   number,var_sum  out  number)  
	 is
	 begin
	      var_sum:=0;
	      for  var_i  in  1..var_n  loop
	           var_sum:=var_sum+var_i;  
	      end  loop;
	 end;
	 / 
	------------------------------------------------------------------------------------------
	declare
	        var_s    number:=0;
	begin
	        getNumN(100,var_s);
	        dbms_output.put_line('var_s='||var_s);           
	end;
	/

	constant       not null
	declare
	        var_x    constant  number  not null:=0; 
	begin
posted @ 2022-01-03 22:02  shoupifeng  阅读(69)  评论(0编辑  收藏  举报