Oracle作业和知识点
作业一
关于数据控制语言中,收回所授予的权限的语句是(B)。
A、create
B、revoke
C、grant
D、update
ORACLE中 char类型与varchar2类型的区别,描述正确的是(AD)
A、char为定长字符数据类型
B、char为不定长字符数据类型
C、varchar2为定长数据类型
D、varchar2为不定长数据类型
以下权限中,不属于表权限的是? (D)
A、Insert
B、update
C、delete
D、exec
下面哪个操作会导致用户连接到ORACLE数据库,但不能创建表(A)。
A、授予了CONNECT的角色,但没有授予RESOURCE的角色
B、没有授予用户系统管理员的角色
C、数据库实例没有启动
D、数据库监听没有启动
向t_student表中添加一列f_address varchar2(50),下列语句正确的是? (A)
A、ALTER TABLE t_student Add f_address varchar2(50)
B、ALTER TABLE t_student Modify f_address varchar2(50)
C、ALTER t_student Add f_address varchar2(50)
D、ALTER t_student Modify f_address varchar2(50)
作业二
order by子句仅对检索数据的显示有影响,并不改变表中行的内部顺序。
正确
在Oracle查询的结果中,要将表userInfo 中的userName 字段用别名 “用户名”显示,请选择错误的语句(AC)。
A、SELECT 用户名 = userName FROM userInfo
B、SELECT userName AS 用户名 FROM userInfo
C、SELECT userName = 用户名 FROM userInfo
D、SELECT username 用户名 FROM userInfo
在Oracle中,有一个教师表teacher的结构如下: ID NUMBER(5)
NAME VARCHAR2(25) EMAIL VARCHAR2(50)
下面哪个语句显示没有Email地址的教师姓名(C)。
A、SELECT name FROM teacher WHERE email = NULL;
B、SELECT name FROM teacher WHERE email <> NULL;
C、SELECT name FROM teacher WHERE email IS NULL;
D、SELECT name FROM teacher WHERE email IS NOT NULL;
下列不属于Oracle数据库数据类型的是(D)
A、NUMBER
B、FLOAT
C、CLOB
D、BOOLEAN
在Oracle中, 获得当前系统时间的查询语句是:(C)。
A、sysdate
B、select sysdate
C、select sysdate from dual
D、select sysdate from common
作业三
Oracle数据库中,连接字符串的运算符是(D)。
A、+
B、&
C、is
D、||
将字符串转换为日期类型的转换函数是(A)。
A、to_date
B、to_number
C、to_char
D、都不是
关于通配符中的“%”,以下说法正确的是(BD)。
A、代表任意一个字符,与like结合使用。
B、代表任意多个字符,与like结合使用。
C、代表任意一个字符,在like后的表达式中只能使用一次“%”。
D、代表任意多个字符,在like后的表达式中可以使用多次“%”。
在Oracle中,使用HAVING子句也可以进行条件查询,以下选项说法是正确的是( C)。
A、HAVING子句和WHERE子句相同
B、HAVING子句用于行的条件查询
C、HAVING子句用于已分组结果的条件查询
D、以上皆非
在oracle中获取前10条的关键字是(D)。
A、top
B、Limit
C、first
D、rownum
作业四
Oracle数据库中返回字符串长度的函数是(D)。
A、substr
B、replace
C、instr
D、length
如果要统计表中有多少行记录,应该使用下列哪个聚合函数?(C)
A、SUM函数
B、AVG函数
C、COUNT函数
D、MAX函数
为了去除结果集中的重复行,可以在SELECT中使用下列哪个关键字?(B)
A、ALL
B、DISTINCT
C、UPDATA
D、MERGE
在Oracle中,下面哪条语句当COMM字段为空时显示0,不为空时显示COMM的值(A)。
A、SELECT ename, NVL(comm, 0) FROM emp;
B、SELECT ename, NULL(comm, 0) FROM emp;
C、SELECT ename, NULLIF(comm, 0) FROM emp;
D、SELECT ename, DECODE(comm, NULL, 0) FROM emp;
‘_P%’表示(C)。
A、以P开头
B、以P结束
C、第二个字母是P
D、右面第二个字母是P
作业五
在Oracle中,下述(A)命令会使挂起的事务完成。
A、COMMIT
B、DELETE
C、UPDATE
D、SELECT
若要删除book表中所有数据,以下语句错误的是(BD)。
A、truncate table book
B、drop table book //会删除表结构
C、delete from book
D、delete * from book
下列关于视图的说法中,正确的是(ACD)。
A、视图是一种查看数据表中数据的方式
B、视图就是真实的表
C、视图是从多张基表中按一定的业务逻辑抽出用户关心的部分,形成一张虚拟表
D、可以将复杂的查询保存为视图,对最终用户屏蔽一定的复杂性。
在视图中并不保存任何数据,通过视图操作的数据仍然保存在表中(正确)。
在PL/SQL块中定义一个名为PI值为3.14的常量的语法是(D)。
A、PI Const number=3.14;
B、PI Real number =3.14
C、Constant PI number:=3.14
D、PI Constant number:=3.14
作业六
下面那个不是oracle程序设计中的循环语句(A) 。
A、for… end for
B、loop…end loop
C、while…end loop
D、for…
在Oracle中,关于PL/SQL下列描述正确的是(C)
A、PL/SQL代表Power Language/SQL
B、PL/SQL未提供boolean数据类型 (ORACLE SQL中不存在)
C、PL/SQL块包括声明部分、可执行部分和异常处理部分
D、子程序参数的模式只有IN和OUT两种模式
过程是一组为了完成特定功能的符合数据库脚本规范的程序,经编译后存储在数据库中,然后由一个应用程序或其他PL/SQL程序调用。 正确
存储过程语法中可选参数列表包含参数的名称,模式和类型,以及参数取值范围。 错误
下列哪个动作不会激发一个触发器?(B)。
A、更新数据
B、查询数据
C、删除数据
D、插入数据
知识点
-
ORACLE 数据库系统是美国 ORACLE 公司(甲骨文)提供的以分布式数据库为核心的一组软件产品,是目前最 流行的客户/服务器(CLIENT/SERVER)或 B/S 体系结构的数据库之一。
-
数据库管理技术三个阶段
人工管理阶段
文件系统阶段
数据库系统阶段
-
对表空间的操作
--查询表空间 select tablespace_name,file_name,bytes from dba_data_files; --创建表空间 create tablespace zth_tablespace datafile 'D:\APP\CUI\ORADATA\test_tablespace.dbf' size 100 --删除表空间 drop tablespace ZTH_TABLESPACE including contents and datafiles --创建用户并指定默认表空间 create user zth identified by 123456; alter user zth default tablespace zth_tablespac
-
Oracle用户
--查看你能管理的用户 select * from all_users; --创建用户 create user student1--用户名 identified by "123456"--密码 default tablespace USERS--表空间名 temporary tablespace temp --临时表空间名 profile DEFAULT --数据文件(默认数据文件) --账户是否解锁(lock:锁定、unlock 解锁) account unlock
该用户现在还不能登录数据库,因为它没有登录数据库权限,最少他需要一个 create session 系统权限才能登录数 据库
--删除用户 drop user student cascade;
一般来说要具有 dba 权限的用户才能删除其他用户。
Oracle 数据库用户权限分为:系统权限和对象权限两种。
系统权限:比如:create session 可以和数据库进行连接权限、create table、create view 等具有创建数据库 对象权限。
对象权限:比如:对表中数据进行增删改查操作,拥有数据库对象权限的用户可以对所拥有的对象进行相应的操作。
--修改用户信息 alter user STUDENT identified by 111111 --修改密码 --修改用户处于锁定状态或者解锁状态 (LOCK|UNLOCK ) account unlock;
SELECT user FROM dual
查看当前用户 -
数据库角色
oracle 数据库角色是若干系统权限的集合,给 Oracle 用户进行授数据库角色,就是等于赋予该用户若干数据库系统权限。
CONNECT 角色:connect 角色是 Oracle 用户的基本角色,connect 权限代表着用户可以和 Oracle 服务器进行 连接,建立 session(会 话)。 RESOURCE 角色:resource 角色是开发过程中常用的角色。 RESOURCE 给用户提供了可以创建自己的对象, 包括:表、视图、序列、过程、触发器、索引、包、类型等。
DBA 角色:DBA 角色是管理数据库管理员该有的角色。它拥护系统了所有权限,和给其他用户授权的权限。 SYSTEM 用户就具有 DBA 权限。
--GRANT 系统权限 TO 用户 grant create view to student; --GRANT 角色 TO 用户 grant connect to STUDENT;--授权 connect 角色 grant resource to STUDENT;--授予 resource 角色
-- Revoke 角色(role) from 用户 revoke resource from STUDENT; --实现权限的传递 grant all on emp(表名) to tea(用户) with grant option; --收回权限 revoke select on emp from tea; revoke all on emp from tea;
回收权限时,不回收WITH ADMIN OPTION权限,要回收WITH GRANT OPTION
取消 Resource 权限后,创建表提示权限不足
-
关于SQL的定义和SQL的作用
SQL(Structured Query Language):结构化的查询语言。可以访问和处理数据库。
SQL 语言主要包括:
数据定义语言(DDL):创建,删除,更新表结构。
数据操作语言(DML):对数据库的数据进行操作,包括数据插入、更新,以及删除操作。
数据查询语言(DQL):对数据库的数据进行查询,是学习重点。
-
数据类型:
Oracle 支持多种类型,大致可以分为三类:数值、日期/时间和字符串类型。
1、VARCHAR2(length)
字符串类型:存储可变的长度的字符串,length:是字符串的最大长度,默认不填的时候是 1,最大长度不超过 4000。
varchar 是标准 sql 里面的。 varchar2 是 oracle 提供的独有的数据类型。
varchar 存放固定长度的字符串,最大长度是 2000,varchar2 是存放可变长度的字符串,最大长度是 400
如果是要更换不同的数据库,例如 mysql,那么就用 varchar,如果就用 oracle,那么用 varchar2
VARCHAR2 比 CHAR 节省空间,在效率上比 CHAR 会稍微差一些,即要想获得效率,就必须牺牲一定的空间, 这也就是我们在数据库设计上常说的‘以空间换效率 ’
2、CHAR(length)
字符串类型:存储固定长度的字符串,length:字符串的固定长度大小,默认是 1,最大长度不超过 2000
3、NUMBER(a,b)
数值类型:存储数值类型,可以存整数,也可以存浮点型。a 代表数值的最大位数:包含小数位和小数点,b 代表小数的位数。
number(6,2),输入 123.12345,实际存入:123.12
number(4,2),输入 12312.345,实际存入:提示不能存入,超过存储的指定的精度。
4、INTEGER 类型
INTEGER 是 NUMBER 的子类型,它等同于 NUMBER(38,0),用来存储整数。若插入、更新的数值有小数,则 会被四舍五入。
FLOAT也是NUMBER的子类型
5、DATE
时间类型:存储的是日期和时间,包括年、月、日、时、分、秒。
select sysdate from dual
获取系统时间日期6、TIMESTAMP
时间类型:存储的不仅是日期和时间,还包含了时区。
select systimestamp from dual
7、CLOB
大字段类型:存储的是大的文本,比如:非结构化的 txt 文本,字段大于 4000 长度的字符串。
8、BLOB
二进制类型:存储的是二进制对象,比如图片、视频、声音等转换过来的二进制对象
-
表的基本操作
/* CREATE TABLE table_name ( 字段名称 字段的数据类型 [字段的约束], 字段名称 字段的数据类型 [字段的约束], ... ); */ -- Create table create table STUDENT.stuinfo ( stuid varchar2(11) not null,--学号:'S'+班号(7 位数)+学生序号(3 位数)(1) stuname varchar2(50) not null,--学生姓名 sex char(1) not null,--性别 age number(2) not null,--年龄 classno varchar2(7) not null,--班号:'C'+年级(4 位数)+班级序号(2 位数) stuaddress varchar2(100) default '地址未录入',--地址 (2) grade char(4) not null,--年级 enroldate date,--入学时间 idnumber varchar2(18) default '身份证未采集' not null--身份证 )-- 备份查询数据命令结构: -- create table 表名 as select 语句 -- 备份学生信息表(stuinfo)的数据: create table student.stuinfo_2021 as select * from student.stuinfo;
表创建到了用户下了,查询其他用户建的表需要在表前加上用户名。
--修改表名 ALTER TABLE t_student RENAME to t_student10; --增加字段 ALTER TABLE t_student10 ADD info varchar(100); --修改字段 ALTER TABLE t_student10 rename column info to stu_info; ALTER TABLE t_student10 MODIFY info integer
-
Oracle支持的完整性约束
完整性约束 NOT NUL 约束字段的值不能为空 DEFAULT 设置字段的默认值 UNIQUE KEY(UK) 设置字段的唯一性 PRIMARY KEY(PK) 约束字段为表的主键 FOREIGN KEY(FK) 约束字段为表的外键 非空约束对 null 值和‘’起作用,都不能插入
若定义了字段可以为空时,所有的空值(NULL)不会进行唯一性验证
主键除了具有唯一性和非空约束的条件外,数据库系统也会为主键自动地建立索引,保证查询的效率。
在建立外键关系的两个表中,如果其中的外键表中存在主表的某个数据,就不能删除主表中的相关数据,因为两个表之间已经建立了外键关系。可以通过先解除外键关系(比如设置外键字段为 null 值)后,进行删除操作。
-- 通过 constraint 关键字,定义联合主键 CREATE TABLE t_student( first_name VARCHAR2(20), last_name VARCHAR2(20), sex VARCHAR2(20) DEFAULT 'MAN', tel VARCHAR2(11), CONSTRAINT pk_firstname_lastname PRIMARY KEY(first_name,last_name) -- CONSTRAINT 外键名称 FOREIGN KEY(表的字段) REFERENCES 关联的外键表(关联表的主键) CONSTRAINT fk_PerOrders FOREIGN KEY(p_id) REFERENCES Persons(p_id) );
-
表数据的操作
oracle 数据库,需要手动提交事务,可以在增删改语句后,添加 commit 语句
插入数据记录
-- INSERT INTO table_name(field1,field2,...) VALUES(val1,val2,...);
-- 指定字段插入
insert into STUDENT. STUINFO (STUID, STUNAME, SEX, AGE, CLASSNO, STUADDRESS, GRADE, ENROLDATE, IDNUMBER)
values ('SC201801001', '张三', '1', 26, 'C201801', '福建省厦门市 XXX 号', '2018', to_date('01-09-2018', 'dd-mm-yyyy'), '3503021992XXXXXXXX');
select * from student.stuinfo t where t.stuid='SC201801005';
-- 不指定字段插入,需要按顺序写(不推荐使用)
insert into STUDENT.STUINFO
values ('SC201801002', '李四', '1', 26, 'C201801', '福建省厦门市 XXX 号', '2018', to_date('01-09-2018', 'dd-mm-yyyy'), '3503021992XXXXXXXX');
-- 插入查询结果(可以批量插入)
insert into student.stuinfo select * from student.stuinfo_2020;
更新数据记录
UPDATE table_name SET field1=val1,field2=val2,... WHERE conditio
删除数据记录
DELETE FROM table_name WHERE CONDITION
-- 清空表格
TRUNCATE TABLE stuinfo_2020;
在删除数据时,也需要特别注意是否需要删除条件,如果没有删除条件,就会把这个表的数据删除,并非清空表格,id 不重置。
truncate 命令是属于 DDL 命令,一次性删除表中所有数据,并且数据不能恢复,在实际开发过程当中 truncate 命令慎用。
-
单表数据查询
SELECT field1,field2,... FROM table_name --查询所有数据 select * from STUINFO t where t.stuname="李胜利"; --避免重复查询 select distinct t.sex from STUINFO t; --实现数学运算的查询 SELECT t.stuname,salary,salary*12 FROM STUINFO t; --字符串连接符||的使用 SELECT '20 级 1 班-'||stuname||'-同学',salary,salary*12 FROM STUINFO t
||可以一次连接多个,concat一次只能连接一个,要连接多个需要嵌套
-
条件数据记录的查询
在条件内部定义:
- 带关系运算符和逻辑运算符的表达式
- 带 between…and 关键字的条件数据查询
- 使用 is null 关键字的条件数据查询
- 使用 in 关键字的条件数据查询
- 带 like(模糊查询)关键字的条件数据查询
Oracle 中的关系运算符:>、 >=、 <、 <=、 !=(<>) 、 = Oracle 中的逻辑运算符:&&(AND)、||(OR)、!(NOT)
--使用!= SELECT stuname,salary,salary*12 FROM STUINFO WHERE salary<>1000; --使用between and SELECT stuname,salary FROM STUINFO WHERE salary BETWEEN 1500 AND 2000; --使用is null SELECT * FROM t_student WHERE code IS NULL; --使用in关键字 SELECT * FROM t_student WHERE id in(2,4); --带like的模糊查询 SELECT * FROM t_student WHERE name LIKE '%悟%'; SELECT * FROM t_student WHERE name LIKE '_白%';
空字符串和null是两个值,使用的时候注意查询空字符串用xxx=‘’,判断是否为null用is null,其中不是空值,使用 IS NOT NULL 表示。
-
排序数据记录
SELECT * FROM table_name ORDER BY field1 排序条件(asc/desc),field2 排序条件(asc/desc)
-
伪列
伪列可以用来限制数据记录的查询数量
常用的伪列有
rowid
和rownum
rowid
是表中行的存储地址,该地址可以唯一标识数据库中的一行,可以使用rowid伪列快速定位表中的一行。rownum
是查询返回的结果集中行的序号,可以使用它来限制查询返回的行数。rownum 是伪列,值从 1 开始,不能用表名修饰
-- 查询所有学生信息,按工资正序 select t.*,rownum from stuinfo t order by t.salary asc; -- 查询工资最低的四位(错误写法) select t.*,rownum from stuinfo t where rownum<=4 order by t.salary asc; -- 查询工资最低的四位(正确写法) select m.* from (select t.*,rownum from stuinfo t order by t.salary asc) m where rownum<=4
由于 order by 一直在 where 条件之后执行,但是 rownum 又是在 where 中执行的,所以按照需求,rownum 的判断应该在 order by 之后
可以利用ronum实现分页查询
-- 每页显示 2 条,第一页数据 select * from (select tt.*,rownum r from (select * from t_student t order by t.id desc) tt where rownum<=2) ttt where ttt.r >=1;
ROWNUM 是对结果集加的一个伪列,即先查到结果集之后再加上去的一个列 (强调:先要有结果集)。它总是从 1 开始排起的。所以你选出的结果不可能没有 1,而有其他大于 1 的值
分页公式:rownum<=页数*每页显示条数,rownum>=(页数-1)*每页显示条数+1
-
Oracle中单引号和双引号的区别
在Oracle中:
双引号的作用是:假如建立对象的时候,对象名、字段名加双引号,则示意Oracle将严格区分大小写,否则Oracl都默认大写。
而单引号则示意:这个加了单引号的字段是一个字类似字符串,并不区分大小写。
-
统计函数和分组数据查询
除了 count 函数,其他函数如果没有找到记录,返回值是 null,count 函数返回 0
聚合函数
SELECT AVG(salary) as "平均薪水", MAX(salary) as "最高薪水", MIN(salary) as "最低薪水", SUM(salary) as "薪水总和", COUNT(id) as "总记录数" FROM t_student where group_num=1;
分组查询
-- SELECT function() FROM table_name WHERE CONDITION GROUP BY field1,field2 SELECT group_num,AVG(salary) AS "平均薪水" FROM t_student WHERE group_num IS NOT NULL GROUP BY group_num --多字段分组 SELECT group_num,sex,AVG(salary) AS "平均薪水" WHERE group_num IS NOT NULL GROUP BY group_num,sex;
使用having对聚合完的数据,进行条件限制查询
-- 多字段分组 SELECT group_num,sex,AVG(salary) AS "平均薪水" FROM t_student WHERE salary > 300 and group_num IS NOT NULL GROUP BY group_num,sex HAVING AVG(salary) > 500 Order by group_num asc;
上述语句的执行顺序:
- 从 t_student 表中过滤出 salary>300,并且 group_num 不是空的数据;
- 根据 group_num,sex 字段,将相同的 group_num,sex 的数据,进行归结;
- 执行 select 关键字后面的字段查询,包括函数的执行。
- 通过 having 关键字,对聚合完成后的数据,再次进行过滤,这里面我们一般过滤的是聚合函数的值。
- 执行 ORDER BY 子句, 把最后的结果按 “group_num”
group by 有一个原则,就是 select 后面的所有列中,没有使用聚合函数的列,必须出现在 group by 后面。
-
多表数据查询
在关系型数据中,表与表之间存在一定的结果关系,关系包括一对一,一对多,多对一,多对多。
-- 多条记录查询 SELECT e.name AS "姓名",d.name AS "部门名称" FROM t_employee e,t_department d WHERE e.dept_id = d.id; -- 内连接的查询 SELECT e.name AS "姓名",d.name AS "部门名称" FROM t_employee e INNER JOIN t_department d ON e.dept_id = d.id
为在内连接查询中,要保证 e.dept_id = d.id 的完全匹配,结果才会被检索 出来。
检索方式: 数据库逐行地扫描 t_employee 表,根据连接条件来决定 t_employee 表的数据,是否被检索出来。
内连接查询只输出满足条件的元组
外连接查询以指定表为连接主体,将主体表中不满足连接条件的元组一并输出
左外连接:将左表作为主表,结果集中除了满足连接条件的记录外,还有主表中不满足条件的记录
select * from t_teacher left join t_teachcourse on t_teacher.tid =t_teachcourse.tid;
右外连接:将右表作为主表,结果集中除了满足连接条件的记录外,还有主表中不满足条件的记录
select * from t_teachcourse right join t_teacher on t_teachcourse.tid =t_teacher.tid;
全连接:结果集中除了满足连接条件的还有左右表中不满足条件的记录
select * from t_teacher full join t_teachcourse on t_teacher.tid = t_teachcourse.tid;
交叉连接:接收两个分别由N行和M行的表T1和T2,返回一个包含交叉乘积N*M条记录的连接表;
select table_name from T1 cross join T2
自连接:
selcet p1.empno,p1.ename,p1.mgr,p2.ename from emp p1 left join emp p2 on p1.mgr=p2.empno;
连接时注意要给表起别名
-
子查询
用查询作为中间结果提供给上一层而不输出,这类查询称为子查询
-
带有比较运算符的子查询
只能为外层提供一个单一值作为外层查询的比较对象
select * from t_student where sid=(select * from t_score where cid=1 );
-
[NOT]IN 子查询
适用于子查询中返回多个值时的情况
select * from t_course where cid in (select cid from t_teachcourse);
-
exists子查询:
存在查询,子查询不返回任何结果,只产生true和false
select * from t_course where exists (select * from t_teachcourse where t_teachcourse.cid=t_course.cid);
-
FROM里面的子查询
当子查询返回一个结果集时,就可以看作一个表,因此在from子句中同样可以使用子查询。
select max(avgscore) from (select avg(score) as avgscore from t_score group by sid);
-
-
操作符
分类:算数、比较、逻辑、集合、连接;
算数运算符:+、-、*、/
SELECT t.stuname,salary,salary+1000 FROM STUINFO t
比较运算符:=、<>(!=) 、<、>、<=、>=、between and
select * from STUINFO t where salary between 1000 and 2000;
逻辑运算符:AND、OR、NOT
连接操作符:||
select ('员工号为'||stuid||',姓名为'||stuname||'的工资为'||salary) from STUINFO
集合操作符:
intersect 返回两个查询的公共行;
union:返回两个查询的不重复的所有行;这里面可以是一个表中的数据;
minus:返回从第一个查询的结果中排除第二个查询中出现的行;(在第一个的结果中查找不满足第二个的)
select * from stuinfo where salary >=1000 intersect select * from stuinfo where age>26
优先级:算术>连接>比较>not 逻辑>and 逻辑>or 逻辑操作符
-
SQL函数
分类:单行、分组、分析
单行函数:从表中查询的每一行只返回一个值,大致分为字符、数字、日期、转换、其他
- 字符函数
select lower(stuid) from stuinfo; select upper(stuid) from stuinfo; --拼接字符串 select concat('员工号为',stuid) from STUINFO
在 oracle 中,需要上述多次拼接应使用||,因为 concat()一次只能拼接 2 个,需要多次嵌套。
- 其他单行函数
-
数字函数
-
日期函数
-
转换函数
to_char:按照指定的格式转化字符串;
to_date:将字符串转化为日期;
to_number:将数字字符串转化为数字;
--转换函数,常见 to_char(日期,格式) select to_char(sysdate,'yyyy-MM-dd') from dual; --字符串转日期 select to_date ('2005-02-28','yyyy/mm/dd') from dual; --字符串转数字 select to_number('20')
nvl(string, replace_with):不为空时为本身,为空时为指定值;
nvl2(e1, e2, e3):不为空时指定值 e2,为空时指定值 e3;
NullIF(a,b):相等时为空,否则为前者;
--nvl 设置为空时的默认值 select stuname,salary,bonus,salary+bonus,salary+nvl(bonus,0) as sal from stuinfo; ---不为空时 10000,为空时 0; select stuname,salary,bonus,salary+nvl2(bonus,10000,0) from stuinfo; --相等为空,不等为前者 select nullif(1000,2000) from dual;
Null 与任何数字相加的结果还是 null,这里需要 nvl
-
分组函数
基于一组行来返回结果; avg、min、max、sum、coun
-
数据库对象
Oracle 数据库对象是数据库的组成部分,常常用 CREATE 命令进行创建,可以使用 ALTER 命令修改,用 DROP 执 行删除操作。前面已经接触过的数据库对象有表、用户等。
同义词:就是给数据库对象一个别名。
序列:Oracle 中实现增长的对象。
视图:预定义的查询,作为表一样的查询使用,是一张虚拟表。
索引:对数据库表中的某些列进行排序,便于提高查询效率。
-
同义词
在 Oracle 中对用户的管理是使用权限的方式来管理的,也就是说,如果我们想使用数据库,我们就必须得有 权限,如果是别人将权限授予了我们,我们也是能对数据库进行操作的,但是我们必须要在已授权的表的名称前 键入该表所有者的名称,同义词是现有对象的一个别名,可以简化 SQL 语句,隐藏对象的名称和所有者,提供对对象的公共访问。
同义词分为私有同义词和共有同义词:
(1)私有同义词:拥有 create synonym 权限的用户(包括非管理员用户)即可创建私有同义词,创建的私有同 义词只能由当前用户使用。
(2)公有同义词:系统管理员可以创建公有同义词,公有同义词可以被所有用户访问。
--赋予 test_user 账号创建同义词权限 grant create public synonym to test_user; --赋予 test_user 账号删除同义词权限 grant drop public synonym to test_user; --为表对象创建同义词 create or replace public synonym syn_t_student for student.t_student; --删除同义词 drop public synonym syn_t_student;
-
序列
序列(Sequence)是用来生成连续的整数数据的对象。序列常常用来作为主键中增长列,序列中的可以升序生成, 也可以降序生成。创建序列的语法是:
-- 创建序列 create sequence seq_empno start with 1 --初始值 increment by 1; --增量 -- 序列中的下一个值,从定义(start with)的值开始,调用了 nextval 之后, currval 会变成 nextval 的值 select seq_empno.nextval from dual; -- 获取序列的当前值 -- CURRVAL 总是返回当前 sequence 的值,但是在第一次 NEXTVAL 初始化之后才能使用 CURRVAL,否则会出错 select seq_empno.currval
-
-
视图
视图(View)是一种虚表,在已有的数据表或其他视图的基础上创建的,可以理解为存储起来的查询语句,视图 本身不存储数据,因此对虚表的操作最终都会转换为对基表的操作,只需要简单的 SELECT…FROM 即可
基本语法
CREATE [OR REPLACE] VIEW view_name [(column_name1[,column_name2… AS select_statement [WITH CHECK OPTION] [WITH READ ONLY --删除视图 drop view v_student
CREATE OR REPLACE:用于创建和修改视图(OR REPLACE :若所创建的试图已经存在,则替换旧视图;)
WITH CHECK OPTION :用于创建限制数据访问的视图
WITH READ ONLY :用于创建只读视图
-
索引
索引就类似的书的目录,能够在一定程度上快速的进行数据的定位。
一旦建立了索引,在数据进行插入或更新时,就会去更新索引结构,带来一定效率损耗。而且因为加了索引会多 占用一定的磁盘空间。
们一般是在需要建立查询条件的字段上创建索引,而且索引也可以定义在多个字段上面的。
索引是为表中字段添加的。当一个字段经常出现在 WHERE 中作为过滤条件,或 ORDER BY 或 DISTINCT 中 时可以为其添加索引以提高查询效率。
--创建索引 create index ix_student on stuinfo(stuname) --删除索引 drop index ix_student --创建组合索引 create index ix_student on
-
PL/SQL基本语法
PL/SQL 是块结构语言; PL/SQL 程序划分成几个部分,并在每个部分中写入逻辑代码块。
每个块由三个子部分组成
声明部分 - 此部分是以关键字 DECLARE 开头。这是一个可选部分,并定义了程序中要使用的所有变量,游标,子程序和其他元素。
可执行命令部分 - 此部分包含在关键字 BEGIN 和 END 之间,这是一个强制性部分。它由程序的可执行 PL/SQL 语句组成。它应该有至少一个可执行代码行,它可以只是一个 NULL 命令,表示不执行任何操作。
异常处理部分 - 此部分以关键字 EXCEPTION 开头。这是一个可选部分,它包含处理程序中错误的异常。
DECLARE <declarations section> BEGIN <executable command(s)> EXCEPTION <exception handling>
只要是 BEGIN 和 END 之间,就可以使用 DBMS_OUTPUT.PUT_LINE(output);输出信息。
注意 delcare中给变量赋值需要使用
:=
PL/SQL 标识符是常量,变量,异常,过程,游标和保留字。默认情况下,标识符不区分大小写。
PL/SQL分隔符
PL/SQL 支持单行和多行注释。注释中的所有字符都被 PL/SQL 编译器忽略。 PL/SQL 单行注释以分 隔符开头 --(双连字符),多行注释由/*和*/括起来。
PL/SQL单元是以下任何一个:
- PL/SQL 块
- 函数
- 包
- 包体
- 过程
- ==触发器==
-
PL/SQL变量声明及初始化
必须在声明部分或包中声明 PL/SQL 变量作为全局变量。
variable_name [CONSTANT] datatype [NOT NULL] [:= | DEFAULT initial_value]
变量初始化方法
a integer := 10; b integer default 20; c integer; f float;
变量作用域
- 局部变量:内部块中声明的变量,外部快不可访问
- 全局变量:在最外部块或包中声明的变量
DECLARE -- 全局变量 num1 number := 95; num2 number := 85; BEGIN dbms_output.put_line('Outer num1: ' || num1); dbms_output.put_line('Outer num2: ' || num2); DECLARE -- 局部变量 num1 number := 195; num2 number := 185; BEGIN dbms_output.put_line('Inner num1: ' || num1); dbms_output.put_line('Inner num2: ' || num2); END; END;
-
将SQL查询结果分配给PL/SQL变量
可以使用 SQL 的 SELECT INTO 语句将值分配给PL/SQL变量。对于 SELECT 列表中的每个项目, INTO 列表中必须有一个对应的类型兼容变量。
DECLARE c_id employee.id%type := 1; c_name employee.name%type; c_addr employee.address%type; c_sal employee.salary%type; BEGIN SELECT name, address, salary INTO c_name, c_addr, c_sal FROM employe WHERE id = c_id; dbms_output.put_line ('员工'||c_name||'来自'||c_addr||',薪水'||c_sal); END;
%type可以自动将变量类型与数据库中的类型兼容,每次数据库中变量类型改变,PL/SQL中的变量也会自动兼容
-
PL/SQL常量、运算符
常量在声明时指定值,并且在程序中不会更改。常量声明需要指定其名称,数据类型和值,并为其分配存储 空间。声明也可以强加 NOT NULL 约束
使用 CONSTANT 关键字声明常量。它需要初始值,不允许在声明后更改该值。
DECLARE -- 声明常量 pi constant number := 3.141592654; -- 半径 radius number(5,2); -- 直径 dia number(5,2); -- 周长 circumference number(7, 2); -- 面积 area number (10, 2); BEGIN radius := 9.5; dia := radius * 2; circumference := 2.0 * pi * radius; area := pi * radius * radius; -- output dbms_output.put_line('半径: ' || radius); dbms_output.put_line('直径: ' || dia); dbms_output.put_line('圆周: ' || circumference); dbms_output.put_line('面积: ' || area); END;
PL/SQL中的运算符:
- 算术运算符
- 关系运算符
- 比较运算符
- 逻辑运算符
- 字符串运算符
关系运算符比较两个表达式或值,并返回一个布尔结果。
DECLARE a number(2) := 21; b number(2) := 10; BEGIN IF (a = b) then dbms_output.put_line('1. a 等于 b'); ELSE dbms_output.put_line('1. a 不等于 b'); END IF; IF (a < b) then dbms_output.put_line('2. a 小于 b'); ELSE dbms_output.put_line('2. a 不小于 b'); END IF; IF ( a > b ) THEN dbms_output.put_line('3. a 大于 b'); ELSE dbms_output.put_line('3. a 不大于 b'); END IF; -- 改变 a 和 b a := 5; b := 20; IF ( a <= b ) THEN dbms_output.put_line('4. a 小于等于 b'); END IF; IF ( b >= a ) THEN dbms_output.put_line('5. b 大于等于 a'); END IF; IF ( a <> b ) THEN dbms_output.put_line('6. a 不等于 b'); ELSE dbms_output.put_line('6. a 等于 b'); END IF; END;
比较运算符用于将一个表达式与另一个表达式作比较,结果始终为 TRUE,FALSE 或 NULL。
--DECLARE CREATE or replace PROCEDURE compare(val varchar2,pattern varchar2) is BEGIN IF val LIKE pattern THEN dbms_output.put_line ('True'); ELSE dbms_output.put_line ('False'); END IF; END; --测试 Like 模糊匹配 BEGIN compare('孙悟空', '孙%'); compare('白龙马', '%白%'); compare('张三', '%三'); compare('李四', '%三'); END;
Like模糊匹配、Between and判断数值变量是否在between and的数值之间
in 判断是否在范围内,is null 判断是否为空
逻辑运算符 AND OR NOT都使用布尔运算符并产生布尔运算结果
-
数据类型
标量(SCALAR)类型 – 用来存储单个值,例如:NUMBER,DATE 或 BOOLEAN 等。
属性数据类型 - 用于引用数据库列的数据类型,以及表示表中一行的记录类型。
大对象(LOB)数据类型 - 指向与其他数据项(例如:文本,图形图像,视频剪辑和声音波形)分开存 储的大对象的指针。
复合数据类型 - 具有可单独访问的内部组件的数据项。例如,集合和记录。
引用数据类型 -指向其他数据项
-
标量数据类型
PL/SQL 中是有 Boolean 类型的,只能取 2 个值:true 和 false; 存储过程中的变量也支持 boolean 型; 但 oracle 本身中没有 boolean 类型
-
属性类型
属性类型用于引用数据库列的数据类型,以及表示表中一行的记录类型。
-
-
条件控制
if-then 语句,if-then-else 语句,if-then-elsif 语句,case 语句,可搜索 case 语句,嵌套 if-then-else 语句
IF condition THEN S; END IF;
IF condition THEN S1; ELSE S2; END IF;
IF-THEN 语句可以有零个或一个 ELSE,它必须在 ELSIF 之后
IF-THEN 语句可以有零或多个 ELSIF,它们必须在 ELSE 之前
一旦有一个 ELSIF 条件测试成功,其余的 ELSIF 或 ELSE都不会再被测试
IF ( a = 10 ) THEN dbms_output.put_line('a 的值是 10' ); ELSIF ( a = 20 ) THEN dbms_output.put_line('a 的值是 20' ); ELSIF ( a = 30 ) THEN dbms_output.put_line('a 的值是 30' ); ELSE dbms_output.put_line('都不匹配'); END IF;
CASE 语句使用选择器而不是多个布尔表达式。选择器是一个表达式,其值用于选择几种替代方法之一。
CASE selector WHEN 'value1' THEN S1; WHEN 'value2' THEN S2; WHEN 'value3' THEN S3; ... ELSE Sn; -- default case END CASE
可搜索的 CASE 语句没有选择器,语句中的 when 子句包含给出布尔值的搜索条件。
CASE WHEN selector = 'value1' THEN S1; WHEN selector = 'value2' THEN S2; WHEN selector = 'value3' THEN S3; ... ELSE Sn; -- default case END CASE;
在 PL/SQL 编程中嵌套 IF-ELSE 语句总是合法的,也就是说可以在一个 IF 或 ELSE IF 语句中使用另一个 IF 或 ELSE IF 语句。
IF (boolean_expression1) THEN -- executes when the boolean expression 1 is true IF (boolean_expression2) THEN -- executes when the boolean expression 2 is true sequence-of-statements; END IF; ELSE -- executes when the boolean expression 1 is not true else-statements; END IF;
-
循环语句
基本 LOOP 循环,while 循环,for 循环,嵌套循环
基本循环结构包含 LOOP 和 END LOOP 语句之间的语句序列。通过每次迭代,执行语句序列,然后在循环顶部继续控制。
LOOP Sequence of statements; END LOOP
这里,语句序列(Sequence of statements;)可以是单个语句或一组语句。需要一个 EXIT 语句或一个 EXIT WHEN 语句来中断循环
DECLARE x number := 10; BEGIN LOOP dbms_output.put_line(x); x := x + 10; -- 第一种退出方式: /*IF x > 50 THEN exit; END IF; */ -- 第二种退出方式: exit WHEN x > 50; END LOOP; dbms_output.put_line('循环结束后,x 的值是: ' || x); END;
只要给定条件为真,PL/SQL 编程语言中的 WHILE LOOP 语句重复执行目标语句。
WHILE condition LOOP sequence_of_statements END LOOP
FOR LOOP 语句是一种重复控制结构,可以有效地编写一个需要执行特定次数的循环。
FOR counter IN initial_value .. final_value LOOP sequence_of_statements; END LOOP
循环变量或计数器的 initial_value 和 final_value 可以是文字,变量或表达式,但必须对数字求值。 否则,PL/SQL 引发预定义的 异常 VALUE_ERROR。
initial_value 不必为 1; 但是,循环计数器增量(或减量)必须为 1。
DECLARE a number(2); BEGIN FOR a in 10 .. 20 LOOP dbms_output.put_line('a 的值是' || a); END LOOP; END;
反转 FOR LOOP 语句,每次迭代后,循环计数器递减。
DECLARE a number(2); BEGIN FOR a in REVERSE 10 .. 20 LOOP dbms_output.put_line('a 的值是' || a); END LOOP; END;
嵌套循环
PL/SQL 中嵌套的基本 LOOP语句语法
LOOP Sequence of statements1 LOOP Sequence of statements2 END LOOP; END LOOP;
PL/SQL 中嵌套 FOR LOOP 语句的语法
FOR counter1 IN initial_value1 .. final_value1 LOOP sequence_of_statements1 FOR counter2 IN initial_value2 .. final_value2 LOOP sequence_of_statements2 END LOOP; END LOOP;
PL/SQL 中嵌套的 WHILE LOOP 循环语句的语法
WHILE condition1 LOOP sequence_of_statements1 WHILE condition2 LOOP sequence_of_statements2 END LOOP; END LOOP;
循环控制语句
exit 语句:结束循环
continue 语句:跳过本次循环,进行下一次循环
goto 语句:转移控制到标记语句
-
异常处理
在运行程序时出现的错误叫做异常。如果在 PL/SQL 块中没有做异常处理,在执行 PL/SQL 块时,出现异常,会传递到调用环境,导 致程序运行出错。
PL/SQL的两种异常
- 系统预定义的异常:当 PL/SQL 程序违反 Oracle 规则或超越系统限制时隐式引发。
- 用户定义的异常:用户可以在 PL/SQL 块的声明部分自定义异常,自定义异常可以通过 raise
异常处理的一般语法
DECLARE <declarations section> BEGIN <executable command(s)> EXCEPTION <exception handling goes here > WHEN exception1 THEN exception1-handling-statements WHEN exception2 THEN exception2-handling-statements WHEN exception3 THEN exception3-handling-statements ........ WHEN others THEN exception3-handling-statements END;
PL/SQL 提供了许多预定义的异常,这些异常在程序违反任何数据库规则时执行。 例如,当 SELECT INTO 语句不返回任何行时,会 引发预定义的异常 NO_DATA_FOUND
如果不确定异常,可以用 others 处理。 异常处理可以按任意次序排列,但 others 必须放在最后。
引发异常:
只要有内部数据库错误,数据库服务器就会自动产生(引发)异常,但程序员可以使用命令 RAISE 明确地引发异常。以下是引发异常的简单语法
DECLARE
exception_name EXCEPTION;
BEGIN
IF condition THEN
RAISE exception_name;
END IF;
EXCEPTION
WHEN exception_name THEN
statement;
END;
DECLARE my-exception EXCEPTION;
DECLARE
c_id customers.id%type := &cc_id;
c_name customerS.name%type;
c_addr customers.address%type; -- 用户自定义异常
ex_invalid_id EXCEPTION;
BEGIN
IF c_id <= 0 THEN
RAISE ex_invalid_id;
ELSE
SELECT name,address INTO c_name,c_addr
FROM customers
WHERE id = c_id;
DBMS_OUTPUT.PUT_LINE ('姓名:'|| c_name);
DBMS_OUTPUT.PUT_LINE ('地址:'||c_addr);
END IF;
EXCEPTION
WHEN ex_invalid_id THEN
dbms_output.put_line('编号 ID 必须要大于 0!');
WHEN no_data_found THEN
dbms_output.put_line('未找到指定 ID 的客户信息!');
WHEN others THEN
dbms_output.put_line('Error!');
END;
PLSQL 中&代表绑定一个变量。
-
存储过程
过程是一组为了完成特定功能的符合数据库脚本规范的程序,经编译后存储在数据库中,然后由一个应用程序或其他 PL/SQL 程序调用
- 函数 - 这些子程序返回单个值; 主要用于计算和返回值。
- 存储过程(程序) - 这些子程序不直接返回值; 主要用于执行动作
创建存储过程
CREATE [OR REPLACE] PROCEDURE procedure_name [(parameter_name [IN | OUT | IN OUT] type [, ...])] {IS |AS} BEGIN < procedure_body > END procedure_name;
可选参数列表包含参数的名称,模式和类型。IN 表示将从外部传递的值,OUT 表示将用于返 回过程外的值的参数。
存储过程参数不带取值范围,in 表示传入,out 表示输
独立的存储程序可以通过两种方式调用
- 使用 EXECUTE 关键字
- 从 PL/SQL块调用过程的名称
删除存储过程
DROP PROCEDURE procedure-name;
-
PL/SQL子程序中的参数模式
in和out模式
CREATE OR REPLACE PROCEDURE findMin(x IN number, y IN number, z OUT number) IS BEGIN IF x < y THEN z:= x; ELSE z:= y; END IF; END; DECLARE a number; b number; c number; BEGIN a:= 12; b:= 35; findMin(a, b, c); dbms_output.put_line('两个数:12, 35 中的最小值是 : ' || c); END;
-
函数
函数是可以返回返回值的 PL/SQL 子程序,与过程(也叫子程序)类似,只不过函数有返回一个值,而过程没有返回 值。
语法:
CREATE [OR REPLACE] FUNCTION function_name [(parameter_name [IN ] type [, ...])] RETURN return_datatype {IS |AS} BEGIN < function_body > END [function_name]
function-name 是指定要创建的函数的名称。
[OR REPLACE]选项指示是否允许修改现有的函数。
可选参数列表包含参数的名称,模式和类型。 IN 表示将从外部传递的值
函数必须包含一个返回(RETURN)语句。
RETURN 子句指定要从函数返回的数据类型。
function-body 包含可执行部分。
CREATE OR REPLACE FUNCTION totalCustomers RETURN number IS total number(2) := 0; BEGIN SELECT count(*) into total FROM customers; RETURN total; END
-
触发器
触发器是与表有关的数据库对象,在满足定义条件时触发,并执行触发器中定义的语句集合。触发器的这种特性 可以协助应用在数据库端确保数据的完整性。
CREATE TRIGGER trigger_name trigger_time trigger_event ON tb_name FOR EACH ROW trigger_stmt;
trigger_name:触发器的名称, 由于触发器是数据库自动执行的,因此该名称只是一个名称,没有实质的用途。
tirgger_time:触发时机,为 BEFORE(表示在数据库动作之前触发器执行)或者 AFTER(表示在数据库动作 之后触发器执行)
trigger_event:触发事件(指明哪些数据库动作会触发此触发器),为 INSERT、DELETE 或者 UPDATE
tb_name:表示建立触发器的表名,就是在哪张表上建立触发器
for each row:对表的每一行触发器执行一次。如果没有这一选项,则只对整个表执行一次。
trigger_stmt:触发器的程序体,可以是一条 SQL 语句或者是用 BEGIN
和END包含的多条语句
BEFORE 和 AFTER 参数指定了触发执行的时间,在事件之前或是之后。
FOR EACH ROW 表示任何一条记录上的操作满足触发事件都会触发该触发器。
注意触发器名称不能重复。
触发器实现id自增
--创建序列 create sequence demo_seq increment by 1 start with 1 ; --创建触发器 create or replace trigger demo_trigger before insert on demo for each row begin -- :new --为一个引用最新的列值; select demo_seq.nextval into :new.id from dual; end; INSERT INTO demo(name,code,clazz) VALUES(1,1,1); commit; select * from demo;
删除触发器
DROP TRIGGER DEMO_TRIGGER;
-
游标的使用
PL/SQL 是用游标来管理 SQL 的 SELECT 语句的。游标是为了处理这些语句而分配的一大块内存。它提供了对一 个结果集进行逐行处理的能力,可看作是一种特殊的指针。它与某个查询结果集相关联,可以指向结果集的任意 位置,以便对指定置的数据进行处理。使用它可以在查询数据的时对数据进行处理。
总结:可以命名一个游标,以便在程序中引用它来获取和处理 SQL 语句返回的行,一次处理一个(行)。
隐式游标、显示游标
当执行 SQL 语句时,如果语句没有显式游标,则 Oracle 会自动创建隐式游标
在 PL/SQL 中,可以将最近的隐式游标引用为 SQL 游标,它始终具有%FOUND,%NOTFOUND,%ISOPEN 和%ROWCOUNT 等属性。 SQL 游标具有额外的属性%BULK_ROWCOUNT 和%BULK_EXCEPTIONS,旨在与 FORALL 语句一起使用
DECLARE
total_rows number(2);
BEGIN
UPDATE customers
SET salary = salary + 500;
--中间加提交,sql%notfound 值为 true
--commit;
IF sql%notfound THEN
dbms_output.put_line('没有找到客户信息~');
ELSIF sql%found THEN
total_rows := sql%rowcount;
dbms_output.put_line('一共有:' || total_rows || ' 个客户的工资被更新! ');
END IF;
END
显示游标:
显式游标是由 PL/SQL 程序员定义和命名的游标。应在 PL/SQL 块的声明部分中定义一个显式游标。 它是在一个返回多行的 SELECT
CURSOR cursor_name
IS
select_statement;
使用显式游标包括以下步骤
- 声明游标初始化内存
- 打开游标分配内存
- 从游标获取数据
- 关闭游标以释放分配的内存
声明游标
声明游标使用名称和相关的 SELECT 语句来定义游标。
CURSOR c_customers IS
SELECT id, name, address FROM customers;
打开游标
打开游标将为游标分配内存,并使其准备好将 SQL 语句返回的行记录数据提取到其中。例如,打开上面定义的游 标,如下所示
OPEN c_customers;
获取游标
获取游标一次仅访问一行。 例如,从上面打开的游标中获取行,如下所示代码:
FETCH c_customers INTO c_id, c_name, c_addr;
关闭游标
关闭游标意味着释放分配的内存。例如,关闭上面打开的游标
CLOSE c_customers
DECLARE
c_id customers.id%type;
c_name customers.name%type;
c_addr customers.address%type;
CURSOR c_customers is
SELECT id, name, address FROM customers;
BEGIN
OPEN c_customers;
LOOP
FETCH c_customers into c_id, c_name, c_addr;
EXIT WHEN c_customers%notfound;
dbms_output.put_line(c_id || ' ' || c_name || ' ' || c_addr);
END LOOP;
CLOSE c_customers;
END