• 关于Oracle数据库的笔记


       1 /*
       2 一、表达式
       3     1.定义:表达式是操作数与操作符的组合
       4     
       5         操作数:可以是常量、变量、函数的返回值、另一个查询语句返回的值
       6         
       7         操作符:就是运算符,包括算术运算符、赋值运算符、比较运算符、逻辑运算符、字符匹配运算等
       8         
       9             算术运算符:+,-,*,/,mod(m,n)[计算m和n的余数]
      10             连接运算符:||
      11             赋值运算符:= (注:比较运算符也是=)
      12             比较运算符:=,>,<,>=,<=,<>,!=,between...and,in,like,is null
      13             逻辑运算符:not,and,or
      14             集合运算符:union,union all,minus,INTERSECT
      15                 union:取出2个表数据合并,去除重复记录
      16                 union all:取出2个表数据合并,保留重复记录
      17                 minus:取出2个表中不同数据
      18                 Intersect:取出2个表中共有数据【交集】
      19             字符匹配运算:
      20                 BETWEEN...AND:如果操作数在某个范围之内,那么就为 TRUE
      21                 IN:如果操作数等于表达式列表中的一个,那么就为 TRUE
      22                 like:如果操作数与一种模式相匹配,那么就为 TRUE
      23                     %:零个或任意个字符
      24                     _:任意一个字符
      25 
      26                     
      27             
      28             
      29 二、添加数据
      30 
      31     1.语法一:(常用)
      32         insert into 表名(字段1,...,字段n)
      33         values(值1,...,值n)
      34     
      35     
      36     2.语法二:(常用)
      37         insert into 表名
      38         values(值1,...,值n)
      39         
      40         注:必须要添加全部字段的数据(标识[identity]列除外)
      41     
      42 
      43     3.语法三:添加多条记录,数据的具体的数据
      44         insert into 表名(目标表)
      45             select 数据1,...,数据n from dual
      46             union
      47             select 数据1,...,数据n from dual
      48             union 
      49             select 数据1,...,数据n from dual
      50             ...
      51             
      52 
      53 
      54         create table student
      55         (
      56             id int identity(1,1) primary key ,
      57             name varchar(20) not null ,
      58             age int ,
      59             wieght float
      60         )
      61     
      62         insert into student
      63             select '赵六',20,180 from dual
      64             union
      65             select '田七',5,180 from dual
      66             union
      67             select '王八',2,250 from dual
      68 
      69     
      70     4.语法四:添加多条记录,数据来源于另一张数据表
      71         把某张表(源表)的数据,添加到另一张表(目标表,此表必须存在)中
      72     
      73         insert into 表名(目标表)
      74             select 字段1,...,字段n 
      75             from 表名(源表)
      76             where 条件
      77             
      78         注:目标表必须存在
      79         
      80         insert into student_two    
      81             select name,age,wieght from student
      82             where age>=18
      83             
      84             
      85         create table student_two
      86         (
      87             id int identity(1,1) primary key ,
      88             name varchar(20) not null ,
      89             age int ,
      90             wieght float
      91         )
      92         
      93         select * from student 
      94         select * from student_two 
      95     
      96     
      97     
      98     5.语法五:在创建数据表的同时,把另一张表的数据录入到表中
      99     
     100         select 源表字段名1, 源表字段名2,……, 源表字段名n 
     101             into 新表名
     102         from 源表名
     103         where 源表字段条件
     104         
     105         create table 表名(目标表)
     106         as
     107         select 字段1,字段2,...|* from 表名(源表)
     108         
     109         注:目标表可以不存在
     110 
     111 三、删除数据
     112 
     113     1.语法一:delete from 表名
     114     
     115         select * from student_two
     116         delete from student_two
     117     
     118     2.语法二:delete from 表名 where 条件 
     119     
     120         注:删除一般要写条件,否则会把整张表的数据都删除了;
     121         一般选择唯一键、主键做为条件
     122     
     123         delete from student where id=6
     124     
     125     3.语法三:truncate table 表名
     126         语法三的功能等同于语法一:都可以清空表中的数据
     127         
     128         truncate table student
     129         
     130         语法一和语法三的区别:    
     131             1)TRUNCATE删除数据的速度快,DELETE相对更慢。
     132             2)TRUNCATE只能一次性删除表中全部数据,DELETE可以删除指定条件的数据行。
     133             3)TRUNCATE删除数据后不能回滚(不写日志),而DELETE可以回滚。
     134             4)使用TRUNCATE删除表数据时,不会触发删除触发器,而DELETE则会触发相应的删除触发器。
     135             5)对于有FOREIGN KEY约束引用的表不能使用TRUNCATE,而DELETE则可以(除已经被引用的数据行以外)。
     136             
     137             
     138 四、修改数据
     139     语法:
     140         update 表名 set 
     141             字段1='新值',
     142             字段2='新值',
     143             ...
     144             字段n='新值'
     145         where 条件
     146         
     147         select * from s69
     148         update s69 set
     149             name='张三三' ,
     150             age=81
     151         where id=3
     152         
     153         
     154     
     155     注:修改一般要写条件,否则会把整张表都修改了
     156 
     157 
     158 
     159 
     160 五、查询数据
     161 1.语法:
     162     select [distinct | 聚合函数] 字段集合 [as 别名]|*
     163     from  表名
     164     [where 查询条件语句集合]
     165     [group by 分组字段列表]
     166     [having 过滤条件语句集合]    分组查询条件
     167     [order by 排序字段集合 [asc | desc]]
     168 
     169 
     170 --查询所有字段的信息
     171 select * from 表名
     172 select * from dept;
     173 select deptno,dname,loc from dept; --建议
     174 
     175 
     176 --查询数据表中局部字段的信息
     177 select 字段名1,...,字段名n
     178 from 表名
     179 
     180 select dname,loc from dept ;
     181 
     182 
     183 --按条件查询
     184 select * from 学生信息
     185 where 条件
     186 
     187 select * from dept 
     188 where deptno>20
     189 
     190 
     191 --模糊查询like
     192     通配符:
     193     _:任意一个字符
     194     %:0个或多个任意字符
     195 
     196 --查看部门名称含有字母"S"的数据
     197 select * from dept 
     198 where dname like '%S%'    
     199 
     200 --查看部门名称以字母"S"结尾的数据    
     201 select * from dept 
     202 where dname like '%S'
     203 
     204 --查看部门名称以"LES"结尾并前面含有两个任意字符的数据
     205 select * from dept 
     206 where dname like '__LES' ;
     207     
     208     
     209 --未知值(is null , is not null):查询某值是否为null
     210 create table t1 
     211 as 
     212 select * from dept ;
     213 
     214 insert into t1(deptno,dname) values (50,'Java开发部')
     215 
     216 --查询部门地址为null的部门信息
     217 select * from t1 
     218 where loc is null
     219 
     220 --查询部门地址不为null的部门信息
     221 select * from t1 
     222 where loc is not null
     223 
     224 
     225 
     226 --列表运算符(in , not in):查询匹配列表中的某一个值
     227 select * from 表名
     228 where 字段 [not] in ('值1',...,'值n')
     229 
     230 --查询部门地址在'NEW YORK','CHICAGO','BOSTON'的部门信息
     231 select * from t1 
     232 where loc in ('NEW YORK','CHICAGO','BOSTON')
     233 
     234 select * from t1 
     235 where loc = 'NEW YORK' or loc = 'CHICAGO' or loc = 'BOSTON'
     236 
     237 
     238 select * from t1 
     239 where loc not in ('NEW YORK','CHICAGO','BOSTON') or loc is null
     240 
     241     
     242     
     243 
     244 
     245 --查询前面的n条记录
     246 注意:Oracle不支持select top 语句,所以在Oracle中经常是用order by 跟rownum
     247 的组合来实现select top n的查询。语法如下:
     248 
     249 select 列名1 ...列名n from
     250 (
     251     select 列名1 ...列名n 
     252     from 表名 order by 列名1
     253 )
     254 where rownum <=N(抽出记录数)
     255 order by rownum asc
     256 
     257 
     258 
     259 eg:
     260 select id,name from 
     261 (
     262     select id,name 
     263     from student order by name
     264 ) 
     265 where rownum<=10 order by rownum asc
     266 
     267 按姓名排序取出前十条数据
     268 其中,rownum是产生有序编号的伪列
     269 
     270 
     271 扩展:某个范围中的数据->分页查询
     272 方法一:利用分析函数(建议),语法为:
     273     row_number() over(order by 字段 desc|asc)
     274     
     275 eg:
     276     select deptno,dname,loc from 
     277     (                               
     278         select 
     279             deptno,
     280             dname,
     281             loc,row_number() over ( order by deptno asc) rn 
     282         from t1 
     283     ) where rn between 2 and 4;
     284     
     285 
     286 
     287 方法二:伪列(rownum)
     288 select deptno,dname,loc from 
     289 (                    
     290     select deptno,dname,loc,rownum as rn 
     291     from dept 
     292     where rownum <= 4  
     293 ) where rn >= 2;
     294 
     295 
     296 
     297 --字符串连接:||
     298 select 'hello' || ' world' from dual
     299 
     300 trim(字段|数据):去除空格
     301 
     302 
     303 
     304 
     305 --改列名(别名)用法
     306 
     307 select 'hello' || ' world' as 你好 from dual
     308 
     309 
     310 
     311 --可以省略as
     312 select 'hello' || ' world' 你好 from dual
     313 
     314 --排序(默认的是升序)
     315     order by 字段名 asc | desc
     316     1)asc:升序(默认)
     317     2)desc:降序
     318     
     319     select * from t1 order by deptno desc;
     320     select * from t1 order by dname asc ;
     321 
     322 --聚合函数
     323     1)max:求最大值
     324     2)min:求最小值
     325     3)sum:求和
     326     4)avg:求平均值
     327     5)count:求记录数
     328     
     329 select 
     330     max(sal) as 最高薪水,
     331     min(sal) as 最低薪水,
     332     sum(sal) as 薪水总和,
     333     avg(sal) as 平均薪水,
     334     count(*) as 总人数   
     335 from emp ;    
     336 
     337 select count(*),count(loc) from t1 ;
     338 
     339 注:
     340 count中如果传递具体字段时,不会统计null的字段
     341 聚合函数一般结合分组函数使用
     342 --统计各部门的平均薪水
     343 select 
     344     deptno as 部门编号,
     345     avg(sal) as 平均薪水
     346 from emp group by deptno;
     347 
     348 --统计各经理有多少个下属员工 
     349 select 
     350     mgr as 领导,
     351     count(*) as 下属人数 
     352 from emp 
     353 group by mgr
     354 having mgr is not null
     355     
     356 
     357 
     358 --集合操作符
     359 union:取出2个表数据合并,去除重复记录
     360 union all:取出2个表数据合并,保留重复记录
     361 minus:取出2个表中不同数据
     362 Intersect:取出2个表中共有数据【交集】    
     363 
     364 SELECT 字段集合|* FROM 表1
     365 
     366 UNION|union all|minus|intersect
     367 
     368 SELECT 字段集合|* FROM 表2
     369 
     370 注意: 
     371     两个查询的字段个数必须相同; 
     372     T_2 的查询字段类型要和 T_1的相同.
     373 
     374 create table t2
     375 as 
     376 select * from dept ;
     377 
     378 
     379 delete from t2 where deptno>=30
     380 
     381 select * from t2 ;
     382 select * from dept ;
     383 
     384 
     385 select * from t2
     386 union
     387 select * from dept;
     388 
     389 select 'aa','bb' from dual
     390 union
     391 select 'cc','dd' from dual
     392 union
     393 select 'cc','dd' from dual
     394 
     395 
     396 select * from t2
     397 union all
     398 select * from dept;
     399 
     400 select 'aa','bb' from dual
     401 union all
     402 select 'cc','dd' from dual
     403 union all
     404 select 'cc','dd' from dual
     405 
     406 
     407 
     408 
     409 select * from dept
     410 minus
     411 select * from t2;
     412 
     413 
     414 select * from dept
     415 intersect
     416 select * from t2;
     417 
     418 
     419 六、连接查询--连接(合并)两张或多张表,进行查询
     420 (多表查询一般是通过主外键关联(公共关键字))
     421 
     422 连接查询是关系数据库中最主要的查询,主要包括内连接、外连接和交叉连接等。
     423 通过连接运算符可以实现多个表查询。
     424 
     425 
     426 关系型数据库
     427     表1
     428     表2
     429     表3
     430 
     431 
     432 1、内连接    inner join ... on ...
     433     select * from 表1 inner join 表2 on 表1.字段=表2.字段
     434     
     435     注:一般是根据主键和外键进行连接
     436 
     437     select * from emp inner join dept 
     438     on emp.deptno = dept.deptno;
     439 
     440 
     441     select * from emp e inner join dept d
     442     on e.deptno = d.deptno;
     443 
     444     select 
     445         ename,
     446         job,
     447         e.deptno,
     448         dname 
     449     from emp e inner join dept d
     450     on e.deptno = d.deptno;    
     451     
     452     
     453 
     454 
     455 2、等值连接    、不等值连接
     456     select * from 表1,表2 
     457     where 表1.字段(主键)=表2.字段(外键)
     458     
     459     select * from 表1,表2 
     460     where 表1.字段!=表2.字段
     461     
     462     
     463     select * from emp,dept 
     464     where emp.deptno = dept.deptno
     465 
     466     select * from emp e,dept d
     467     where e.deptno = d.deptno
     468 
     469     select ename,job,dname from emp e,dept d
     470     where e.deptno = d.deptno    
     471     
     472 
     473     
     474 3、外连接    
     475 3.1)左外连接
     476     select * from 表1 left [outer] join 表2 
     477     on 表1.字段=表2.字段
     478     
     479     
     480     select * from 表1,表2 where 表1.字段(+)=表2.字段
     481     
     482 注:(+)的用法:
     483 1>(+)操作符只能出现在WHERE子句中,并且不能与OUTER JOIN语法同时使用。
     484 2>当使用(+)操作符执行外连接时,如果在WHERE子句中包含有多个条件,则必须在所有条件中都包含(+)操作符。
     485 3>(+)操作符只适用于列,而不能用在表达式上。
     486 4>(+)操作符不能与OR和IN操作符一起使用。
     487 5>(+)操作符只能用于实现左外连接和右外连接,而不能用于实现完全外连接。
     488 
     489 3.2)右外连接
     490     select * from 表1 right [outer] join 表2 on 表1.字段=表2.字段
     491     select * from 表1,表2 on 表1.字段=表2.字段(+)
     492 
     493 
     494 3.3)完全外连接
     495     select * from 表1 full [outer] join 表2 on 表1.字段=表2.字段
     496 
     497 --主键表(主表)
     498 create table cls
     499 (
     500        name varchar2(30) primary key ,
     501        teacher varchar2(30) ,
     502        loc varchar2(30)
     503 )
     504 
     505  insert into cls values('s3sj132','张老师','213') ;
     506  insert into cls values('s3sj133','李老师','214') ;
     507  insert into cls values('s3sj134','王老师','215') ;
     508  insert into cls values('s3sj137','赵老师','216') ;
     509 
     510 select * from cls;
     511 drop table stu ;
     512 --外键表(从表)
     513 create table stu
     514 (
     515        name varchar2(30) ,
     516        age number(3,0) ,
     517        sex char(2) ,
     518        cls_name varchar2(30) 
     519 )
     520 
     521 insert into stu values ('张三',18,'男','s3sj132') ;
     522 insert into stu values ('李四',19,'男','s3sj133') ;
     523 
     524 insert into stu values ('王五',17,'女','s3sj134') ;
     525 insert into stu values ('赵六',16,'男','s3sj135') ;
     526 
     527 delete from stu where name='张三'
     528 
     529 
     530 
     531 select * from cls;
     532 select * from stu;
     533 
     534 select * from cls left join stu
     535 on cls.name=cls_name;
     536 
     537 select * from cls inner join stu
     538 on cls.name=cls_name;
     539 
     540 
     541 
     542 
     543 select * from cls right outer join stu
     544 on cls.name = cls_name;
     545 
     546 
     547 select * from cls full outer join stu
     548 on cls.name = cls_name;    
     549     
     550     
     551     
     552 
     553 select * from cls,stu
     554 where cls.name(+)=stu.cls_name;
     555 
     556 select * from cls,stu
     557 where cls.name=stu.cls_name(+);    
     558     
     559     
     560     
     561 4、交叉连接
     562     select * from 表1 cross join 表2 
     563     select * from 表1 , 表2 
     564     
     565     select * from cls cross join stu;
     566     select * from cls,stu;
     567 
     568     
     569 七、子查询
     570 1.概念:当一个查询是另一个查询的条件时,称为子查询。
     571         
     572         
     573 --在SELECT语句中使用子查询
     574 select * from 学生信息
     575 where 学号 in 
     576 (
     577     select 学生编号 from 成绩信息 where 分数>96
     578 )
     579     
     580 --查询薪水最高的员工所在的部门信息
     581 select * from dept where deptno in
     582 (
     583   select deptno from emp where sal=
     584   (
     585          select max(sal) from emp 
     586   )
     587 )
     588 
     589 
     590 select emp.deptno,dname,loc,ename,sal from dept,emp 
     591 where dept.deptno=emp.deptno 
     592 and emp.sal =
     593 (
     594        select max(sal) from emp
     595 );
     596 
     597 
     598 
     599 
     600     
     601 --子查询可以使用在SELECT、INSERT、UPDATE或DELETE语句中
     602 insert into 学生信息
     603 values ('2014010102','李四四',
     604 (select 性别 from 学生信息 
     605 where 姓名='张苗苗'),
     606 '1999-09-09','汉族','20050101','广东珠海')
     607 
     608 
     609 update 学生信息 set
     610     性别=(select 性别 from 学生信息 where 姓名='赵希坤')
     611 where 姓名='张苗苗'
     612 
     613 
     614 delete from 学生信息
     615 where convert(varchar,家庭住址)=(select convert(varchar,家庭住址) from 学生信息 where 姓名='张苗苗')
     616     
     617 
     618 
     619     
     620 八、事务处理
     621 1、commit:提交事务
     622     show autocommit    : 显示是否自动事务提交
     623     set autocommit=on|off    : 设置是否自动事务提交
     624 
     625 2、rollback:事务回滚
     626     rollback
     627     rollback to 保存点
     628     
     629 3、设置保存点
     630     savepoint 保存点名称
     631 
     632 4、设置只读事务
     633     set transaction read only
     634     
     635 九、函数
     636 
     637 */
     638 
     639 /*
     640 一、函数的定义
     641     具有某种功能的代码段
     642     
     643     实现代码重用,模块化编程
     644     
     645 二、分类
     646     1.系统函数,用户自定义函数
     647     
     648     2.参数,返回值
     649         1)无参无返
     650         2)无参有返
     651         3)有参无返
     652         4)有参有返
     653     
     654         函数中有两个角色:主调函数(张老师),被调函数(袁家辉)
     655         参数:主调函数给被调函数传递的信息(数据)
     656             参数的数量:0个或多个
     657             
     658             形式参数(形参):在定义函数时的参数
     659             实际参数(实参):在调用函数时的参数
     660             
     661         返回值:被调函数给主调函数传递的信息(数据)
     662             返回值的数量:0个或1个
     663     
     664         
     665         int sum(int a,int b) {
     666             int s ;
     667             s = a + b ;
     668             return s ;
     669         }
     670     
     671         sum(1,2) ;
     672     
     673 三、Oracle提供的系统函数 
     674 1.数学函数
     675 
     676 --求绝对值
     677 select abs(-4) from dual
     678 
     679 --power(n,m):n的m次方
     680 select power(2,3) from dual
     681 
     682 
     683 --返回大于或等于n最小整数值(3,4,5...)
     684 select ceil(2.48) from dual ;    --3
     685 select ceil(2.68) from dual ;    --3
     686 
     687 --返回小于或等于n最大整数值(2,1,0,-1...)
     688 select floor(2.48) from dual ;    --2
     689 select floor(2.68) from dual ;    --2
     690 
     691 --四舍五入
     692 select round(2.48) from dual ;    --2
     693 select round(2.68) from dual ;    --3
     694 
     695 --四舍五入,设置保留位数
     696 select round(2.48,1) from dual ;  --2.5
     697 select round(2.163,2) from dual ;  --2.16
     698 
     699 --随机数
     700 --1)小数(0 ~ 1)
     701 select dbms_random.value from dual;
     702 
     703 --2)指定范围内的小数 ( 0 ~ 100 )
     704 select dbms_random.value(0,100) from dual;
     705 
     706 --3)指定范围内的整数 ( 0 ~ 100 )
     707 select round(dbms_random.value(0,100),0) from dual;
     708 select round(dbms_random.value(0,100)) from dual;
     709 
     710 --4)长度为20的随机数字串
     711 select substr(cast(dbms_random.value as varchar2(38)),3,20) from dual;
     712 
     713 --5)随机字符串
     714 select dbms_random.string(opt, length) from dual;
     715 其中:opt为选项,规则如下所示:
     716 'u','U'    :    大写字母
     717 'l','L'    :    小写字母
     718 'a','A'    :    大、小写字母
     719 'x','X'    :    数字、大写字母
     720 'p','P'    :    可打印字符
     721 length为随机字符串的长度
     722 
     723 select dbms_random.string('a',10) from dual;
     724 
     725 --6)生成GUID:32位十六进制字符串
     726 select sys_guid() from dual;
     727 select length(sys_guid()) from dual;
     728 
     729 
     730 
     731 2.字符串函数
     732 --length:求字符串的长度
     733 print len('hello,world')
     734 select length(ename),ename from emp ;
     735 
     736 --lower/upper:大小写
     737 select ename,lower(ename),upper(ename) from emp ;
     738 
     739 --concat/||:字符串连接
     740 select concat('hello ','world') from dual ;
     741 select 'hello ' || 'world' from dual ;
     742 
     743 
     744 --substr("字符串",start,n):截取字符串,从start开始截取n个字符
     745 select substr('hello,world',1,3) from dual;
     746 select ename,substr(ename,1,3) from emp ;
     747 
     748 
     749 --replace:替换字符串
     750 replace('字符串','被替换子字符串','替换字符串')
     751 select replace('hello world','world','china') from dual ;
     752 
     753 --instr:查找字符串
     754 instr('字符串','查找字符/字符串','起始位置'),返回下标位置(从1开始)
     755 select instr('abcabc','c',-2) from dual;
     756 select instr('abcabc','c',0) from dual;
     757 select instr('abcabc','c') from dual;
     758 
     759 注:起始位置中,正数从左向右、负数从右向左查找
     760 
     761 
     762 --trim:去掉字符串左边、右边两边的空格
     763 --ltrim:去掉字符串左边空格
     764 --rtrim:去掉字符串右边空格
     765 select 'AAA' || '   BBB    ' ||  'CCC' from dual ;
     766 select 'AAA' || trim( '   BBB    ') ||  'CCC' from dual ;
     767 
     768 --
     769 
     770 3.日期函数 getdate()
     771 --sysdate:返回当前session所在时区的默认时间
     772 --获取当前系统时间
     773 select sysdate from dual;
     774 
     775 --add_months:返回指定日期月份+n之后的值,n可以为任何整数
     776 --查询当前系统月份+2 的时间
     777 select add_months(sysdate,2) from dual;
     778 
     779 --查询当前系统月份-2 的时间
     780 select add_months(sysdate,-2) from dual;
     781 
     782 --last_day:返回指定时间所在月的最后一天
     783 --获取当前系统月份的最后一天
     784 select last_day(sysdate) from dual;
     785 
     786 --months_between:返回月份差,结果可正可负,当然也有可能为 0
     787 --获取入职日期距离当前时间多少月
     788 select months_between(sysdate, hiredate) from emp;
     789 select months_between(hiredate, sysdate) from emp;
     790 
     791 
     792 
     793 --trunc(number,num_digits) 
     794 --用法一:截取日期值
     795 select trunc(sysdate) from dual --2013-01-06 今天的日期为2013-01-06
     796 
     797 select trunc(sysdate, 'mm') from dual
     798  --2013-01-01 返回当月第一天.
     799  
     800 select trunc(sysdate,'yy') from dual --2013-01-01 返回当年第一天
     801 
     802 select trunc(sysdate,'dd') from dual --2013-01-06 返回当前年月日
     803 
     804 select trunc(sysdate,'yyyy') from dual --2013-01-01 返回当年第一天
     805 
     806 select trunc(sysdate,'d') from dual --2013-01-06 (星期天)返回当前星期的第一天
     807 
     808 select trunc(sysdate, 'hh') from dual --2013-01-06 17:00:00 当前时间为17:35 
     809 select trunc(sysdate, 'mi') from dual --2013-01-06 17:35:00 TRUNC()函数没有秒的精确
     810 
     811 
     812 --用法二:截取数值
     813 number:需要截尾取整的数字。 
     814 num_digits:用于指定取整精度的数字。Num_digits 的默认值为 0。
     815 trunc()函数截取时不进行四舍五入
     816 
     817 select trunc(123.458) from dual --123
     818 select trunc(123.458,0) from dual --123
     819 select trunc(123.458,1) from dual --123.4
     820 select trunc(123.458,-1) from dual --120
     821 select trunc(123.458,-4) from dual --0
     822 select trunc(123.458,4) from dual --123.458
     823 select trunc(123) from dual --123
     824 select trunc(123,1) from dual --123
     825 select trunc(123,-1) from dual --120
     826 
     827 
     828 4.转换函数
     829 --to_char:日期转换
     830 select to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss') from dual
     831 select to_char(sysdate, 'yyyy-mm-dd hh12:mi:ss') from dual
     832 
     833 --to_char:数字转换
     834 select to_char(-100.789999999999,'L99G999D999') from dual
     835 select to_char(-100000.789999999999,'L99G999D99') from dual
     836 select to_char(-100000.789999999999,'L999G999D99') from dual
     837 
     838 9 代表一位数字,如果当前位有数字,显示数字,否则不显示(小数部分仍然会强制显示)
     839 0 强制显示该位,如果当前位有数字,显示数字,否则显示 0
     840 . (句点)    小数点
     841 , (逗号)    分组(千)分隔符
     842 PR    尖括号内负值
     843 S    带负号的负值(使用本地化)
     844 $     美元符号显示
     845 L    货币符号(使用本地化)
     846 D    小数点(使用本地化)
     847 G    分组分隔符(使用本地化)   10,000
     848 MI    在指明的位置的负号(如果数字 < 0)
     849 PL    在指明的位置的正号(如果数字 > 0)
     850 SG    在指明的位置的正/负号
     851 RN    罗马数字(输入在 1 和 3999 之间)
     852 TH or th    转换成序数
     853 V    移动 n 位(小数)(参阅注解)
     854 EEEE    科学记数。现在不支持。
     855 
     856 
     857 
     858 --to_date:将字符串转换成日期对象
     859 select to_date('2011-11-11 11:11:11', 'yyyy-mm-ddhh24:mi:ss') from dual
     860 
     861 --to_number:将字符转换成数字对象
     862 --字符转换成数字对象
     863 select to_number('209.976')*5 from dual
     864 select to_number('209.976', '9G999D999')*5 from dua
     865 
     866 
     867 5.空值判断函数
     868 --nvl(内容,data):空值函数,类似 SQLServer中的 null()函数,如果内容为空,则值设置为data
     869 select ename,comm,nvl(comm,0) from emp;
     870 
     871 --nvl2(内容,data1,data2):如果内容不为空,则值设置为data1,否则设置为data2
     872 select ename,comm,nvl2(comm,comm+200,200) from emp;
     873 
     874 --nullif(a,b):如果 a,b 的值相等,返回 null,如果不相等,返回a
     875 select nullif(10,10) from dual;    --空,神马都没有
     876 select nullif(10,11) from dual;    --返回 10
     877 
     878 
     879 6.分析函数
     880 --row_number() over (order by 字段 asc|desc):为有序组中的每一行(划分组的行或查询行)返回一个唯一的排序值
     881 select ename,sal,row_number() over(order by sal desc) 名次 from emp;
     882 
     883 --rank() over(order by 字段 asc|desc):排名中如果出现相同的,名次相同,后面的名次跳过相应次数
     884 select ename,sal,row_number() over(order by sal desc) 名次,rank() over(order by sal desc) 名次 from emp;
     885 
     886 --dense_rank() over(order by 字段 asc|desc):排名中如果出现相同的,名次相同,后面的名次不跳过相应次数
     887 select 
     888     ename,
     889     sal,row_number() over(order by sal desc) 名次1,
     890     rank() over(order by sal desc) 名次2, 
     891     dense_rank() over(order by sal desc) 名次3
     892 from emp;
     893 
     894 
     895 
     896 
     897 
     898 
     899 
     900 */
     901 /*
     902 数据库对象
     903 
     904 一、概述
     905 ORACLE数据库是关系型数据库,同时也是面向对象关系型数据库,又称ORDBMS,因此,在 ORACLE 数据库中也有专属的 ORACLE 对象, 主要有如下数据库对象:
     906 1、同义词
     907 2、序列
     908 3、表
     909 4、表分区
     910 5、视图
     911 6、过程
     912 7、索引
     913 
     914 
     915 二、同义词(别名)
     916 1、概念:
     917 同义词是数据库方案对象的一个“别名”,经常用于简化对象访问和提高对象访问的安全性。 
     918 同义词并不占用实际存储空间,只在数据字典中保存了同义词的定义。
     919 Oracle同义词有两种类型,分别是公用 Oracle 同义词与私有 Oracle 同义词。
     920 
     921 2、问题
     922 select * from scott.emp;
     923 
     924 
     925     
     926 --当前登录的session是非scott用户,访问emp表时,必须指定schema.表名
     927 
     928 3、解决:同义词
     929 --创建公用同义词
     930 create public synonym syn_emp for scott.emp;
     931 --通过访问同义词来简化对象的访问
     932 select * from syn_emp;
     933 
     934 4、创建同义词的语法:
     935     create [or replace] [public] synonym sys_name 
     936     for [schema.]object_name
     937 
     938 说明:
     939     create:创建同义词
     940     create or replace:没有则创建,有则替换
     941     public:声明公用同义词,不写则为私有同义词
     942     synonym:关键字
     943     sys_name:用户创建同义词的名称,建议以sys_为前缀
     944     for:关键字
     945     schema:对象的集合,如包含tables, views, sequences, synonyms, indexes等;
     946     一个用户一般对应一个schema,该用户的schema名等于用户名,并作为该用户缺省schema。
     947     
     948     object_name:对象名
     949 
     950 --eg1:公用同义词
     951 create public synonym syn_emp for scott.emp;
     952 select * from syn_emp;
     953 
     954 --eg2:私用同义词
     955 create or replace synonym syn_pri_emp for scott.emp
     956 select * from syn_pri_emp;
     957 
     958 
     959 5、查看同义词
     960 --查看当前用户创建的私有同义词
     961 select * from user_synonyms;
     962 
     963 --查看当前用户创建的所有同义词
     964 select * from all_synonyms where table_owner='SCOTT';
     965 select * from dba_synonyms where table_owner='SCOTT';
     966 
     967 6、删除同义词
     968 drop public synonym 公有同义词名称
     969 
     970 drop synonym 私有同义词名称
     971 
     972 
     973 7、注意事项
     974 1)用户必须拥有 Create public synonym 的系统权限才能创建公共同义词;
     975   只有Create any synonym 权限才能创建私有同义词
     976 
     977   
     978 2)用户必须拥有同义词所定义对象的权限才能进行访问,同义词不代表权限
     979 
     980 3)同义词不仅可以查询,还可以添加,删除,修改,但都作用于物理表
     981 
     982 
     983 
     984 二、序列(自动增长)
     985 1、概念
     986     在oracle中sequence就是所谓的序列号,
     987     每次取的时候它会自动增加,
     988     一般用在需要按序列号排序的地方;
     989     Oracle的序列(SEQUENCE)类似SQLServer中的自动增长列,
     990     用来生成唯一,连续的整数的数据库对象,
     991     序列通常用来生成主键或唯一值,并且可以排序。
     992 
     993     
     994 2、语法:
     995     CREATE SEQUENCE sequence_name
     996     INCREMENT BY 1                     --每次加几个 默认 1
     997     START WITH 1                     --从 1 开始计数 默认 1
     998     [MAXVALUE 值|NOMAXVALUE]         --设置最大值 默认最大 10E27
     999     [MINVALUE 值|NOMINVALUE]         --设置最小值 默认最小-10E26
    1000     [CYCLE|NOCYCLE]                 --一直累加,不循环
    1001     [CACHE 10|NoCYCLE]                 --使序列号预分配
    1002     [Order|NoOrder 默认]
    1003 
    1004 
    1005 eg:
    1006     CREATE SEQUENCE seq_test  
    1007         INCREMENT BY 1          --每次加几个  
    1008         START WITH 1              --从1开始计数  
    1009         NOMAXVALUE              --不设置最大值  
    1010         NOCYCLE                   --一直累加,不循环  
    1011         CACHE 10                  --使序列号预分配10个数,默认NOCACHE
    1012 
    1013 3、访问序列的值
    1014     NEXTVAL:返回序列的下一个值
    1015     CURRVAL:返回序列的当前值
    1016     
    1017     select 序列.nextval from dual
    1018     select 序列.currval from dual
    1019     
    1020     select seq_test.nextval from dual
    1021     select seq_test.currval from dual
    1022 
    1023 4、使用
    1024     insert into 表名(自动增长的字段) values (序列名称.nextval)
    1025 
    1026 5、修改
    1027     alter sequence 序列名称 increment by 2;    
    1028 
    1029     
    1030     alter sequence seq_test increment by 2;    
    1031     --每次加2
    1032     
    1033     1)不能修改序列的初始值
    1034     2)序列的最小值不能大于当前值
    1035     3)序列的最大值不能小于当前值
    1036     
    1037 5、删除序列
    1038   drop sequence 序列名称
    1039 
    1040 
    1041 三、表分区
    1042 1、概述
    1043 在ORACLE中,当表的数据不断增加后,查询数据的速度就会降低,应用程序的效率也将大大下降,每次检索数据时都得扫描整张表,浪费了极大的资源,如何处理超大表数据存储和查询带来的问题, ORACLE 提供了特有的表分区技术。
    1044 
    1045 2、什么是表分区
    1046 ORACLE的表分区是一种处理超大型表,索引等对象的技术,简单可以理解为分而治之,即将一张大表分成可以管理的小块。表分区后逻辑上依然是同一张表,只是将表中的数据在物理上存储到多个(表空间)物理文件上。
    1047 
    1048 3、表分区的优点
    1049 1)增强可用性【一个分区出问题,不影响其他分区】
    1050 2)维护方便【同上,只维护部分分区】
    1051 3)均衡 IO【不同分区映射到磁盘平衡 IO】
    1052 4)改善查询性能【检索自己需要的分区,提高检索速度】
    1053 
    1054 4、分类
    1055 
    1056 4.1)范围分区--最早,最经典,数据管理能力强,但分配不均匀
    1057 
    1058 范围分区就是对数据表中的某个值的范围进行分区,根据某个值的范围,决定将该数据存储在哪个分区上。 
    1059 这种分区方式是最为常用的,并且分区键经常采用日期,数值。
    1060 
    1061 1)语法:
    1062 CREATE TABLE 表名
    1063 (
    1064     字段名1     类型 [约束],
    1065     ...
    1066     字段名n     类型 [约束]
    1067 )
    1068 --表分区的定义
    1069 PARTITION BY RANGE (COLUMN_NAME)
    1070 (
    1071     PARTITION PART1 VALUES LESS THAN (RANG1) [TABLESPACE TBS1],
    1072     
    1073     PARTITION PART2 VALUES LESS THAN (RANG2) [TABLESPACE TBS2],
    1074     
    1075     ...
    1076     
    1077     PARTITION PARTN VALUES LESS THAN (MAXVALUE) [TABLESPACE TBSN],
    1078 );
    1079 
    1080 其中,
    1081     COLUMN_NAME:指定分区字段
    1082     PART1...PARTN:是表分区的名称
    1083     RANG1...MAXVALUE:表分区的边界值,其中MAXVALUE表示边界最大值,每个分区的边界值必须比下一个分区的边界值小。
    1084     TABLESPACE:表空间(可选),指定表分区所在的表空间
    1085     TBS1...TBSN:表分区所在的表空间
    1086 
    1087 注意:
    1088 只能在创建表时创建表分区(指定相关的表分区类型),而不能对现有的表(未创建表分区)创建表分区。
    1089 
    1090 2)例子:
    1091 
    1092 eg1:根据某个值的范围来分区
    1093 
    1094 CREATE TABLE part_andy1
    1095 (
    1096     andy_ID     NUMBER NOT NULL PRIMARY KEY,
    1097     FIRST_NAME  VARCHAR2(30) NOT NULL,
    1098     LAST_NAME   VARCHAR2(30) NOT NULL,
    1099     PHONE       VARCHAR2(15) NOT NULL,
    1100     EMAIL       VARCHAR2(80),
    1101     TATUS       CHAR(1)
    1102 )PARTITION BY RANGE (andy_ID)(
    1103     PARTITION PART1 VALUES LESS THAN (10000) ,
    1104     PARTITION PART2 VALUES LESS THAN (20000)
    1105 );
    1106 
    1107 说明:
    1108     andy_ID字段的数值小于10000分配在PART1分区,
    1109     andy_ID字段的数值大于等于10000且小于20000分配在PART2分区,
    1110     andy_ID字段的数值大于等于20000将会出错,数据无法添加
    1111 
    1112 
    1113 eg2:根据日期分区
    1114 注意:如果是Date类型的字段,则必须使用年份为4个字符的格式,需要使用to_date()函数指定分区边界。
    1115 CREATE TABLE part_andy2
    1116 (
    1117     ORDER_ID          NUMBER(7) NOT NULL,
    1118     ORDER_DATE        DATE,
    1119     OTAL_AMOUNT     NUMBER,
    1120     CUSTOTMER_ID     NUMBER(7),
    1121     PAID               CHAR(1)
    1122 )PARTITION BY RANGE (ORDER_DATE)(
    1123     PARTITION p1 VALUES LESS THAN (TO_DATE('2014-10-1', 'yyyy-mm-dd')) ,
    1124     PARTITION p2 VALUES LESS THAN (TO_DATE('2015-10-1', 'yyyy-mm-dd')) ,
    1125     partition p3 values less than (maxvalue)
    1126 );
    1127 
    1128 说明:
    1129     ORDER_DATE在2014-10-1之前的,分配在p1分区,
    1130     ORDER_DATE大于或等于2014-10-1且小于2015-10-1的,分配在p2分区,
    1131     ORDER_DATE大于或等于2015-10-1,分配在p3分区
    1132 
    1133     
    1134 --课堂作业
    1135 创建一张表(姓名、班级、课程名称、成绩),并使用范围分区对成绩字段划分为以下四个分区:
    1136 不合格:小于60分
    1137 合格:大于等60小于80
    1138 良好:>=80且<90
    1139 优秀:>=90且<=100
    1140     
    1141     
    1142 3)修改分区--分区界限必须调整为高于最后一个分区界限
    1143 ALTER TABLE 表名
    1144     ADD PARTITION 表分区名称 VALUES LESS THAN (值);
    1145     
    1146 alter table part_andy1
    1147     add partition PART3 values less than (30000)
    1148     
    1149 
    1150 4)截断分区--分区中数据将全部删除,但分区依然存在
    1151 alter table 表名 
    1152     truncate partition 分区名;
    1153     
    1154 alter table part_andy1 
    1155     truncate partition PART2;
    1156     
    1157 5)合并分区--将两个相邻分区合并成一个新分区,继承原分区中最高上限(可重用上界限名称,下界限不可以,也可以使用新的)
    1158 alter table 表名 
    1159     merge partitions 分区名1,分区名2 into partition 新分区名或原上界限名称;    
    1160     
    1161 alter table part_andy1 
    1162     merge partitions PART2,PART3 into partition PART3;    
    1163         
    1164 6)拆分分区--将一个分区在指定的 value 值处一分为二,变成 2 个分区,原分区将不存在,数据将分到相应新的分区
    1165 alter table 表名 
    1166     split partition 原表分区 at (value) into (partition 拆分表分区1,partition 拆分表分区1);
    1167 
    1168 
    1169 --查询part_andy1中,表分区PART3的数据
    1170 select * from part_andy1 partition(PART3);
    1171 
    1172 --拆分分区    
    1173 alter table part_andy1 
    1174     split partition PART3 at (20000) into (partition PART31,partition PART32);
    1175 
    1176 --查看
    1177 select * from part_andy1 partition(PART31);
    1178 select * from part_andy1 partition(PART32);
    1179 
    1180 7)变更分区名--将分区名称改变
    1181 alter table 表名 
    1182     rename partition 原分区名 to 新分区
    1183 
    1184 alter table part_andy1 
    1185     rename partition PART31 to PART31_NEW
    1186     
    1187 8)删除分区
    1188 Alter table 表名
    1189     drop partition 分区名    
    1190     
    1191 alter table part_andy1 
    1192     drop partition PART31_NEW
    1193     
    1194 4.2)散列分区--适合静态数据,总体性能最佳,易于实施,均匀
    1195 散列分区是在列值上使用散列算法, 通过在分区键上执行 HASH 函数决定存储的分区,将数据平均地分布到不同的分区,当列的值没有合适的条件时,建议使用散列分区。
    1196 CREATE TABLE EMPLOYEE
    1197 (
    1198     EMP_ID NUMBER(4),
    1199     EMP_NAME VARCHAR2(14),
    1200     EMP_ADDRESS VARCHAR2(15),
    1201     DEPARTMENT VARCHAR2(10)
    1202 )PARTITION BY HASH (DEPARTMENT)
    1203 (
    1204     partition p1,  
    1205     partition p2,  
    1206     partition p3  
    1207 )
    1208 --PARTITIONS 4;
    1209 select * from EMPLOYEE partition(p1);  
    1210 select * from EMPLOYEE partition(p2);  
    1211 select * from EMPLOYEE partition(p3);  
    1212 
    1213 4.3)列表(List)分区
    1214 列表分区的特点是某列的值只有几个,基于这样的特点我们可以采用列表分区,允许用户将不相关的数据组织在一起。
    1215 CREATE TABLE employee
    1216 (
    1217     Emp_ID number(4),
    1218     Emp_Name varchar2(14),
    1219     Emp_Address varchar2 (15)
    1220 )PARTITION BY LIST (Emp_Address)(
    1221     Partition north values ('北京') ,
    1222     Partition west values ('成都','重庆') ,
    1223     Partition south values ('广州', '深圳'),
    1224     Partition east values ('杭州', '苏州','温州')
    1225 );
    1226 
    1227 --添加数据
    1228 insert into employee values(1,'zhangsan','北京');
    1229 insert into employee values(2,'lucy','广州');
    1230 insert into employee values(3,'petter','深圳');
    1231 
    1232 
    1233 --查询数据
    1234 select * from employee partition (north);?    --zhangsan
    1235 select * from employee partition (south);    --lucy、petter
    1236 
    1237 4.4)复合分区:
    1238 形式一:范围-散列分区
    1239 表首先按某列进行范围分区,然后再按散列算法进行散列分区,分区之中的分区被称为子分区
    1240 create table slog
    1241 (
    1242   sno number,
    1243   sinfo varchar(300)
    1244 )partition by range(sno)        --范围分区
    1245 subpartition by hash(sinfo)        --散列分区
    1246 subpartitions 6(
    1247   partition p1 values less than (2000),
    1248   partition p2 values less than (4000),
    1249   partition p3 values less than (6000),
    1250   partition p4 values less than (8000)
    1251 );
    1252 
    1253 形式二:范围-列表分区
    1254 表首先按某列进行范围分区,然后再按某列进行列表分区,分区之中的分区被称为子分区
    1255 create table slog
    1256 (
    1257     sno number,
    1258     sinfo varchar(300)
    1259 )
    1260 partition by range(sno)            --范围分区
    1261 subpartition by LIST(sinfo)        --列表分区
    1262 subpartition template(
    1263     subpartition t1 values('404','NotFind'),
    1264     subpartition t2 values('500','Error'),
    1265     subpartition t3 values('200','Success') 
    1266 )
    1267 (
    1268     partition p1 values less than (2000),
    1269     partition p2 values less than (4000),
    1270     partition p3 values less than (6000),
    1271     partition p4 values less than (8000)
    1272 );
    1273 
    1274 
    1275 4.5)Interval分区
    1276 11G 版本引入的 interval 分区范围分区的一种增强功能,可实现 equi-sized 范围分区的自动化。创建的分区作为元数据,只有最开始的分区是永久分区。随着数据的增加会分配更多的部分,并自动创建新的分区和本地索引
    1277 CREATE TABLE test
    1278 (
    1279     ID NUMBER,
    1280     ORDER_DATE DATE
    1281 ) PARTITION BY RANGE (ORDER_DATE)
    1282 INTERVAL (NUMTOYMINTERVAL(1,'month'))
    1283 (
    1284     PARTITION p_first VALUES LESS THAN (to_date('2013-06-23','yyyy-mm-dd'))
    1285 );
    1286 
    1287 insert into test values(1,to_date('2013-06-22','yyyy-mm-dd'));
    1288 insert into test values(1,to_date('2013-06-23','yyyy-mm-dd'));
    1289 insert into test values(1,to_date('2013-07-20','yyyy-mm-dd'));
    1290 insert into test values(1,to_date('2013-07-24','yyyy-mm-dd'));
    1291 
    1292 select * from test partition (p_first);
    1293 
    1294 ......
    1295 
    1296 5、分区原则
    1297 1)表的大小:当表的大小超过 1.5GB-2GB,或对于 OLTP 系统,表的记录超
    1298 过 1000 万,都应考虑对表进行分区。
    1299 
    1300 2)数据访问特性:基于表的大部分查询应用,只访问表中少量的数据。对于
    1301 这样表进行分区,可充分利用分区排除无关数据查询的特性。
    1302 
    1303 3)数据维护:按时间段删除成批的数据,例如按月删除历史数据。对于这样
    1304 的表需要考虑进行分区,以满足维护的需要。
    1305 
    1306 4)数据备份和恢复: 按时间周期进行表空间的备份时,将分区与表空间建
    1307 立对应关系。
    1308 
    1309 5)只读数据:如果一个表中大部分数据都是只读数据,通过对表进行分区,
    1310 可将只读数据存储在只读表空间中,对于数据库的备份是非常有益的。
    1311 
    1312 6)并行数据操作:对于经常执行并行操作(如 Parallel Insert,Parallel Update
    1313 等)的表应考虑进行分区。
    1314 
    1315 7)表的可用性:当对表的部分数据可用性要求很高时,应考虑进行表分区。
    1316 
    1317 
    1318 
    1319 
    1320 
    1321 */
    1322 
    1323 视图
    1324 /*
    1325 一、概念
    1326 1、视图是一张虚拟的表,此表的结构从一个或多个表(或其它视图)查询的得到的结果一致。
    1327 
    1328 2、视图一经定义,则以对象的方式存储在Oracle数据库中,视图中的数据是来源于查询的基表;对视图的CRUD操作,相应的基表也会发生变化。
    1329 
    1330 3、对视图的更新或者插入限制很多,事实上,除非视图包含的是简单的select语句,
    1331 否则不能通过它来做更新.推荐的做法还是在基表上做更新或者插入操作,
    1332 一般情况下,视图只是用来方便查询的
    1333 
    1334 二、优点:
    1335 1、集中用户使用的数据
    1336 2、掩盖数据库的复杂性
    1337 3、简化用户权限的管理
    1338 4、重新组织数据
    1339 5、不占物理存储空间,它只是一个逻辑对象(虚拟的表)
    1340         
    1341 三、分类
    1342 1、关系视图:
    1343 关系视图(relational view)基本上就是经过存储的查询,可以将它的输出看作是一个表。它就是基于关系数据的存储对象。
    1344 
    1345 2、内嵌视图:
    1346 又称为嵌套查询,是嵌入到父查询中的查询,能够在任何可以使用表名称的地方使用。
    1347 
    1348 3、对象视图:
    1349 为了迎合数据库中对象类型而将关系表投射到特定数据类型的虚拟对象表中,视图的每行都是带有属性、方法和唯一标识(OID)的对象实例。
    1350 
    1351 4、物化视图:
    1352 就是在数据库中查询结果存储在视图中,并支持查询重写、刷新、提交等特性的视图
    1353     
    1354     
    1355 四、创建视图的步骤:
    1356 1、编写select语句
    1357 2、测试select语句
    1358 3、查询结果的正确性
    1359 4、创建视图
    1360     
    1361 注意:
    1362 1)普通用户并没有创建视图的权限,如果要创建视图,需要使用 dba 角色的用户赋予 create view 的权限,如:
    1363 
    1364     grant create view to scott;
    1365 
    1366 2)查看视图:User_views,All_views,Dba_views     
    1367     
    1368 五、语法:
    1369     CREATE [OR REPLACE] [FORCE] VIEW view_name [(alias[, alias]...)]
    1370     AS 
    1371     select_statement
    1372     [WITH CHECK OPTION [CONSTRAINT constraint]]
    1373     [WITH READ ONLY]
    1374     
    1375 其中: 
    1376 OR REPLACE:若所创建的试图已经存在,ORACLE自动重建该视图; 
    1377 FORCE:不管基表是否存在ORACLE都会自动创建该视图; 
    1378 NOFORCE:只有基表都存在ORACLE才会创建该视图(默认): 
    1379 alias:为视图产生的列定义的别名; 
    1380 select_statement:一条完整的SELECT语句,可以在该语句中定义别名; 
    1381 WITH CHECK OPTION : 插入或修改的数据行必须满足视图定义的约束; 
    1382 WITH READ ONLY : 该视图上不能进行任何DML操作。 
    1383 
    1384 六、关系视图
    1385 1、创建普通关系视图,并对其进行DML操作
    1386 create table emp1
    1387 as
    1388 select * from emp;
    1389 
    1390 create view view_emp1
    1391 as 
    1392 select * from emp1 
    1393 
    1394 update view_emp1 set sal=1000 where empno=7369
    1395 
    1396 2、创建只读视图
    1397 特点:只读,不能执行其他 DML 操作
    1398 create or replace view view_emp11 
    1399 as 
    1400 select * from emp1 where sal>=3000 with read only;
    1401 
    1402 --执行删除操作
    1403 delete from view_emp11;    --错误
    1404 
    1405 
    1406 3、创建检查视图
    1407 特点:执行 DML 操作时,自动检测是否满足创建视图时所建立的 where 条件,如果不满足,直接出错
    1408 create or replace view view_emp11 
    1409 as 
    1410 select * from emp1 
    1411 where sal>=3000 with check option;
    1412 
    1413 update view_emp11 set sal=4000 where empno=7902    --正确
    1414 update view_emp11 set sal=1000 where empno=7902    --错误
    1415 
    1416 
    1417 4、创建连接视图        
    1418 特点:连接视图是指基于多个表所创建的视图,即定义视图的查询是一个连接查询。使用连接视图的主要目的是为了简化连接查询。【 只能更新键保留表】
    1419 create or replace view view_emp_dept
    1420 as
    1421 select e.*,d.dname,d.loc
    1422 from emp e,dept d 
    1423 where e.deptno=d.deptno
    1424 
    1425 update view_emp1_dept1 set sal=2450 where empno=7782    --正确
    1426 update view_emp1_dept1 set dname='aaa' where empno=7782    --错误
    1427 
    1428 注意:emp的主键在视图中作为主键,则emp是键保留表,而dept是非键保留表。
    1429 在连接视图中,oracle规定可以更新键保留表。 因此,可以更新emp表中的数据,不能更新dept表中的数据。
    1430 
    1431 5、创建复杂视图
    1432 特点: 复杂视图是指包含函数、表达式或分组数据的视图,主要目的是为了简化
    1433 查询
    1434 create or replace view view_emp 
    1435 as 
    1436 select count(*) 人数,avg(sal+nvl(comm,0)) 平均工资,deptno 部门编号 
    1437 from emp 
    1438 group by deptno;
    1439 
    1440 6、创建强制视图
    1441 特点:正常情况下,如果基表不存在,创建视图就会失败。但是可以使用 FORCE选项强制创建视图(前提是创建视图的语句没有语法错误),但此时该视图处于失效状态,调用会出错,直到这个基表已经存在
    1442 
    1443 create or replace force view view_test 
    1444 as select * from myemp;
    1445 
    1446 select * from myemp;    --错误
    1447 
    1448 create table myemp        --创建myemp表
    1449 as 
    1450 select * from emp ;
    1451 
    1452 select * from myemp;    --正确
    1453 
    1454 课堂练习
    1455 1、创建一个视图,以便于查询薪水大于2000的员工信息
    1456 
    1457 2、创建一个视图,以便于查询部门为SALES的员工信息,及部门所在地
    1458 
    1459 3、修改某数据测试是否成功
    1460 
    1461 七、内嵌视图
    1462 内嵌视图又称为嵌套查询嵌视图。
    1463 可以出现在 SELECT 语句的 FROM 子句中,以及INSERT INTO、 UPDATE、甚至是 DELETE FROM 语句中。
    1464 内嵌视图是临时的,它只存在于父查询的运行期间。
    1465 eg:
    1466 select * from (select e.*,rownum rn from emp e) tab 
    1467 where rn>=5 and rn<=10;
    1468 其中: select e.*,rownum rn from emp e 就是一个内嵌视图,临时有效
    1469 
    1470 
    1471 八、物化视图
    1472 1、概述
    1473 物化视图简单理解就是一张特殊的物理表,预先计算并保存表连接或统计中需要耗时较多的操作的结果。物化视图也称为”快照”。
    1474 
    1475 物化视图可以定时更新视图中的数据,对于大量数据统计查询后得出的
    1476 小量结果集这种情况比较适合。
    1477 
    1478 物化视图可以查询表,视图和其它的物化视图。
    1479 
    1480 我们可以通过 user_segments 查看用户创建对象所在资源情况。
    1481 
    1482 2、物化视图的作用
    1483 1)实现两个数据库之间的数据同步,可以存在时间差。
    1484 
    1485 2)如果是远程链接数据库的场景时,提高查询速度。(由于查询逻辑复杂,数据量比较大,导致每次查询视图的时候,查询速度慢,效率低下)
    1486 
    1487 3、分类
    1488 1)包含聚集的物化视图
    1489 2)只包含连接的物化视图
    1490 3)嵌套物化视图
    1491 
    1492 注意:
    1493 无论哪种视图,都需要设置物化视图的创建方式、 查询重写、 刷新方式等
    1494 几个方面的功能选项。
    1495 
    1496 1)创建方式(Build Methods)
    1497 build immediate:是在创建物化视图的时候就生成数据。 默认为build immediate。
    1498 
    1499 build deferred:是在创建时不生成数据,以后根据需要在生成数据
    1500 
    1501 2)查询重写( Query Rewrite)
    1502 查询重写(ENABLE QUERY REWRITE):指当对物化视图的基表进行查询时,Oracle 会自动判断能否通过查询物化视图来得到结果,如果可以,则避免了聚集或连接操作,而直接从已经计算好的物化视图中读取数据。
    1503 
    1504 不查询重写(DISABLE QUERY REWRITE):指当对物化视图的基表进行查询时, Oracle不会判断能否通过查询物化视图来得到结果,直接对基表进行查询数据而不从物化视图中读取数据。 默认为DISABLE QUERY REWRITE。
    1505 
    1506 3)刷新(Refresh)方式【自动 on commit,手动】
    1507 刷新的方法有四种: FAST、 COMPLETE、 FORCE 和 NEVER。 默认值是 FORCE。
    1508 
    1509 刷新的模式有两种: ON DEMAND 和 ON COMMIT。 默认值是 ON DEMAND
    1510 
    1511 
    1512 4、创建视图日志文件
    1513 CREATE MATERIALIZED VIEW LOG ON
    1514 <table_name>
    1515 [TABLESPACE <tablespace_name>]             --视图日志保存位置
    1516 [WITH [PRIMARY KEY|ROWID|SEQUENCE ];    --标示基表每一行
    1517 [including new values]
    1518 
    1519 注意:如果设置刷新方法为 fast,必须先构建一个基于基表的视图日志。
    1520 
    1521 eg:
    1522 create materialized view log on emp with rowid
    1523 
    1524 5、创建物化视图语法
    1525 CREATE MATERIALIZED VIEW [mv_name]
    1526 [
    1527 TABLESPACE [ts_name]                 -- 指定表空间
    1528 BUILD [IMMEDIATE|DEFERRED]             -- 创建时是否产生数据
    1529 REFRESH [FAST|COMPLETE|FORCE]         -- 快速、完全刷新
    1530 [ON COMMIT|ON DEMAND START WITH (start_time) NEXT (next_time)]     -- 刷新方式
    1531 [WITH {PRIMARY KEY |ROWID}]         --快速刷新时候唯一标示一条记录
    1532 {ENABLE|DISABLED} QUERY REWRITE     -–是否查询重写
    1533 ]
    1534 AS {select_statement};
    1535 
    1536 eg1:
    1537 create materialized view my_view
    1538 build immediate
    1539 refresh fast on commit
    1540 with rowid
    1541 as
    1542 select empno,ename,sal from emp where sal>=3000;
    1543 
    1544 eg2:
    1545 create materialized view my_view
    1546 build immediate 
    1547 refresh 
    1548 on commit 
    1549 enable query rewrite 
    1550 as
    1551 select deptno,count(*) amount from myemp group by deptno;
    1552 
    1553 eg3:
    1554 create materialized view my_view 
    1555 refresh 
    1556 start with sysdate next sysdate+1/48 
    1557 with rowid
    1558 as
    1559 select count(*),avg(sal+nvl(comm,0)) sals from myemp;
    1560 
    1561 6、删除物化日志文件
    1562 drop materialized view log on empd
    1563 
    1564 7、删除物化视图
    1565 drop materialized view my_view;    
    1566 
    1567 
    1568 
    1569 九、常用系统视图
    1570 1、USER_*:有关用户所拥有的对象信息,即用户自己创建的对象信息。
    1571 1)Select * from user_users;            --查看当前用户信息
    1572 2)Select * from user_tables;        --查看当前用户创建表信息
    1573 3)Select * from user_views;            --查看当前用户创建视图信息
    1574 4)select * from user_tab_privs;        -—查看当前用户表权限
    1575 5)select * from user_sys_privs;        --查看当前用户系统
    1576 6)select * from user_role_privs;    --查看当前用户角色
    1577 
    1578 2、ALL_*: 有关用户可以访问的对象的信息,即用户自己创建的对象的信息
    1579 加上其他用户创建的对象但该用户有权访问的信息。
    1580 
    1581 3、DBA_*: 有关整个数据库中对象的信息。这里的 *可以为 TABLES,
    1582 INDEXES, OBJECTS, USERS 等。
    1583 
    1584 4、V$*:一般是动态视图,随着客户端或参数值设定的不同而不
    1585 
    1586 
    1587 
    1588 */
    1589 PL/SQL
    1590 一、概述
    1591 1、概念
    1592     是oracle在标准的 sql 语言上的扩展 。
    1593     实现具体的业务功能。
    1594 
    1595 2、组成
    1596     1)procedural language:过程语言
    1597     2)SQL(struts Query language):结构化查询语言
    1598 
    1599 3、PL/SQL块 -> PL/SQL代码的集合
    1600     逻辑上相关的声明和语句组合在一起
    1601     块(block)是 pl/sql 的基本程序单元。
    1602 
    1603 4、PL/SQL块分类
    1604 匿名块
    1605 非匿名块
    1606     
    1607 注意:
    1608     在块中不能直接使用 DDL 语句,
    1609     但可以通过动态 SQL 来解决。
    1610 
    1611 二、PL/SQL块的三大结构:声明部分、可执行部分、异常部分
    1612 语法:
    1613 
    1614 declare     --声明部分(可省略)
    1615     变量/常量的定义
    1616     
    1617 begin        --可执行部分,由begin开始,end结束,end后必须加分号,实现具体的功能业务
    1618     ...
    1619 
    1620 
    1621 exception    --异常处理(可省略)
    1622     ...
    1623 end;
    1624 
    1625 
    1626 
    1627 void main() {
    1628 
    1629 }
    1630 
    1631 public static void main(String[] args) {
    1632 
    1633 }
    1634 
    1635 public xxx extends HttpServlet {
    1636     public void service() {
    1637     
    1638     }
    1639 }
    1640 
    1641 
    1642 
    1643 
    1644 说明:
    1645 1)各语句必须以分号结束
    1646 
    1647 2)变量的定义 - declare关键字下定义
    1648 变量名称 数据类型 
    1649 变量名称 数据类型 not null default--not null 必须指定默认值
    1650 变量名称 数据类型 :=--定义变量时指定默认值(方式一)
    1651 变量名称 数据类型 default--定义变量时指定默认值(方式二)
    1652 
    1653 注:赋值运算符为   :=
    1654 
    1655 eg1:
    1656 declare 
    1657      name varchar2(30);
    1658      name := '张三11' ; --错误
    1659 begin
    1660      name := '张三11' ;
    1661   dbms_output.put_line('你好,' || name) ;
    1662 end;
    1663 
    1664 eg2:
    1665 declare 
    1666     name varchar2(30) not null default '匿名' ;
    1667 begin
    1668     name := '张三'   ;
    1669     dbms_output.put_line('你好,' || name) ;
    1670 end;
    1671 
    1672 eg3:
    1673 declare //定义
    1674     name varchar2(30) not null default '匿名' ;
    1675     sex char(2) := '' ;
    1676     age number(3) default 18 ;
    1677 begin
    1678     name := '张三'   ;
    1679     dbms_output.put_line('姓名:' || name) ;
    1680     dbms_output.put_line('性别:' || sex) ;
    1681     dbms_output.put_line('年龄:' || age) ;
    1682 end;
    1683 
    1684 
    1685 3)常量的定义:常量在定义时必须赋初始值
    1686 常量名 constant 数据类型 ; --错误
    1687 
    1688 常量名 constant 数据类型 := 常量值
    1689 
    1690 常量名 constant 数据类型 default 常量值
    1691 
    1692 
    1693 4)给变量赋值
    1694 方式一:使用赋值运算符,把具体的数值赋值给变量/常量
    1695     变量名称 :=/表达式 ;
    1696 
    1697 方式二:select into,把查询的数据动态的给变量赋值
    1698 select 字段 into 变量名 from 表名 [where 条件];
    1699 
    1700 select 字段1,...,字段n into 变量名1,...,变量n from 表名 [where 条件];
    1701 
    1702 
    1703 5&符号:代表由用户根据提示手动输入数据  -> 输入
    1704 &提示内容
    1705 declare
    1706     变量名 varchar2 = '&提示内容' ;
    1707 
    1708 declare
    1709 name varchar2(4);    --name超过4个字符会出错,解决使用%type或定义足够长的字符
    1710 begin
    1711   select ename into name from emp where empno=&员工编号;
    1712   dbms_output.put_line('姓名为:'||name);
    1713 end;
    1714 
    1715 6%type:定义变量的数据类型和长度与数据表某列的一致
    1716 语法:变量 表名.字段%type
    1717 
    1718 declare
    1719 name emp.ename%type;
    1720 begin
    1721   select ename into name from emp where empno=&员工编号;
    1722   dbms_output.put_line('姓名为:'||name);
    1723 end;
    1724 
    1725 7%rowtype:返回一个记录类型,其数据类型和数据表的数据结构一致
    1726 语法:变量 表名%rowtype
    1727 
    1728 访问数据:
    1729     变量.字段
    1730 
    1731 declare 
    1732   obj emp%rowtype;
    1733 begin
    1734   select * into obj from emp where empno = 7369;
    1735   dbms_output.put_line('姓名='|| obj.ename);
    1736   dbms_output.put_line('岗位='|| obj.job);
    1737   dbms_output.put_line('薪水='|| obj.sal);
    1738 end;
    1739 
    1740 
    1741 declare
    1742   v_no emp.empno%type := &empno;    --用户输入员工编号
    1743   rec emp%rowtype;                    --rec为记录
    1744 begin
    1745   select * into rec from emp where empno=v_no;
    1746   dbms_output.put_line('姓名:'||rec.ename||' 工资:'||rec.sal);
    1747 end;
    1748 
    1749 8)异常
    1750     zero_divide
    1751     case_not_found
    1752     ...
    1753     
    1754     when 异常种类 then
    1755         ...
    1756 
    1757 
    1758 三、数据类型
    1759 1、标量数据类型
    1760 标量类型是非常常用的一种类型,没有内部组件,仅包含单个值,主要包括 numbercharacter,date/time,boolean 类型
    1761 
    1762 declare 
    1763     变量 标量数据类型 
    1764     ...
    1765 
    1766 
    1767 2、LOB 数据类型
    1768 
    1769 3、组合【复合】数据类型
    1770 1)record:用来存储多个值的变量称之为组合或者复合变量,其中存储的多个值可以是 PL/SQL 记录,也可以是 PL/SQL 中的表
    1771 
    1772 declare
    1773     type 组合类型名称 is record    --创建一个组合类型
    1774     (
    1775         变量1 数据类型 ,
    1776         ...
    1777         变量n 数据类型
    1778     );
    1779     
    1780     age number(3,2) ;
    1781     
    1782     组合类型变量 组合类型名称 ;    --定义一个组合类型的变量
    1783 
    1784     
    1785 begin
    1786     select 字段1,...,字段n into 组合类型的变量 from 表名 where ... ;
    1787     ...
    1788 end;
    1789 
    1790 
    1791 
    1792 declare
    1793   type emp_mytype is record
    1794   (
    1795     name emp.ename%type,
    1796     job emp.job%type,
    1797     sal number(10,2)
    1798   );
    1799   
    1800   einfo emp_mytype;
    1801 
    1802 begin
    1803   select ename,job,sal into einfo from emp where empno=7788;
    1804   dbms_output.put_line('姓名:'||einfo.name||' 岗位:'||einfo.job||' 待遇:'||einfo.sal);
    1805 end;
    1806 
    1807 
    1808 不足之处:一次只能存储一条记录的值
    1809 
    1810 
    1811 2table
    1812 
    1813 declare
    1814   type 组合类型名称 is table of 数据类型 [index by binary_integer];
    1815   
    1816   组合类型变量 组合类型名称;
    1817   
    1818 begin
    1819   select 字段 into 组合类型变量(下标1) from 数据表 where ...;
    1820   ...
    1821   select 字段 into 组合类型变量(下标2) from 数据表 where ...;
    1822   
    1823 end;
    1824 
    1825 注:
    1826     下标可以任意的整数(负数,无上下限)
    1827     
    1828     index by binary_integer : 下标自动增长,并不需要每次使用extend增加一个空间
    1829 
    1830 eg1:使用by binary_integer
    1831 declare
    1832   type my_table is table of emp.ename%type index by binary_integer;
    1833   
    1834   einfo my_table;        --不需要初始化
    1835 begin
    1836   --不必须使用extend增加一个空间且下标可以任意整数
    1837   select ename into einfo(-1) from emp where empno=7788;    
    1838   select ename into einfo(-2) from emp where empno=7900;
    1839   select ename into einfo(-3) from emp where empno=7902;
    1840   
    1841   dbms_output.put_line('姓名 1:'||einfo(-1)||'姓名 2:'||einfo(-2)||'姓名 3:'||einfo(-3));
    1842 end;
    1843 
    1844 
    1845 
    1846 
    1847 
    1848 eg2:不使用by binary_integer
    1849 declare
    1850   type my_table is table of emp.ename%type ;
    1851   einfo my_table := my_table() ;    --必须初始化
    1852 begin
    1853   einfo.extend;                        --必须使用extend增加一个空间且下标从1开始
    1854   select ename into einfo(1) from emp where empno=7788;
    1855   
    1856   einfo.extend;
    1857   select ename into einfo(2) from emp where empno=7900;
    1858   
    1859   einfo.extend;
    1860   select ename into einfo(3) from emp where empno=7902;
    1861   
    1862   dbms_output.put_line('姓名 1:'||einfo(1)||'姓名 2:'||einfo(2)||'姓名 3:'||einfo(3));
    1863 end;
    1864 
    1865 
    1866 
    1867 
    1868 eg3:可以使用bulk collect一次将符合条件的数据全部写入表中
    1869 declare
    1870   type my_table is table of emp.ename%type index by binary_integer;
    1871   einfo my_table;
    1872 begin
    1873   select ename bulk collect into einfo from emp ;
    1874   for i in 1 .. einfo.count        --count返回表的记录数
    1875     loop
    1876       dbms_output.put_line(einfo(i));
    1877     end loop;
    1878 end;
    1879 
    1880 
    1881 
    1882 eg4:record与table组合类型的混合应用
    1883 
    1884 declare
    1885 --第一:自定义组合类型 - recod
    1886 type myrecord is record (
    1887      mname emp.ename%type ,
    1888      mjob emp.job%type
    1889 ) ;
    1890 
    1891 --第一:自定义组合类型 - table
    1892 type myType is table of myrecord index by binary_integer ;
    1893 
    1894 --第二:创建组合类型的变量
    1895 einfo myType ;
    1896 
    1897 begin
    1898   --第二:给组合类型变量赋值  
    1899   select ename,job into einfo(1) from emp where empno=7369 ;
    1900   select ename,job into einfo(2) from emp where empno=7499 ;
    1901   select ename,job into einfo(3) from emp where empno=7521 ;
    1902   
    1903   dbms_output.put_line('第一个姓名:' || einfo(1).mname || ' 职位' || einfo(1).mjob) ;
    1904   dbms_output.put_line('第二个姓名:' || einfo(2).mname || ' 职位' || einfo(2).mjob) ;
    1905   dbms_output.put_line('第三个姓名:' || einfo(3).mname || ' 职位' || einfo(3).mjob) ;
    1906 end;
    1907 
    1908 
    1909 
    1910 4、引用【参照】数据类型
    1911 
    1912 
    1913 四、程序控制语句
    1914 1、条件
    1915 1if
    1916 
    1917 if 条件 then
    1918     代码块;
    1919 end if;
    1920 
    1921 if(条件) {
    1922     代码块 ;
    1923 }
    1924 
    1925 注:条件一般是逻辑运算符或关系运算符或混合
    1926 
    1927 --输入年龄,判断是否大于18岁,如果大于18岁,则输出可以去网吧。
    1928 
    1929 2)if...else
    1930 
    1931 if 条件 then
    1932     代码块 ;
    1933 else 
    1934     代码块 ;
    1935 end if;
    1936 
    1937 
    1938 --输入年龄,判断是否大于18岁,如果大于18岁,则输出可以去网吧,否则输出不可以去网吧。
    1939 
    1940 3if..else if..
    1941 if 条件1 then
    1942     代码块1 ;
    1943 elsif 条件2 then
    1944     代码块2 ;
    1945 elsif 条件3 then
    1946     代码块3 ;
    1947 else 
    1948     代码块n
    1949 end if;
    1950 
    1951 --输入成绩,判断成绩的等级
    1952 0-60:不及格
    1953 60-70:及格
    1954 70-80:中等
    1955 80-90:良好
    1956 90-100:优秀
    1957 其它:输入的成绩有误
    1958 
    1959 
    1960 4case
    1961 case
    1962     when 条件1 then 
    1963         语句块1 ;
    1964     ...
    1965     when 条件n then 
    1966         语句块n ;
    1967     else
    1968         语句块n+1 ;
    1969 end case ;
    1970 
    1971 --使用case改写以上的练习
    1972 --判断今天是星期几
    1973     如果是周1-5,打印输出"好好学习,天天向上"
    1974     如果是周六,打印输出"睡个懒觉,醒了去外面玩玩"
    1975     如果是周日,打印输出"复习、做作业"
    1976 
    1977 
    1978 2、循环
    1979 1)loop
    1980 loop 
    1981     要执行的语句(循环体);
    1982     exit when <条件语句>     --条件满足,退出循环语句
    1983 end loop;
    1984 
    1985 其中: 
    1986 exit when 子句是必须的,否则循环将无法停止。
    1987 
    1988 
    1989 --循环打印输出1-10的数据
    1990 
    1991 
    1992 2)while
    1993 WHILE 条件 
    1994 LOOP 
    1995     要执行的语句;
    1996 END LOOP;
    1997 
    1998 其中:
    1999WHILE 循环语句中仍然可以使用 EXITEXIT WHEN 子句
    2000 
    2001 --使用while语句实现变量v_num从1到10的循环,打印输出v_num的值,如果v_num=8退出循环。
    2002 
    2003 3)for
    2004 for 循环变量 in [ REVERSE ] 下限 .. 上限 
    2005 LOOP 
    2006     要执行的语句;
    2007 END LOOP;
    2008 
    2009 其中:
    2010 每循环一次,循环变量自动加 1;使用关键字 REVERSE,循环变量自动减 1
    2011 跟在 IN REVERSE 后面的数字必须是从小到大的顺序,但不一定是整数,可以是能够转换成整数的变量或表达式
    2012 可以使用 EXIT WHEN 子句退出循环
    2013 
    2014 
    2015 4)特殊语句
    2016 exit    -- 相当于高级语言中的break 
    2017 continue
    2018 
    2019 exit when 条件
    2020 continue when 条件
    2021 
    2022 
    2023 五、动态SQL语句
    2024 
    2025 
    2026 
    2027 六、异常处理
    2028 
    2029 
    2030 
    2031 五、动态SQL语句  
    2032 1、概述
    2033 在 PL/SQL 块中,可以执行 DML 和 TCL,但是不可以直接执行 DDL 以及 DCL,如果想在块中使用,必须使用动态 SQL。
    2034 
    2035 --在PL/SQL块执行DDL操作
    2036 begin
    2037   drop table stu ;
    2038 end;
    2039 
    2040 2、动态SQL的两种实现(分类):
    2041 本地动态 SQL
    2042 DBMS_SQL包
    2043 
    2044 3、本地动态SQL
    2045 1)语法:
    2046 
    2047 Execute immediate dynamic_sql_string
    2048 [into define_variable_list]
    2049 [using bind_argument_list]
    2050 
    2051 说明:
    2052 dynamic_sql_string:动态执行的SQL语句
    2053 define_variable_list:用于接受 select 查询记录值的变量列表
    2054 bind_argument_list:绑定输入参数的列表
    2055 
    2056 2)例子
    2057 --eg1:动态的执行DDL语句
    2058 declare 
    2059     str_sql varchar(300) ;
    2060 begin
    2061   str_sql := 'drop table stu' ;
    2062   execute immediate str_sql;
    2063 end;
    2064 
    2065 --eg2:接受 select 查询记录值的变量列表
    2066 declare 
    2067     str_sql varchar(300) ;
    2068     row_line emp%rowtype ;
    2069 begin
    2070   str_sql := 'select * from emp where empno=' || &工号 ;
    2071   execute immediate str_sql into row_line;
    2072   dbms_output.put_line('姓名:' || row_line.ename);
    2073 end;
    2074 
    2075 
    2076 
    2077 --eg3:绑定输入参数的列表
    2078 1>设置占位符-> :1、:2、...、:n
    2079 2>动态传入参数 -> using 参数值1,...,参数值n
    2080 
    2081 create table stu (
    2082     name varchar2(30) ,
    2083     age number(3) ,
    2084     sex char(2)
    2085 )
    2086 
    2087 declare
    2088     str_sql varchar2(100) ;
    2089 begin
    2090     str_sql := 'insert into stu values (:1,:2,:3)' ;
    2091     execute immediate str_sql using '张三',18,'';
    2092     commit;
    2093 end;
    2094 
    2095 select * from stu ;
    2096 
    2097 
    2098 4、DBMS_SQL 包执行动态 SQL
    2099 1)步骤
    2100 第一:构建动态 SQL 语句
    2101 
    2102 第二:打开游标
    2103 
    2104 第三:使用 DBMS_SQL 包的 parse 过程来分析字符串
    2105 
    2106 第四:使用 DBMS_SQL 包的 bind_variable 过程来绑定变量
    2107 
    2108 第五:使用 DBMS_SQL 包的 execute 函数来执行语句并返回受影响的行
    2109 
    2110 
    2111 第六:关闭游标
    2112 
    2113 2)例子
    2114 declare
    2115   table_name varchar2(50):='&table_name';
    2116   str_sql varchar2(500);
    2117   v_cursor number;
    2118   v_row int;
    2119 begin
    2120   --第一:构建动态DDL语句
    2121   str_sql:='delete from ' || table_name || ' where name=:1';
    2122   --第二:为处理打开游标
    2123   v_cursor:=dbms_sql.open_cursor;
    2124   --第三:分析语句 -- dbms_sql.native指定语句的行为(根据版本)
    2125   dbms_sql.parse(v_cursor,str_sql,dbms_sql.native);
    2126    --第四:绑定变量
    2127   dbms_sql.bind_variable(v_cursor,':1','张三');
    2128   --第五:执行语句[DDL语句,该操作可以省略]
    2129   v_row:=dbms_sql.execute(v_cursor);
    2130   --第六:关闭游标
    2131   dbms_sql.close_cursor(v_cursor);
    2132   dbms_output.put_line('删除表中的数据,受影响行为:' || v_row);
    2133 end;
    2134 
    2135 
    2136 
    2137 六、异常处理
    2138 1、预定义异常
    2139 declare
    2140   v_name varchar2(30);
    2141 begin
    2142   select ename into v_name from emp; --where empno=73691;
    2143   dbms_output.put_line('姓名:' || v_name) ;
    2144   
    2145   exception
    2146     when TOO_MANY_ROWS then
    2147          dbms_output.put_line('返回多行');
    2148     when no_data_found then --可以有多个 when
    2149          dbms_output.put_line('没有查询到数据');
    2150     when others then --可选
    2151          dbms_output.put_line('未知异常,错误号'||sqlcode||',错误信息'||sqlerrm);
    2152  
    2153 end;
    2154 
    2155 2、非预定异常
    2156 declare
    2157   v_i int;
    2158   my_math exception;   --定义一个异常名
    2159   pragma exception_init(my_math,-1476);     --将异常名与 Oracle 错误码绑定
    2160 begin
    2161   v_i := 10/0;         --将出现异常
    2162   exception
    2163     --when my_math then    --除数为 0 异常将被处理
    2164       --dbms_output.put_line('除数不能为 0! ');
    2165     when others then
    2166       dbms_output.put_line('未知异常,错误号'||sqlcode||',错误信息'||sqlerrm);
    2167 end;
    2168 
    2169 
    2170 
    2171 3、用户定义异常
    2172 eg1:
    2173 declare
    2174   myexception exception;   --定义一个异常名
    2175   age int;
    2176 begin
    2177   age:=&age;
    2178   
    2179   if age<18 or age>36 then
    2180     raise myexception;        --手动抛出异常
    2181   else
    2182     dbms_output.put_line('您输入的年龄是' || age);
    2183   end if;
    2184   
    2185   exception
    2186     when myexception then   --处理异常
    2187       dbms_output.put_line('年龄不符合标准');
    2188 end;
    2189 
    2190 
    2191 
    2192 eg2:抛出应用程序异常:raise_application_error
    2193 declare
    2194   age int;
    2195 begin
    2196   age:=&age;
    2197   if age<18 or age>36 then
    2198     raise_application_error(-20001,'你输入的数据'||age||'超出了合适的范围!'); --手动抛出系统异常
    2199   else
    2200     dbms_output.put_line('您输入的年龄是'|| age);
    2201   end if;
    2202 end;
    2203 
    2204 
    2205 eg3:
    2206 declare
    2207   age int;
    2208   myexeption exception;--定义异常名
    2209   pragma exception_init(myexeption,-20001);--将异常名与系统错误号绑定
    2210 begin
    2211   age:=&age;
    2212   
    2213   if age<18 or age>36 then
    2214     raise_application_error(-20001,'你输入的数据'||age||'超出了合适的范围!'); --手动抛出系统异常
    2215   else
    2216     dbms_output.put_line('您输入的年龄是'|| age);
    2217   end if;
    2218   
    2219   exception
    2220     when myexeption then
    2221       --在自定义异常时,函数 sqlcode 与 sqlerrm 可以用来显示错误号与错误信息
    2222       dbms_output.put_line('出错了,错误号:'||sqlcode||',错误信息:'||sqlerrm);
    2223 end;
    2224 
    2225 存储过程
    2226 一、子程序
    2227     一个命名的 PL/SQL 块,编译并存储在数据库中。
    2228     
    2229     PL/SQL块可以实现复杂的业务逻辑,但只是临时的,只能用一次;
    2230     而子程序把实现业务逻辑的PL/SQL块进行命名,存储在数据库中,便于重复使用。
    2231 
    2232 二、子程序的结构
    2233     子程序的结构和普通的PL/SQL块是一致的,也包括如下部分:
    2234      
    2235     声明部分
    2236      可执行部分
    2237      异常处理部分
    2238 
    2239     
    2240 三、子程序的分类
    2241     存储过程
    2242     函数
    2243     
    2244 四、优点
    2245      模块化【将程序分解为逻辑模块】
    2246      可重用性【可以被任意数目的程序调用】
    2247      可维护性【简化维护操作】
    2248      安全性【通过设置权限,使数据更安全】
    2249 
    2250 五、存储过程
    2251 1、概念
    2252     过程是用于完成特定任务的子程序,通过使用过程不仅可以简化客户端应用程序的开发和维护,而且还可以提高应用程序的运行性能。
    2253 
    2254 2、语法
    2255 --创建过程,可指定运行过程需传递的参数
    2256 create [or replace] procedure 存储过程名 [(参数列表)]
    2257 is|as 
    2258    [变量/常量的定义]              
    2259 begin
    2260    可执行的语句部分              --具体的业务逻辑功能的实现
    2261 [exception
    2262    异常的具体处理
    2263 ]              
    2264 end;
    2265 
    2266 注意事项:
    2267 1)过程体内不能使用查询语句,只能用于赋值(SQL语句块都如此)
    2268 2)如果过程体语句有错误也能创建成功
    2269 3)没有参数就不写,不用()
    2270 4)参数列表,语法如下
    2271   参数名 in/out 数据类型,...
    2272 5)在调用存储过程时,也可以通过"=>"给参数赋值。
    2273     输入/输出参数名=>2274 
    2275 3、hello,world
    2276 --创建
    2277 create or replace procedure sayhello
    2278 as             
    2279 begin
    2280    dbms_output.put_line('hello,world') ;    
    2281 end;
    2282 
    2283 --调用
    2284 begin
    2285     sayhello();
    2286 end;
    2287 
    2288 4、调用
    2289 exec 存储过程名[(实参列表)] ;
    2290 
    2291 2292 
    2293 begin
    2294     存储过程名称[(实参列表)] ;
    2295 end;
    2296 
    2297 
    2298 5、输入/输出参数
    2299 in : 输入参数(默认)
    2300 out: 输出参数
    2301 
    2302 
    2303 6、例子
    2304 1)无输入参数、无输出参数
    2305 --创建
    2306 create or replace procedure sum1
    2307 as
    2308   a number := 1 ;
    2309   b constant number := 1 ;      
    2310 begin
    2311    dbms_output.put_line(a+b) ;  
    2312 end;
    2313 
    2314 --调用
    2315 begin 
    2316     sum1;
    2317 end;
    2318 
    2319 
    2320 2)有输入参数、无输出参数
    2321 --创建(参数默认是输入参数)
    2322 create or replace procedure sum2(a in number,b number)
    2323 as
    2324   c number := 3 ;     
    2325 begin
    2326    dbms_output.put_line(a+b+c) ;  
    2327 end;
    2328 
    2329 --调用
    2330 begin 
    2331     sum2(1,2);
    2332 end;    
    2333 
    2334 3、无参有返
    2335 --创建
    2336 create or replace procedure sum3(s out number)
    2337 as
    2338   a number := 1 ;
    2339   b number := 2 ;
    2340   c number := 3 ;     
    2341 begin
    2342    s := a + b + c ;  
    2343 end;
    2344 
    2345 --调用
    2346 declare 
    2347     s number ;
    2348 begin 
    2349     sum3(s);
    2350     dbms_output.put_line(s) ;
    2351 end;
    2352 
    2353 
    2354 
    2355 4、有参有返
    2356 --创建
    2357 create or replace procedure sum4(a number,b in number,s out number)
    2358 as   
    2359 begin
    2360    s := a + b  ;  
    2361 end;
    2362 
    2363 --调用
    2364 declare 
    2365     aa number := 11 ;
    2366     bb number := 22 ;
    2367     ss number ;
    2368 begin 
    2369     sum4(aa,bb,ss);
    2370     dbms_output.put_line(ss) ;
    2371 end;
    2372 
    2373 5、多输出参数
    2374 --创建
    2375 create or replace procedure sum5(a number,b in number,s1 out number,s2 out number)
    2376 as   
    2377 begin
    2378    s1 := a + b ;  
    2379    s2 := a * b ;
    2380 end;
    2381 
    2382 --调用
    2383 declare 
    2384     aa number := 2 ;
    2385     bb number := 3 ;
    2386     ss1 number ;
    2387     ss2 number ;
    2388 begin 
    2389     sum5(aa,bb,ss1,ss2);
    2390     dbms_output.put_line(ss1) ;
    2391     dbms_output.put_line(ss2) ;
    2392 end;
    2393 
    2394 
    2395 课堂作业
    2396 1、输入员工编号,打印输出员工的姓名、职位、薪水,如果没有此员工,则进行异常处理,输出“对不起,不存在此用户”
    2397 2、输入部门编号,返回该部门的员工人数
    2398 3、输入部门编号,返回该部门最高薪水和最低薪水的员工姓名
    2399 
    2400 
    2401 六、为用户授予执行存储过程的权限
    2402     grant execute on 存储过程名 to 用户名;
    2403 
    2404 
    2405 七、查看存储过程
    2406 select * from user_objects;
    2407 select name,line,text from user_source where name='HELLO';
    2408 
    2409 八、删除存储过程
    2410 drop procedure 存储过程名 ;
    2411 
    2412 
    2413 ---------------------------------------------------------------
    2414 函数
    2415 一、概念
    2416 
    2417 
    2418 二、语法
    2419 create [or replace] function 函数名[(参数列表)]
    2420 return 数据类型  
    2421 is|as 
    2422   变量/常量的定义
    2423 begin
    2424   函数具体实现的功能;
    2425   return 结果;
    2426 [exception
    2427   异常处理;]
    2428 end;
    2429 
    2430 三、例子
    2431 1、无参
    2432 create or replace function fun_one return int
    2433 as
    2434 v_num number;
    2435 begin
    2436   select max(sal)-min(sal) into v_num from emp;
    2437   return v_num;
    2438 end;
    2439 
    2440 --调用
    2441 --SQL语句调用函数
    2442 select fun_one from dual;
    2443 
    2444 --使用PL/SQL块调用函数
    2445 declare
    2446     n number:=0;
    2447 begin
    2448     n:=fun_one();
    2449     dbms_output.put_line('n:' || n);
    2450 end;
    2451 
    2452 2、有参
    2453 create or replace function fun_two(eno number) return varchar2
    2454 as
    2455     v_ename emp.ename%type;
    2456 begin
    2457     select ename into v_ename from emp where empno=eno;
    2458     return v_ename;
    2459 exception
    2460     when no_data_found then
    2461         dbms_output.put_line('没有找到数据');
    2462         return '';
    2463 end;
    2464 
    2465 
    2466 四、函数授权
    2467     grant execute on 函数名 to 用户名
    2468 
    2469     
    2470 五、查看
    2471     user_objects,user_source
    2472 
    2473 六、删除函数
    2474     drop function 函数名 
    2475     
    2476 七、存储过程与函数的区别
    2477 1、存储过程:
    2478 1)作为 PL/SQL 语句执行
    2479 2)在规格说明中不包含  RETURN 子句
    2480 3)不返回任何值
    2481 4)可以包含 RETURN 语句,但是与函数不同,它不能用于返回值
    2482 
    2483 2、函数
    2484 1)作为表达式的一部分供SQL调用
    2485 2)必须在规格说明中包含 RETURN 子句
    2486 3)必须返回单个值
    2487 4)必须包含至少一条 RETURN 语句
    2488 
    2489 
    2490 
    2491 
    2492 
    2493 */
    2494 
    2495 create or replace procedure sayhello(b in number)
    2496 as 
    2497     a number := 10 ;
    2498     c number ;
    2499 begin 
    2500     c := a-b ;
    2501     dbms_output.put_line(c) ;
    2502 end ;
    2503 
    2504 begin
    2505     sayhello(20);
    2506 end ;
    2507 
    2508 
    2509 
    2510 
    2511 --1、输入员工编号,打印输出员工的姓名、职位、薪水,如果没有此员工,则进行异常处理,输出“对不起,不存在此用户”
    2512 
    2513 --第一
    2514 create or replace procedure hao(b in number)
    2515 as 
    2516  
    2517    v_name  varchar2(30) ;
    2518    v_job  varchar2(30) ;
    2519    v_sal number ;
    2520 begin 
    2521     select ename,job,sal into v_name,v_job,v_sal from emp where empno=b ;
    2522     dbms_output.put_line('姓名:'|| v_name || '  工作:' || v_job || '  薪水:' || v_sal) ;
    2523     
    2524      exception
    2525      when no_data_found then 
    2526          dbms_output.put_line('对不起,不存在此用户');
    2527 end ;
    2528 
    2529 
    2530 declare 
    2531     bianhao number ;
    2532 begin 
    2533     bianhao :=&编号 ;
    2534     hao(bianhao) ;
    2535 end ;
    2536 
    2537 
    2538 --第二
    2539 
    2540 create or replace procedure haohao(b in number)
    2541 as 
    2542  
    2543   obj emp%rowtype;
    2544 begin 
    2545     select * into obj from emp where empno=b ;
    2546     dbms_output.put_line('姓名:'|| obj.ename || '  工作:' || obj.job || '  薪水:' || obj.sal) ;
    2547     
    2548      exception
    2549      when no_data_found then 
    2550          dbms_output.put_line('对不起,不存在此用户');
    2551 end ;
    2552 
    2553 
    2554 declare 
    2555     bianhao number ;
    2556 begin 
    2557     bianhao :=&编号 ;
    2558     haohao(bianhao) ;
    2559 end ;
    2560 
    2561 
    2562 
    2563 
    2564 
    2565 --2、输入部门编号,返回该部门的员工人数
    2566 
    2567 create or replace procedure bumen(b in number,s out number)
    2568 as 
    2569   
    2570    v_people number ;
    2571 begin 
    2572      select count(ename) into v_people  from emp e,dept d where e.deptno=d.deptno and d.deptno=b ;
    2573      
    2574      s:=v_people ;
    2575     
    2576 end ;
    2577 
    2578 declare 
    2579     bianhao number ;
    2580     s number ;
    2581 begin 
    2582     bianhao :=&编号 ;
    2583     bumen(bianhao,s) ;
    2584     
    2585     dbms_output.put_line('部门编号为'||bianhao||'的部门人数为:'||s)  ;
    2586 end ;
    2587 
    2588 
    2589 
    2590 
    2591 
    2592 --3、输入部门编号,返回该部门最高薪水和最低薪水的员工姓名
    2593 
    2594 
    2595 create or replace procedure bumen2(b in number)
    2596 as 
    2597    max_name varchar2(30) ;
    2598    min_name varchar2(30) ;
    2599    max_sal number ;
    2600    min_sal number ;
    2601 begin 
    2602     select max(sal) into max_sal from emp e,dept d where e.deptno=d.deptno and d.deptno=b  ;
    2603     select ename into max_name from emp where sal= max_sal and deptno=b ;
    2604      
    2605     select min(sal) into min_sal from emp e,dept d where e.deptno=d.deptno and d.deptno=b  ;
    2606       select ename into min_name from emp where sal=min_sal and deptno=b ;
    2607   
    2608     
    2609      dbms_output.put_line('部门编号为'||b||'的最高薪水的姓名为:'||max_name||'薪水为:'||max_sal)  ;
    2610       dbms_output.put_line('部门编号为'||b||'的最低薪水的姓名为:'||min_name||'薪水为:'||min_sal)  ;
    2611 end ;
    2612 
    2613 declare 
    2614     bianhao number ;
    2615 begin 
    2616     bianhao :=&编号 ;
    2617     bumen2(bianhao) ;
    2618 end ;
    2619 
    2620   select min(sal)  from emp e,dept d where e.deptno=d.deptno and deptno=20  ;
    2621 
    2622 select min(sal),ename into min_sal,min_name from emp where deptno=20 ;
    2623 
    2624 select * from emp
  • 相关阅读:
    DevExpress Winform SearchGridLookUpEdit多选简单设置
    C# yyyyMMdd 类型字符串转换为datetime 类型
    Winform中TextBox文字垂直居中显示
    操作数据库 增删改查
    C# 连接MySql数据库
    XtraEditors三、LookUpEdit、GridLookUpEdit、SearchLookUpEdit
    前端下拉框多选
    php round函数失效
    防御式CSS开发
    微服务解决方案
  • 原文地址:https://www.cnblogs.com/aa1314/p/8082308.html
Copyright © 2020-2023  润新知