一、oracle数据库安装
(一)如何搭建Oracle使用环境
1、vmware安装
利用keygen.exe获取激活码
2、在vmware安装系统
(1)使用Pe系统ISO文件启动,制作PE系统访问大白菜 https://www.dabaicai.com/
(2)使用pe系统中的分区工具给虚拟机硬盘分区,格式化分区
(3)使用pe系统中“手动执行GHOST”,安装win7镜像文件(GHO文件),
从上往下数:1->2->3。
3、安装VMware tools,便于主机跟虚拟机之间拷贝文件,操作如下:
虚拟机菜单 -> 安装VMware tools ->在光盘D以管理员身份运行setup64.
4、安装oracle数据库
给数据库起个名字,默认用orcl
给超级用户sys和管理员用户system加个密码,例如:jsj
友情提醒:Oracle数据库安装时不要装在系统盘
(二)如何制作ISO文件
1、在本机安装“4”制作iso文件的软碟通软件,该软件要注册。
2、创建文件夹,把要放到iso文件的软件放到该文件夹
3、选择该文件夹,点击鼠标右键,选择“UltraISO”=>添加到“.iso”
生成iso映像文件,该ISO文件用于在虚拟机中安装操作系统。
二、oracle数据库配置和常用工具
(一)Oracle服务器信息、网络配置
1、两个服务:数据库服务、监听服务
2、两个用户:超级用户(sys,使用时要亮明身份“as sysdba”)、管理员(system)
3、Oracle网络配置的两种方式
(1)使用配置工具:net manager
监听程序(服务器端): 主机(相当于单位地址,ip地址)、端口(相当于门牌号,默认是1521)、全局数据库名(相当于单位名称),如:orcl
服务命名(员工使用的计算机上配置,要与服务器端的监听程序信息一致(IP地址和端口)):
网络服务名:相当于访问服务器的路名,可以自己取名,如:orcl238。
主机名:是Oracle数据库所在计算机的IP地址,如:192.168.1.238。
端口号:Oracle服务器提供的监听端口,要与服务器端的监听程序端口一致。如:1521
服务名:全局数据库名(相当于单位名称),如:orcl
(2)修改配置文件(在…\dbhome_1\NETWORK\ADMIN目录下)
A、服务器端监听配置(…\dbhome_1\NETWORK\ADMIN\listener.ora)所需信息:
获取HOST,即安装Oracle服务器的计算机名:在windows系统桌面,用鼠标右击“计算机”图标,选择“属性”,即可找到计算机名;
获取SID_NAME 命令:select instance_name from v$instance;
获取GLOBAL_DBNAME命令:select * from global_name;
参考例子:
# listener.ora Network Configuration File: C:\app\Oracle\product\11.2.0\dbhome_1\NETWORK\ADMIN\listener.ora
# Generated by Oracle configuration tools.
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = ORCL)
(GLOBAL_DBNAME = ORCL)
(ORACLE_HOME = C:\app\Oracle\product\11.2.0\dbhome_1)
)
)
LISTENER =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = PC-20200221GVAQ)(PORT = 1521))
)
)
ADR_BASE_LISTENER = C:\app\Oracle
B、客户端服务命名(客户端服务命名(...\dbhome_1\NETWORK\ADMIN\tnsnames.ora)
获取SERVER 命令:select name from v$database;
获取SERVICE_NAME 命令:show parameter SERVICE;
获取INSTANCE_NAME命令:select instance_name from v$instance;
或:show parameter instance;
参考例子:
# tnsnames.ora Network Configuration File: C:\app\Oracle\product\11.2.0\dbhome_1\NETWORK\ADMIN\tnsnames.ora
# Generated by Oracle configuration tools.
LISTENER_ORCL =
(ADDRESS = (PROTOCOL = TCP)(HOST = PC-20200221GVAQ)(PORT = 1521))
ORCL =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = PC-20200221GVAQ)(PORT = 1521))
)
(CONNECT_DATA =
(SERVER = ORCL)
(SERVICE_NAME = orcl)
(INSTANCE_NAME = orcl)
)
)
(二)常用工具介绍
(一)、SQLPLUS工具(使用命令)
1、使用工具:sqlplus
(1) 进入工具,运行 ->cmd ,在出现的窗口中输入以下命令:(win10:win+R键))
sqlplus 或 sqlplus /nolog
(2) 登录到Oracle数据库。
connect 用户名/密码@服务命名
如果是超级用户,要加身份,其他用户不用。
超级用户:connect sys/密码@服务命名 as sysdba
普通用户:connect sys/密码@服务命名
(3) 断开用户连接
disconnect
2、启动数据库
startup
关闭数据库:
shutdown immediate (上课教学使用)
shutdown (工作中使用)
3、一些常用命令
(1)查看当前操作的用户:
show user;
(2)查看表结构:
desc 表名;
(3)、运行SQL文件命令(此命令比较实用,建议掌握)
start 或 @
例:start D:\temp\ao.txt
或
@ D:\temp\ao.txt
4、退出命令
quit 或 exit
(二)、开发工具SQL developer 工具,要求oracle数据库必须是启动的
准备工作:
数据库名:orcl
数据库服务器的计算机名或IP地址:gxjd IP地址:172.16.32.126
监听端口号:1521
连接名:由用户定义的: daxuelu
如果是sys用户,用户名为:sys as sysdba
以上信息可以在服务器的 net manager中获取。
在SQL Developer工具运行保存在文本文档文件的命令:
@ 路径\文件
例如:@ G:\sql\tables.sql;
(三)、OEM管理工具
1、网址:
https://计算机名或oracle服务器的IP地址:端口号/em
https://192.168.47.129:1158/em
如何找到oracle服务器的oem端口号?
<oracle主目录>\install\portlist.ini
2、启动OEM还需要什么条件?
启动服务:
(1)、两个oracle必须启动的服务:oracleService<sid> (实例服务) 、监听服务
(2)、OEM还需启动控制台服务:oracledbconsole<sid>
3、启动数据库
主机身份证明:
用户名:是oracle服务器所在计算机的操作系统用户:administrator
口令(不能为空):jsj
数据库身份证明:
用户名:oracle数据库的超级管理员:sys
口令:jsj
三、Oracle体系结构(1)
(一)常用关键字意思
db:DataBase 数据库
a:administrator(管理员)
dba:数据库管理员
f: file 文件
dbf: 数据文件
ctl:control(控制)
log:log(日志)
(二)体系结构(三个等式)
Oracle 数据库体系结构由物理存储结构和逻辑存储结构组成
三个等式:
Oracle数据库服务器 = 数据库 + 实例;
Oracle数据库(硬盘部分)= 数据文件(.dbf) + 控制文件(.ctl) + 日志文件(.log)
实例(内存部分) = 内存(SGA) + 进程;
(三)物理存储结构[三大类文件(在资源管理器中可以找到)]
1、基本知识
.ctl 控制文件(controlfile) 默认3个,内容一致,至少1个。
.dbf 数据文件(database file) 数据文件 布置应用系统必须要建立,通过创建表空间来创建
.log 日志文件(logfile),记录数据的变动情况
日志文件分两类:归档日志和重做日志
(1)redo重做 重做日志文件:redo001.log
(2)archivelog(归档日志)归档日志文件:XXX.arc
数据文件:datafile data(数据) file(文件)
控制文件:controlfile control(控制)file(文件)
日志文件:logfile log(日志) file(文件)
2、查看物理存储
select * from v$controlfile; 查看控制文件信息
select * from v$datafile; 查看数据文件信息
SELECT * FROM v$logfile; 查看重做日志文件信息
(四)逻辑存储结构
1、基本概念
逻辑结构是从逻辑的角度分析数据库的构成,即创建数据库后形成的逻辑概念之间的关系。
数据块是最小的组成单位,数据块组成了数据区间,数据区间组成了数据段,数据段构成表空间,最后表空间形成数据库。
2、查看逻辑存储(在资源管理器不找到的文件,这些信息存放在数据文件中)
(1)、数据库管理员(dba)看对象信息存放的系统表:dba_对象类型s;
例如:表空间信息存放的系统表:dba_tablespaces
select * from dba_tablespaces; 查看表空间信息
例如:普通表信息存放的系统表:dba_tables
select * from dba_tables; 查看表信息
例如:用户信息存放的系统表:dba_users
select * from dba_users; 查看用户信息
(2)、普通用户看自己拥有的对象信息存放的系统表:user_对象类型s;
例如:表对象存放的表:
user_tables、user_triggers
例如:普通表信息存放的系统表:user_tables
select * from user_tables; 查看表信息
例如:触发器信息存放的系统表:user_triggers
select * from user_triggers; 查看用户的触发器信息
(五)数据字典
1、概念
数据字典作为一种元数据,在Oracle中的作用是存放整个数据库实例的基本信息,很多的数据字典都必须以system或者是sysdba用户登录才能够使用的。这些数据字典的结构,可以通过输入“desc 数据字典名称”的方式查询。
2、常用数据字典:
(1) 查看USER视图(当前用户所拥有的表)
SQL>select table_name from USER_TABLES;
(2) 查看ALL视图(当前用户可以查询的表)
SQL>select table_name from ALL_TABLES;
(3) 查看DBA视图(查询数据库中所有的表)
SQL>select table_name from DBA_TABLES;
(4) 查询数据库中当前存在的Oracle用户
SQL>select username from dba_users;
(5) 查询本用户所拥有的系统权限
SQL>select * from user_sys_privs;
(6) 查询本用户拥有其他用户对象的权限
SQL>select * from user_tab_privs;
(7) 查询本用户拥有的对象
SQL>select * from user_catalog;
(8) 查询当前数据库的详细信息
SQL>select * from V
D
A
T
A
B
A
S
E
;
(
9
)
取得
o
r
a
c
l
e
版本的详细信息
S
Q
L
>
s
e
l
e
c
t
∗
f
r
o
m
V
DATABASE; (9) 取得oracle版本的详细信息 SQL>select * from V
DATABASE;(9)取得oracle版本的详细信息SQL>select∗fromVVERSION;
(10) 查看当前数据库所有日志文件的信息
SQL>select * from v
l
o
g
f
i
l
e
;
(
11
)
查看当前数据库所有控制文件的信息。
S
Q
L
>
s
e
l
e
c
t
∗
f
r
o
m
V
logfile; (11) 查看当前数据库所有控制文件的信息。 SQL>select * from V
logfile;(11)查看当前数据库所有控制文件的信息。SQL>select∗fromVCONTROLFILE;
(12) 查看当前数据库所有数据文件的详细信息。
SQL>select * from V$DATAFILE;
四、Oracle体系结构(2)
(一)软件项目部署到Oracle数据库服务器的过程
(1)建立存放软件系统数据存放的地方(创建数据文件,通过表空间)
(2)谁来 管理该软件或使用该软件?(建用户并授予权限)
(3)软件的数据如何组织和维护?(建表,增删改数据)
(4)使用系统数据提供信息(数据查询)
(5)数据的备份和恢复
(二)Oracle数据库SQL命令
(一)、命名规则:
驼峰式:第一个词全部小写,后面的每个词的第一个字母大写,如:studentName
下划线分割:每个词直接用下划线分割,如:student_name
推荐使用英语APP:有道翻译官
(二)、oracle操作命令对象分类
分为两类:数据库对象(逻辑存储)、数据(表的数据)
数据库对象:表空间(tablespace),用户(user),表(table),视图(view),过程(procedure),函数(function),触发器(trigger)等。
数据:存放在表的信息,操作时要指明表名。
(三)、常用SQL命令
1、三对命令(增删改)
(1) 增
数据:
insert into 表(列) values(列对应的值);
对象:
create 对象类型 对象名 操作;
例子:建表(table)
create table abc
(a char(10));
建用户(user)
create user laoou
identified by 密码;
建表空间tablespace
create tablespace student
datafile 'c:\student\stu.dbf'
size 100m;
(2)改
数据:
update 表
set 列=修改后的值
where 条件;
对象:
alter 对象类型 对象名 操作;
例子:修改用户的密码
alter user abc
identified by 新的密码;
alter user student
identified by jsj;
(3) 删
数据:
delete from 表名 where 条件;
对象:
drop 对象类型 对象名;
例子:drop user laoou cascade;
删除表student:
drop table student;
2、针对数据-事务管理
保存数据(提交事务): commit;
不保存数据(回退或回滚或撤销): rollback;
3、学数据库特别重要的命令
查询命令 select
select 字段(列)
from 表
where 条件
group by 分类统计的字段 having 用到函数做条件
order by 字段 DESC或ASC;
4、针对用户-权限管理
授权:grant
grant 权限 to 用户;
撤销权限:revoke
revoke 权限 from 用户;
(三)表空间管理(创建存放数据的地方)
表空间是Oracle数据库的最大逻辑划分区域,通常用来存放数据表、索引、回滚段等数据对象。一个表空间由一个或多个数据文件(操作系统物理存储结构)组成,一个数据文件只属于一个表空间。
表空间的大小等于所有从属于它的数据文件大小的总和。
(一)、知识准备
谁来创建? 数据库管理员(sys或system)
表空间:tablespace
表:table
空间:space
(二)、表空间管理
1、表空间的操作有:数据文件(datafile)、数据文件的大小(size)、数据文件数据填满后要自动扩展(autoextend on next)。
2、语法格式:
通用:create 对象类型 对象名 操作或属性;
具体:
create tablespace 表空间名
datafile '数据文件存放的路径\数据文件名.dbf'
size 文件大小
autoextend on next 自动扩展空间大小;
例子: 创建存放学生管理的表空间student,
数据文件名:stu.dbf 文件大小:50m,数据写满后每次扩展10m。
create tablespace student
datafile 'F:\wszh\stu.dbf'
size 50m
autoextend on next 10m;
3、查看创建的表空间命令:
select tablespace_name from dba_tablespaces;
4、课堂作业
创建表空间,要求:
表空间名:ylxt
文件:d:\temp\ylxt.dbf
大小:10M
自动扩展:1m
代码:
create tablespace ylxt
datafile 'd:\temp\ylxt.dbf'
size 10m
autoextend on next 1m;
五、SQL语言开发(上)-基本查询
(一)知识准备
1、作用:提供信息,Excel格式,在网站显示信息
2、谁来做?普通数据库用户、开发人员
3、演示用户:scott 密码:tiger
Oracle安装完成后scott用户默认是锁住的,要解锁,操作如下:
用管理员(system)登录SQL Developer工具,在SQL工作表输入以下命令并执行:
alter user scott account unlock; 给scott用户解锁
alter user scott identified by tiger; 把scott用户的密码改为tiger
4、scott用户拥有的表:
部门表(dept)
字段说明 名称 是否为空? 类型
-
部门编号 DEPTNO NOT NULL NUMBER(2)
部门编号 DNAME VARCHAR2(14)
部门位置 LOC VARCHAR2(13)
员工表(emp)
字段说明 名称 是否为空? 类型
-
员工编号 EMPNO NOT NULL NUMBER(4)
员工姓名 ENAME VARCHAR2(10)
职位 JOB VARCHAR2(9)
领导编号 MGR NUMBER(4)
雇佣日期 HIREDATE DATE
基本工资 SAL NUMBER(7,2)
奖金 COMM NUMBER(7,2)
部门编号 DEPTNO NUMBER(2)
工资等级表salgrade
字段说明 名称 是否为空? 类型
-
工资等级 GRADE NUMBER
最低工资 LOSAL NUMBER
最高工资 HISAL NUMBER
工资表bonus
字段说明 名称 是否为空? 类型
-
员工姓名 ENAME VARCHAR2(10)
职位 JOB VARCHAR2(9)
工资 SAL NUMBER
奖金 COMM NUMBER
5、建立以下理念:
一条select语句就是一张表
视图就是一条select语句
(二)语法格式:
select 显示的列或表达式(Excel的列) 约束显示的列,列之间用逗号分隔
from 显示的信息来源于哪里(Excel表单) 如果有多个表,表之间用逗号分隔
where 条件 约束显示的行
group by 分类统计的列 having 统计函数作为条件 如果有多个统计列,列之间用逗号分隔
order by 排序列1 asc或desc,排序列2 asc或desc,…;
提示:select语句必须有from子句,如果不能确定显示的信息来源于某张表,则使用伪表dual代替。
(三)书写查询语句常用的步骤:
(1) 确定显示的列 =>解决select子句
(2) 确定显示的列是来自于哪张表 =>from子句
(3) 确定条件 =>where子句
(4) 确定条件中是否有来自另外的表的列 =>from 子句
(5) 如果from子句后有多张表,则要加上表之间的连接关系(外键)。
(四)基本查询
(0) 显示所有列:*
select * from 表;
(1) 显示具体的列,列之间用逗号分隔
select empno,ename,sal
from emp;
(2) 加标题: as “标题”
select empno as “员工编号”,ename as “姓名” from emp;
(3) 字符串连接:||
select ename||‘_’||job as “姓名及职位” from emp;
(4) 去除重复的数据:distinct
select distinct deptno from emp;
(5) 使用表达式
SELECT ename, job, sal*12 FROM emp;
(6) 空值处理函数 空值=不确定的值
nvl(表达式1,表达式2)
如果表达式1为空值,则用表达式2代替它的值。
例如:nvl(comm,0)
六、SQL语言开发(上)-过滤数据
使用SELECT子句时,除了需要指定从哪一个表查询及需要查询的列名称之外,
通常会利用WHERE子句做进一步的条件限制,以实现更精确的查询。
在WHERE子句之后可以增加多个条件,最常见关系运算:
>、>=、<、<=、=、!=(<>)、BETWEEN…AND、LIKE、IN、IS NULL、AND、OR、NOT。
1、常用关系运算
查询编号为7521的职工的姓名、职位、雇用日期和基本工资。
SELECT ename , job , hiredate , sal FROM emp WHERE empno=7521 ;
要求查询出基本工资高于1500的所有雇员信息。
SELECT * FROM emp WHERE sal > 1500;
要求查询出职位是办事员(CLERK)的所有雇员信息。
SELECT * FROM emp WHERE job=‘CLERK’;
2、比较范围:between,in
(1) between 值是连续的
列 between 条件的下限 and 条件的上限;
等价于: 列>=条件的下限 and 列<=条件的上限;
例子:
select deptno
from emp
where deptno>=20 and deptno<=40;
或
select deptno
from emp
where deptno between 20 and 40;
(2) in 值是可以数得出来的
列 in (条件值1,条件值2,....,条件值n)
例子:
select deptno
from emp
where deptno in (20,40);
或
select deptno
from emp
where deptno=20 or deptno=40;
3、模糊查询
在where子句后加: 列 like 条件值 或 列 not like 条件值
两个通配符: _ 表示 任意一个字符,% 表示任意字符;
条件值的表示形式
以A开头的字符串:'A%'
以A结尾的字符串:'%A'
包含有A的字符串:'%A%'
如果第2个字符是A的字符串:'_A%'
例子:查询姓名是以A开头的员工;
select ename
from emp
where ename like 'A%';
查询姓名不是以A开头的员工;
select ename
from emp
where ename not like 'A%';
七、SQL语言开发(上)-分组查询
分组查询往往跟统计查询结合
1、语法格式:
select 显示的列或表达式(Excel的列) 约束显示的列,列之间用逗号分隔
from 显示的信息来源于哪里(Excel表单) 如果有多个表,表之间用逗号分隔
where 条件 约束显示的行
group by 分类统计的列 having 统计函数作为条件 如果有多个统计列,列之间用逗号分隔
order by 排序列1 asc或desc,排序列2 asc或desc,…;
注意:
(1)、where 和having用途:
共同点:条件
不同点:where对表的记录过滤, having对分组后形成的结果进行过滤
(2)、select后的列,只能是group by后的列和统计函数
2、统计函数
(1) count():返回找到的记录数
返回总记录数。
SELECT count(*) FROM emp;
返回comm不为空的总记录数。
SELECT count(comm) FROM emp;
(2) avg():返回一个数字列或计算列的平均值
返回所有员工的平均工资。
SELECT avg(nvl(sal,0)) FROM emp;
(3) sum():返回一个数字列或计算列的平均值
求该月本公司发出的工资总额。
SELECT sum(comm)+sum(sal) FROM emp;
(4) max():返回一个数字列或计算列的最大值
返回员工工资最大值。
SELECT max(sal) FROM emp;
(5) min():返回一个数字列或计算列的最小值
返回员工编号最小值。
SELECT min(empno) FROM emp;
3、例子
(1)、求出每个部门的员工人数。
SELECT deptno,count() as “人数”
FROM emp
GROUP BY deptno;
(2)、求出员工人数大于3的部门。
SELECT deptno,count() as “人数”
FROM emp
GROUP BY deptno having count(*)>3;
(3)、求出每个部门的员工的平均工资。
SELECT deptno,avg(nvl(sal,0))
FROM emp
GROUP BY deptno;
(4)、求出员工平均工资大于1500的部门。
SELECT deptno,avg(nvl(sal,0))
FROM emp
GROUP BY deptno having avg(nvl(sal,0))>1500;
(5)、显示平均工资大于等于2000的部门工资情况。
select deptno,count(*),sum(sal),to_char(avg(sal),'$999999.99'),max(sal),min(sal)
from emp
group by deptno having avg(sal)>=2000
order by deptno desc;
(6)、统计部门编号大于10且员工超过5人的部门工资情况。
select deptno,count(*),sum(sal),avg(sal),max(sal),min(sal)
from emp
where deptno>10
group by deptno having count(*)>5
order by deptno;
4、关于取小数点位数。
要用到转换函数:to_CHAR(表达式,格式)
例:12345.6789
to_CHAR(12345.6789,‘999999.99’)
select to_CHAR(12345.6789,‘999999.99’) from dual;
八、SQL语言开发(上)-多表查询
想要的数据不在同一张表,就需要多个表进行联查。
表连接类型:内连接、外连接
-
内连接
内连接:指表连接的结果只包含那些完全满足连接条件的记录。
(1). 等值连接(inner关键字可以省略)
指在连接条件中使用等于(=)运算符比较被连接的值。
例:使用内连接等值连接scott.emp和scott.dept两个表。
SELECT *
FROM scott.emp e INNER JOIN scott.dept d ON e.deptno = d.deptno;
或:
SELECT *
FROM scott.emp e JOIN scott.dept d ON e.deptno = d.deptno;
(2). 自然连接
自然连接(NATURAL JOIN)是在两个表中寻找列名和数据类型都相同的字段,通过相同的字段将两个表连接在一起,并返回所有符合条件的结果。
例:自然连接scott.emp和scott.dept两张表
SELECT * FROM scott.emp e NATURAL JOIN scott.dept d;注意: A、如果自然连接的两个表中有多个字段都满足名称和数据类型相同,那么它们都会被作为自然连接的条件。 B、如果自然连接的两个表中,仅仅字段名称相同,而字段的数据类型不同,那么使用该字段进行连接将会返回一个错误。 C、由于Oracle支持自然连接,那么在设计表时,应该尽量在不同的表中,将具有相同含义的字段使用相同的名字和数据类型。
-
外连接
外连接:外连接是对内连接的拓展,它是指包含完全符合的记录之外,还会包含驱动表所有不符合的连接条件的记录
(1) 左连接的情况:
SQL>select * from t1;
id col1A A1 B B1 C C1 D D1 SQL>select * from t2; id col2 A A2 C C2 D D2 E E2 SQL>select * from t1 left join t2 on t1.id=t2.id; 或 select * from t1,t2 where t1.id=t2.id(+); id col1 id col2 A A1 A A2 B B1 C C1 C C2 D D1 D D2
(2) 右连接:与左连接反过来,以被驱动表t2为准。
SQL>select * from t1 RIGHT join t2 on t1.id=t2.id;
或 select * from t1,t2 where t1.id(+)=t2.id;
id col1 id col2A A1 A A2 C C1 C C2 D D1 D D2 E E2
(3) 全外连接就是不管驱动表t1还是被驱动表t2全都查出来,不管是否符合连接条件,语法是full join on。
SELECT * FROM t1 a FULL JOIN t2 b ON a.id = b.id;
或
SELECT * FROM t1 a FULL OUTER JOIN t2 b ON a.id = b.id;
id col1 id col2A A1 A A2 B B1 C C1 C C2 D D1 D D2 E E2
九、SQL语言开发(下)-子查询
高级查询
(一)建立以下理念
理念1:查询结果可以看成一张表,查询语句就是一张表,select后跟的列就是这张表的字段
select emp_id
from (select empno as emp_id,deptno as dept_id,sal as salary from emp);
提示:子查询中的列是作为新表的列,如有别名,则别名作为新表的列名,所以别名要符合列名命名规则(别名不能用双引号引起来)。
以下例子实现翻页功能,每条select语句查询的结果都有rownum这一列:
select * from emp;
select rownum,emp.* from emp order by empno;
select rownum,emp.* from emp where rownum<=5 order by empno;
select rownum,emp.* from emp where rownum>=6 and rownum<=10 order by empno;
select *
from (select rownum,emp.* from emp order by empno)
where rownum>=6 and rownum<=10; --这样无法实现
正确的语句
select *
from (select rownum as rno,emp.* from emp order by empno)
where rno>=5*1+1 and rno<=5*1+5;
理念2:查询结果可以看成通过计算获得的结果。结果集
例:查询人数大于3的部门详细信息。
普通查询方式(不能获取部门的详细信息):
select deptno
from emp
group by deptno having count(*)>3;
子查询方式:
select deptno,dname,loc
from dept
where deptno in(select deptno
from emp
group by deptno having count(*)>3);
例:查询大于平均工资的员工信息:
以下命令无法实现,是错误的,where子句中不能使用统计函数。
select *
from emp
where sal>avg(sal);
使用子查询解决步骤
(1)、求平均工资
select avg(sal) from emp;
(2)、把步骤1得到的结果当成条件值。
select empno,ename,sal
from emp
where sal>(select avg(sal) from emp);
理念3:在查询语句里可以包含一条或多条查询语句。
1、什么时候用子查询?
(1) 条件的值是通过查询语句来获取;
(2) from后的表是通过查询语句来得到。
(3) 子查询不能带有order by 子句。
2、子查询举例
例1:求人数最多的部门。
求解过程
(1)求出部门人数最大值:
select max(count(*)) from emp group by deptno;
(2)把求出的部门人数最大值作为条件:
select deptno,count(*) from emp
group by deptno
having count(*)=(select max(count(*)) from emp group by deptno);
例2:求大于平均工资的员工信息。
求解过程
(1)用理解题意,用类查询语句表示
显示:员工信息 *
表:员工表 emp
条件:大于平均工资 >avg(sal)
表之间关系:无
(2)把(1)转换成查询语句步骤
A、转成查询语句,但平均工资不能再where子句使用,所有要先求出来。
select * from emp where sal>平均工资;
B、用查询语句求平均工资
select avg(sal) from emp;
C、把求出的平均工资查询语句替换A中的平均工资。
select * from emp where sal>(select avg(sal) from emp);
二、操作符
1. 单行单列子查询 (只有一个值)
返回一行数据,且只有一列值。
运算符:=,>=,<=,>,<,!=
例:查询emp表中,与Smith同一部门的所有员工
select * from emp where deptno=
(select deptno from emp where ENAME=‘SMITH’);这里的select查询只返回一行数据
2. 多行单列子查询(有多个值)
运算符:in,>all,<all,>any,<any,=any, not in
如果有多个条件值使用:in(包含),not in(不包含)
例:求工资为1500的员工信息
select * from employees where salary=1500;
或
select * from emp where empno=(select empno from emp where sal=1500);
或
select * from emp where empno in (select empno from emp where sal=1500);
例:查询所有员工中工作和部门10的工作一样的员工信息
select * from emp where job in
(select distinct job from emp where deptno=10); 这里的select查询返回多行记录
3.单行多列子查询
与单行单列子查询类似,
注意:条件中的列要括号括起来,且顺序与子查询select后的列一致
例:查询sal和comm和empno为7788相同的人员的信息:
select * from emp where (sal,comm)=(select sal,comm from emp where empno=7788);
4. 多行多列子查询
与多行单列子查询类似,
注意:条件中的列要括号括起来,且顺序与子查询select后的列一致
例:查询sal和comm和empno为10号部门人员相同的人员的信息:
select * from emp where (sal,comm)in(select sal,comm from emp where deptno=10);
十、SQL语言开发(下)-单行函数
(一)数值类函数
1. ROUND函数(四舍五入)
select round(45.923,2) 小数位,round(45.923,0) 整数位, round(45.923,-1) 十位,round(45.923,-2) 百位 from dual;
2. trunc函数(截断)(不会四舍五入)
select trunc(45.926,2) 截断 from dual;
3. mod函数(求余)
select mod(1600,300) 求于 from dual;
4. 组函数(统计函数)
–求员工的工资总和
select sum(sal) from emp;
–求个数
select count() from emp;
–求平均工资
select sum(sal)/count() 方式一, avg(sal) 方式二 from emp;
–关于空值:组函数会自动滤空
select count(*), count(comm) from emp;
–max和min:求最高工资和最低工资
select max(sal) 最高工资,min(sal) 最低工资 from emp;
–分组数据:求各个部门的平均工资
select deptno,avg(sal) from emp group by deptno;
–group by作用于多列: 按部门,不同的工种,统计平均工资
–group by作用于多列:先按照第一列分组;如果相同,再按照第二列分组
select deptno,job,avg(sal) from emp group by deptno,job;
–求部门的平均工资大于2000的部门
select deptno,avg(sal) from emp group by deptno having avg(sal)>2000;
(二)字符类函数
1. 大小写控制函数
select lower(‘Hello World’) 转小写, upper(‘Hello World’) 转大写 from dual;
2. initcap: 首字母大写
select initcap(‘hello world’) 首字符大写 from dual;
3. 字符控制函数
(1) concat: 字符连接函数, 等同于 ||
select concat(‘Hello’,’ World’) from dual;
(2) substr:求母串中的某个子串
select substr(‘Hello World’,3) from dual; --从第3个字符开始的字符串
select substr(‘Hello World’,3,4) from dual; --从第3个字符开始取长度为4的字符串
(3)length和lengthb: 字符数和字节数
select length(‘广西 China’) 字符数, lengthb(‘广西 China’) 字节数 from dual;
(4) instr:在母串中,查找子串的位置
select instr(‘Hello World’,‘ll’) from dual;
(5) lpad,rpad: 左右填充,将abcd用填充到10位
select lpad(‘abcd’,10,'‘) 左填充, rpad(‘abcd’,10,’‘) 右填充 from dual;
(6) trim: 去掉字符串前后指定的字符,如果不指定去掉字符则默认为空格
去除字符串左右的’H’字符
select trim(‘H’ from ‘Hello WorldHH’) from dual;
去除字符串左右的空格
select trim(’ Hello World ‘) from dual;
(7) replace:字符串替换函数
select replace(‘Hello Wordl’,‘l’,’') from dual; --l用*替换
(三)日期类函数
常用表示意思:
yyyy:年
mm:月
dd:日
hh、hh12或hh24:小时
mi:分
ss:秒
day:星期几
1. 改变日期显示格式
alter session set nls_date_format=‘yyyy-mm-dd hh24:mi:ss’;
或
alter session set nls_date_format=‘yyyy"年"mm"月"dd"日" hh24"时"mi"分"ss"秒" day’;
2. 显示当前日期
select sysdate from dual;
3. 显示时间部分
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;
4. 显示昨天,今天和明天,加减数字仍未日期
select sysdate-1 昨天, sysdate 今天, sysdate+1 明天 from dual;
5. 两个日期相减,结果为相差的天数,查询员工信息,显示员工工龄。两个日期不能相加
select empno,ename, sysdate-hiredate 天 from emp;
6. 查询员工信息,显示员工工龄,分别按照天,星期,月显示
select empno,ename,sysdate-hiredate 天,(sysdate-hiredate)/7 星期, (sysdate-hiredate)/30 月 from emp;
7. months_between:两个日期相差的月数
select (sysdate-hiredate)/30 方式一除30, months_between(sysdate,hiredate) 方式二months_between函数 from emp;
8. add_months:在指定日期上加上若干个月
select add_months(sysdate,1) 下个月, add_months(sysdate,123) "123个月后" from dual;
9. last_day: 某个日期当月的最后一天
select last_day(sysdate) from dual;
10. next_day:下周六
select next_day(sysdate,'星期五') from dual;
11. 对日期进行四舍五入
select round(sysdate,'MONTH') 月,round(sysdate,'YEAR') from dual;
12. 对日期进行截断
select trunc(sysdate,'MONTH') 月,trunc(sysdate,'YEAR') from dual;
13. 日期格式
select * from emp where hiredate=to_date('1982-01-23','yyyy-mm-dd');
14. 查询当前日期:显示: ............今天是星期六
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss"今天是"day') from dual;
select to_char(sysdate,'yyyy"年"mm"月"dd"日" hh24"时"mi"分"ss"秒" "今天是"day') from dual;
15. 查询员工信息,显示员工的编号,姓名,月薪,要求有货币代码(L),千位符(,),小数点(.),
select empno,ename,to_char(sal,'L9,999.99') from emp; --美元用$
(四)转换函数
从一种数据类型转换为另一种数据类型。
1. TO_CHAR() 本函数又可以分三小类,分别是
(1) 转换字符->字符TO_CHAR©:将nchar,nvarchar2,clob,nclob类型转换为char类型;
例:
SELECT TO_CHAR(‘AABBCC’) FROM DUAL;
(2) 转换时间->字符TO_CHAR(d[,fmt]):将指定的时间(data,timestamp,timestamp with time zone)按照指定格式转换为varchar2类型;
例:
SELECT TO_CHAR(sysdate,‘yyyy-mm-dd hh24:mi:ss’) FROM DUAL;
(3) 转换数值->字符TO_CHAR(n[,fmt]):将指定数值n按照指定格式fmt转换为varchar2类型并返回;
例1:
SELECT TO_CHAR(1234567890, ‘L999G999G999G999D99MI’) FROM DUAL;
提示:L:本地货币符’¥’,G:‘,’,D:‘.’,MI:‘-’
例2:
SELECT to_char(1234567890,‘099999999999999’) FROM dual;
SELECT to_char(12345678,‘999,999,999,999’) FROM dual;
SELECT to_char(123456,‘99.999’) FROM dual;
SELECT to_char(1234567890,‘999,999,999,999.9999’) FROM dual;
2. TO_DATE(c[,fmt[,nls]]) 将char,nchar,varchar2,nvarchar2转换为日期类型,如果fmt参数不为空,则按照fmt中指定格式进行转换。注意这里的fmt参数。如果ftm为’J’则表示按照公元制(Julian day)转换,c则必须为大于0并小于5373484的正整数。
例:
SELECT TO_DATE(2454336, ‘J’) FROM DUAL;
SELECT TO_DATE(‘2007-8-23 23:25:00’, ‘yyyy-mm-dd hh24:mi:ss’) FROM DUAL;
3. TO_NUMBER(c[,fmt[,nls]]) 将char,nchar,varchar2,nvarchar2型字串按照fmt中指定格式转换为数值类型并返回。
例:
SELECT TO_NUMBER('100.00', '9G999D99') FROM DUAL;
(五)通用函数
1. 空值转换函数:nvl()和nvl2()
nvl(exp1,exp2):当exp1为空时,返回exp2
nvl2(exp1,exp2,exp3):当exp1为空时,返回exp3;否则返回exp2
例:
select ename,sal*12+nvl2(comm,comm,0) 年收入 from emp;
2. NULLIF函数
NULLIF(expr1, expr2),如果expr1=expr2,返回null;否则,返回expr1
例:
select nullif(‘abc’,‘abc’) from dual;
select nullif(‘abc’,‘abcaa’) from dual;
3. COALESCE函数 (不常用)
COALESCE :找到参数列表中,第一个不为空的值
例:
select ename,comm,sal,COALESCE(comm,sal) from emp;
4. decode函数
decode(条件,值1,返回值1,值2,返回值2,…值n,返回值n,缺省值)
例:给员工涨工资,根据职位涨,总裁涨1000,经理涨600 其他人员涨400
select ename,job,sal 涨前工资, decode(job,‘PRESIDENT’,sal+1000,
‘MANAGER’,sal+600,
sal+400) 涨后工资
from emp;
例:根据员工表中职位显示职位名称,''
select decode(job,'CLERK','办事员','SALESMAN','销售员','MANAGER','经理','其他') from emp;
十一、SQL语言开发(下)-维护数据
***建议:先建好表及约束,再添加数据
(一)增加
语法格式:
insert into 表名(列1,列2,…,列n)
values(列值1,列值2,…,列值n);
insert into 表名 values(列值1,列值2,...,列值n);
提示:
(1) 如果在INSERT INTO后没有指定列名,那么VALUES子句必须按照表结构中定义的列的次序为每个列提供值。
查看表结构的命令:desc 表名;
(2) 如果在INSERT INTO子句中指定了列名,那么每一个指定的列只能有一个值,并且值的次序必须与表中定义的次序相同。
(3) 当某列的数据类型为字符串时,其值应该使用单引号括起来。
例:insert into scott.deptno(deptno,dname) values(80,'销售部');
使用SELECT语句添加数据,则INSERT INTO子句中指定的列名必须与SELECT子句中指定的列相匹配。
insert into 表名(列) 查询语句;
例:假设my_emp表和scott.emp表的表结构完全一致,将scott.emp表中deptno为10的数据插入my_emp表。
INSERT INTO my_emp
SELECT * FROM scott.emp WHERE deptno=10;
(二)修改
语法格式:
update 表名
set 列=新值
where 条件表达式;
例:在scott.emp表中,针对empno值为7935的员工,将sal的值增加200。
UPDATE scott.emp
SET sal = sal + 200
WHERE empno=7935 ;
(三)删除
语法格式:
delete from 表 where 条件表达式;
delete from dept where deptno>30;
例:删除scott.emp表中empno的值为7935的员工记录。
DELETE FROM scott.emp
WHERE empno = 7935 ;
(四)事务控制(数据保存)
提交事务(保存),从内存写到硬盘
commit;
回滚事务(不保存)
rollback;
或
rollback to 事务点名;
设置事务点
SAVEPOINT 事务点名;
例:向scott.emp表插入雇员编号为1111的记录,设置一个保存点,用UPDATE命令将该记录的雇员姓名修改为李明,然后用ROLLBACK命令回滚到保存点。
SQL>INSERT INTO scott.emp(empno) value(1111); --插入一行记录
SQL>SELECT * FROM scott.emp WHERE empno =1111; --姓名为NULL
SQL>SAVEPOINT p1; --设置保存点
SQL>UPDATE scott.emp SET ename='李明' WHERE empno =1111; --修改姓名为李明
SQL>SELECT * FROM scott.emp WHERE empno =1111; --查看更新结果
SQL> ROLLBACK to p1; --回滚到保存点p1,撤销部分事务
SQL>SELECT * FROM scott.emp WHERE empno =1111; --姓名又变为NULL
**** 如果已经写到硬盘,请使用闪回技术恢复。
十二、数据库对象创建、管理与维护 - 创建和管理表
(一)知识准备
***谁来做?项目的管理员或者开发者(普通用户)
管理员用户:sys(超级管理员,要亮明身份,用来启动和关闭数据库),system
***表放在哪里?
项目的表空间(数据文件)
***具备什么条件的用户才能建表?
权限:建表(create table)。
在项目表空间上分配有空间(安全管理章节讲解):分配配额(quota)
(二)数据类型
1. 数值型:number(P,S)
P:数据的长度 S:小数位
整数:number(4)
带小数的数:number(4,2) 99.99 小数位不算到长度
2. 字符型:字符型数据用单引号引起来,例: ‘莫有才’
固定长度:char(n)
例: char(8) 莫有才 占用字节数8
可变长度:varchar2(n)
例:varchar2(8) 莫有才 占用字节数6
3. 日期型: date
中国人喜欢的日期格式:
yyyy-mm-dd hh24:mi:ss
如何修改显示日期的格式:
alter session set nls_date_format=‘yyyy-mm-dd hh24:mi:ss’;
查看系统时间:
select sysdate from dual; --dual 伪表,显示的信息不是来自于具体的表
例:获取年月日
select to_char(sysdate,‘yyyy-mm-dd’) from dual;
select to_char(sysdate,‘yyyy’) from dual;
select to_char(sysdate,‘mm’) from dual;
select to_char(sysdate,‘dd’) from dual;
4. LOB型:blob、clob、Bfile
用于存放: 声音、图像、视频、文档等
(三)表操作
1. 建表:
(1) 表的操作:字段(列)、数据类型及长度、约束。
(2) 语法格式
通用:
create 对象类型 对象名 操作;
具体:
create table 表名
(
列1 数据类型 列约束1,
…
列n 数据类型 列约束n,
表(行) 约束1,
...
表(行)约束n
);
例:创建学生表(student)
create table student
(
xuh number(3) , --序号
xueh char(11) , --学号
xingm char(8) --姓名
);
例:创建部门表(department)
create table department
(
deptid number(4)
);
例:创建员工表(employee)
create table employee
(
empid number(4),
ename varchar2(10),
salary number(10,2) ,
sex varchar2(2),
deptid number(4)
);
(3) 使用查询语句建表
语法格式:
create table 表名
as 查询语句;
2. 修改表(alter table)
通用语法格式:
alter table 表 操作;
(1) 增加字段
ALTER TABLE 表名
ADD (列 数据类型);
例:
ALTER TABLE student
ADD(age NUMBER(3), birthday DATE DEFAULT SYSDATE);
(2) 修改字段名
ALTER TABLE 表名
RENAME COLUMN 旧列名 TO 新列名;
例:
ALTER TABLE student
RENAME COLUMN age TO nianl;
(3) 修改字段类型
alter table 表名
modify(列 新的数据类型);
例:
ALTER TABLE student
MODIFY(xingm VARCHAR2(10));
(4) 删除字段
ALTER TABLE 表名
DROP COLUMN 删除的字段名;
例:
ALTER TABLE student
DROP COLUMN age;
3. 删除表(drop table)
语法格式:
drop table 表名;
十三、数据库对象创建、管理与维护 - 创建和管理约束
五种类型:
非空(not null)、
唯一(unique)、
检查(check)、
主键(primary key)、
外键(references或foreign key)
(一) 非空约束(not null 或 null),字段默认是null
什么是空值? 不确定的值
空值跟空格有什么区别? 空格是一个确定的值,空值没有具体值
性别的值不为空 :性别 is not null
性别的值为空 : 性别 is null
***如何在表中定义非空约束(由于字段默认是null,可以有空值的列不用定义):
create table 表名
( 字段 字段类型 列级约束,
....
字段 字段类型 not null,
表(行)级约束,
...
表(行)级约束
);
(二)唯一(unique): 唯一标识一行数据,可以有空值(null,不确定的值)
如何在表中定义唯一列
create table 表名
( 字段 字段类型 列级约束,
…
字段 字段类型 unique,
表(行)级约束,
…
表(行)级约束
);
(三) 检查(check):某一列的有输入条件
(1) 数学中的条件表达式在编程语言或 数据库中如何表示?
数 学:0<=成绩<=100
计算机:成绩>=0 and 成绩<=100
(2) 如何在表中定义检查约束
create table 表名
( 字段 字段类型 列级约束,
....
字段 字段类型 check (条件表达式),
表(行)级约束,
...
表(行)级约束
);
(四)主键(primary key):唯一标识一行数据,如身份证号码,不能有空值。
***每个表必须有主键吗?
表可以不建任何约束,所以表可以没有主键
***主键跟唯一约束有什么区别?
主键列的值不能有空值,而唯一约束的列的值可以有空值。
***如何在表中建主键
(1) 如果主键 是一列
create table 表名
( 字段1 字段类型 primary key,
....
字段n 字段类型 列级约束n,
表(行)级约束1,
...
表(行)级约束n
);
(2) 如果主键 是多列
create table 表名
( 字段1 字段类型 列级约束1,
....
字段n 字段类型 列级约束n,
primary key(字段1,字段2,...)
);
(五)外键(references、foreign key):某张表某一列的值必须要在另一张表对应的列上有相应的值。
关联
***如何在表中定义外键
1. 如果外键 是一列
create table 表名
( 字段1 字段类型 列级约束1,
…
字段n 字段类型 references 外键对应表( 外键对应表的主键或唯一约束的列),
表(行)级约束1,
…
表(行)级约束n
);
例:t_b表的a列的值受到t_a表a列值的约束,即在t_b表要建外键。
create table t_a
(a number(4,5) PRIMARY KEY,
b char(8)
);
create table t_b
(a number(4,2) references a(a),
b char(8),
);
2. 如果外键 是多列
create table 表名
( 字段1 字段类型 列级约束1,
....
字段n 字段类型 列级约束n,
foreign key (字段1,字段2,...) references 外键对应表(外键对应表的主键(或唯一)字段1,字段2,...)
);
例:t_bb表的a、b列的值受到t_aa表a、b列值的约束,即在t_bb表要建外键。
create table t_aa
(a number(4,5),
b char(8),
PRIMARY KEY(a,b)
);
create table t_bb
(a number(4,2),
b char(8),
foreign KEY (a,b) references a(a,b)
);
(六) 默认值(default)
***如何在表中定义默认值,要跟再字段类型后,其他列级约束之前。
create table 表名
( 字段1 字段类型 列级约束1,
…
字段n 字段类型 default 默认值 列级约束n,
表(行)级约束1,
…
表(行)级约束n
);
(七)添加、修改和删除约束
通用语法格式:
ALTER TABLE 表名
ADD constraint 约束名
操作;
1. 添加约束
(1). 主键
ALTER TABLE 表名
ADD constraint 约束名
primary key(主键列);
(2). 唯一
ALTER TABLE 表名
ADD constraint 约束名
unique(唯一约束列);
(3). 检查
ALTER TABLE 表名
ADD constraint 约束名
check( 条件表达式 );
(4). 非空
创建表时,列默认是空值,所以只能是修改非空约束。
ALTER TABLE 表名
MODIFY (列名 NOT NULL或NULL);
(5). 外键
ALTER TABLE 表名
ADD constraint 约束名
foreign key ( 外键列 ) references 外键对应表(外键对应表的主键);
(6). 默认值
只能是修改,不存在添加。
ALTER TABLE 表名
MODIFY (列名 DEFAULT 默认值 );
2. 修改约束
采用先删除要修改的约束,然后再重新添加该约束来实现。
3. 删除约束
语法格式:
ALTER TABLE 表名
DROP constraint 约束名;
(八)举例
例:创建学生表(student)
create table student
(
xuh number(3) unique check (xuh>=1 and xuh<=999), --序号
xueh char(11) primary key, --学号
xingm char(8) not null --姓名
)
例:创建部门表(department)
create table department
(
deptid number(4) primary key,
dname varchar2(20) unique
);
例:创建员工表(employee)
create table employee
(
empid number(4) primary key,
ename varchar2(10) unique,
salary number(10,2) default 0,
sex varchar2(2) default '男' check (sex='男' or sex='女'),
deptid number(4) references department(deptid)
);
十四、数据库对象创建、管理与维护 - 创建和管理视图
核心知识:查询语句 ->表,值
(一)视图简介
视图是虚表,查看数据的窗口,本质上只是sql语句,不存储数据。
(二) 视图作用
简化数据操作:视图可以简化用户处理数据的方式。
着重于特定数据:不必要的数据或敏感数据可以不出现在视图中。
视图提供了一个简单而有效的安全机制,可以定制不同用户对数据的访问权限。
提供向后兼容性:视图使用户能够在表的架构更改时为表创建向后兼容接口。
自定义数据:视图允许用户以不同方式查看数据。
导出和导入数据:可使用视图将数据导出到其他应用程序。
总之,简化查询,提高安全性。
(三)视图分类
视图分类:简单视图、复杂视图。
简单视图只从单表里获取数据;复杂视图从多表里获取数据。
简单视图不包含函数和数据组;复杂视图包含函数和数据组。
简单视图可以实现增删改操作;复杂视图不可以。
(四)创建视图(view)
1. 在创建视图之前需要确认当前用户是否有创建视图权限。
(1) 查看当前用户(如scott)拥有的创建视图的权限或角色
select * from user_sys_privs; --查看用户的系统权限
select * from user_role_privs; --查看用户的角色
(2) 使用管理员(SYSTEM)登录,并给SCOTT用户创建视图权限。
grant create view to scott; --授予用户创建视图权限
例:创建简单视图
create view v_dept
as
select * from dept;
测试
select * from v_dept;
2. 创建视图
语法格式:
CREATE [OR REPLACE] [FORCE|NOFORCE] VIEW view_name
[(alias[, alias]...)]
AS subquery
[WITH CHECK OPTION [CONSTRAINT constraint]]
[WITH READ ONLY]
解释:
OR REPLACE :若所创建的试图已经存在,ORACLE自动重建该视图;
FORCE :不管基表是否存在ORACLE都会自动创建该视图;
NOFORCE :只有基表都存在ORACLE才会创建该视图:
alias :为视图产生的列定义的别名;
subquery :一条完整的SELECT语句,可以在该语句中定义别名;
WITH CHECK OPTION :插入或修改的数据行必须满足视图定义的约束;
WITH READ ONLY :该视图上不能进行任何DML操作。
(1) 创建简单视图
简单视图是指基于单个表建立的,不包含任何函数、表达式和分组数据的视图。
例:基于emp表创建一个vw_emp视图。
CREATE VIEW vw_emp
AS
SELECT empno,ename,job,hiredate,deptno FROM emp;
简单视图创建后,可以跟表一样进行使用。例如:
DESC vw_emp; --显示视图的结构
SELECT * FROM vw_emp WHERE deptno=10; --查询
INSERT INTO vw_emp VALUES(1234,'JACK','CLERK','29-4月-1963',10); --增加
UPDATE vw_emp SET ename='刘德华' WHERE ename='JACK'; --更新
DELETE vw_emp WHERE ename='刘德华'; --删除
(2) 只读视图, 保证数据安全。
创建简单视图:只读
create or replace view v_temp1
as
select empno,ename,job,mgr from emp
with read only;
测试(不能插入)
insert into v_temp1(empno,ename,job,mgr) values(1,'David','coder',9300);
(3) 创建检查视图,对通过视图进行的增删改操作进行检查,只有满足条件的数据才可以增加、修改。
例如:
CREATE VIEW vw_emp_check
AS
SELECT empno,ename,job,hiredate,deptno
FROM emp WHERE deptno=10
WITH CHECK OPTION CONSTRAINT vw_emp_chk ;
要求增删改操作的数据必须是SELECT查询所能查询到的数据,若执行下面的语句:
INSERT INTO vw_emp_check
VALUES (1235,'JACK','CLERK','29-4月-1963',20);
是无法执行成功的,由于20号部门不在查询范围内,违反检查约束。
(4) 创建连接视图
连接视图是指基于多个表所创建的视图,即定义视图的查询是一个连接查询,主要目的是为了简化连接查询。
例:查询部门编号为10和30的部门及雇员信息。
CREATE VIEW vw_dept_emp
AS
SELECT a.deptno,a.dname,a.loc,b.empno,b.ename,b.sal
FROM dept a , emp b
WHERE a.deptno=b.deptno
AND a.deptno in (10,30);
(5) 创建复杂视图
复杂视图是指包含函数、表达式、或分组数据的视图。主要目的是为了简化查询,用于执行查询操作,并不用于执行DML操作。
提示:当视图的SELECT查询中包含函数或表达式时,必须为其定义列别名。
例:查询目前每个岗位的平均工资、工资总和、最高工资和最低工资。
CREATE VIEW vw_emp_job_sal
(job,avgsal,sumsal,maxsal,minsal)
AS
SELECT job,avg(sal),sum(sal),max(sal),min(sal)
FROM emp
GROUP BY job;
(6) 强制创建视图
正常情况下,如果基表不存在,视图创建就会失败。但是可以使用FORCE选项强制创建视图(前提是创建视图的语句没有语法错误),此时该视图处于失效状态,当基表存在时,视图有效。
例:test_tab表不存在,但可以强制创建视图。
CREATE FORCE VIEW vw_test_tab
AS
SELECT c1,c2 FROM test_tab;
查询视图的状态,可以看到视图状态为INVALID。
SELECT object_name,status
FROM user_objects
WHERE object_name='VW_TEST_TAB';
创建test_tab表
CREATE TABLE test_tab
(c1 number(9) primary key, c2 varchar2(20),c3 varchar2(30));
再次查询视图的状态,可以看到视图状态为VALID。
SELECT object_name,status
FROM user_objects
WHERE object_name='VW_TEST_TAB';
(五)删除视图
语法格式:
drop view 视图名;
删除视图的定义不影响基表中的数据。
只有视图所有者和具备DROP VIEW权限的用户可以删除视图。
视图被删除后,基于被删除视图的其他视图或应用将无效。
(六)查看视图
可以使用数据字典视图,相关的数据字典如下:
dba_views:数据库中的所有视图(管理员操作);
all_views:用户“可访问的”视图;
user_views:“用户拥有的”视图;
dba_tab_columns:数据库中的所有视图的列(或表的列)(管理员操作);
all_tab_columns:用户“可访问的”视图的列(或表的列);
user_tab_columns:“用户拥有的”视图的列(或表的列)。
例:查询当前方案中所有视图的信息。
SELECT view_name,text FROM user_views;
十五、PL/SQL语言开发(1)
(一)PL/SQL概述
PL/SQL是一种高级的数据库程序设计语言,专门使用与Oracle语言基于数据库的服务器的内部,所以PL/SQL代码可以对数据库进行快速的处理。
1、什么是PL/SQL?
PL/SQL包含过程化语句和SQl语句,是对于SQL语言的一个补充,将SQL语言通过过程化的结构融合在一起。
2、PL/SQL的优点?
(1) 基于数据库的内部,所有速度是很快的,有利于提高性能
开发过程的时候,将PL/SQL块直接放在应用程序中,PL/SQL将整个语句发生给服务器,这个过程在单次执行的时候完成,降低网络拥挤,一般的SQL语句,是单独的监护,在网络环境中浪费大量的带宽,影响响应的时间。
(2) 可重用性
只要在Oracle下就可以使用,并不需要关心系统,无需修改代码。
(3)模块化
一个PL/SQL可以包含一个或者多个程序块,每一块的都实现一个逻辑操作,可以将任务进行分割,有不同的模块来完成。并且块之间是可以嵌套的。
3、PL/SQLl块分类
匿名块(在服务器端不驻留)
命名块(在服务器端驻留)存储过程、触发器、函数、包
(二)基本语法
1、程序结构:
DECLARE
–声明部分,变量定义部分
BEGIN
–执行部分,程序代码部分
[EXCEPTION] --[]表示异常处理部分可以没有
–异常处理部分
END;
(1) 声明部分
包含了变量和常量的定义。这个部分由关键字DECLARE开始,如果不声明变量或者常量,可以省略这部分。
(2) 执行部分
是PL/SQL块的指令部分,由关键字BEGIN开始,END结尾。所有的可执行PL/SQL语句都放在这一部分,该部分执行命令并操作变量。其他的PL/SQL块可以作为子块嵌套在该部分。PL/SQL块的执行部分是必选的。
(3) 异常处理部分
该部分是可选的,用EXCEPTION关键字将可执行部分分成两个小部分,之前的程序是正常运行的程序,一旦出现异常就跳转到异常部分执行。
2、注释
单行:--
多行: /* .... */
3、标识符
以字母开头,后边跟字母、数字、美元符($)、井号(#)、下划线(_),字符长度不能超过30。
4、字符串连接符和运算符
赋值运算符 :=
字符串连接 ||
5、数据类型
数值型:number
字符型: char, varchar2
日期型: date
布尔型: boolean
6、变量(variable)与常量
定义格式:
变量名 [constant] 数据类型 [:= 初始值];
如果加constant关键字表示定义的是一个常量,必须要赋初始值。
7、输出语句
(1) 如果要输出信息,则必须设置 serveroutput为ON,命令如下:
set serveroutput on
(2) 输出信息语句:
dbms_output.put_line(输出的信息);
8、键盘输入数据,使用&地址符,如果是字符型数据要加单引号引起来,数值数据不用,如:'&str'
例1:变量定义、赋值、输出。
declare
pnumber number(7,2);
pname varchar2(20);
pdate date;
begin
pnumber:=12;
pname:='张三';
pdate:=sysdate;
dbms_output.put_line(pnumber);
dbms_output.put_line(pname);
dbms_output.put_line(pdate+1);
end;
例2:数据输入、输出
--接收一个键盘输入
--num:地址值,含义是:在该地址上保存了输入的值
accept num prompt '请输入数据:';
declare
--定义变量保存用户从键盘输入数据
pnum number:= # --&地址符号,将num地址上的值赋给pnum
begin
dbms_output.put_line('您输入的数据是:'||pnum);
end;
提示:accept语句可以省略。
(三)两种与表有关的数据类型(比较重要,请掌握)
1、%type类型
作用:使变量的类型与某张表的某个字段类型一样。
好处:当某个字段类型发生改变时,并不用改动程序
例:定义变量v_ename,数据类型与emp表的ename字段类型一致。
v_ename emp.ename%type
2、%rowtype类型
作用:使得变量的类型跟表结构一样,可以存放一行数据
例:定义变量v_emp,数据类型与emp表结构一致。
v_emp emp%rowtype
3、如何在程序中使用%type和%rowtype两种类型变量
通常再程序的select、insert、update、delete语句中使用
例:查询语句的在程序中使用
(1) 以下程序能否运行?如果不能,该如何修改代码?
declare
begin
select empno,ename,sal from emp where empno=7788;
end;
提示:在程序中select语句获得的数据必须存放到变量中。
SELECT 列 INTO 变量 from 表 where 条件;
(2) 解决方案1:使用%type类型
declare
v_empno emp.empno%type;
v_ename emp.ename%type;
v_sal emp.sal%type;
begin
select empno,ename,sal into v_empno,v_ename,v_sal from emp where empno=7788;
dbms_output.put_line(v_empno||' '||v_ename||' '||V_sal);
end;
(3) 解决方案2:使用%rowtype类型
declare
v_emp emp%rowtype;
begin
select * into v_emp from emp where empno=7788;
dbms_output.put_line(v_emp.empno||' '||v_emp.ename||' '||V_emp.sal);
end;
4、如果查询获得的数据有多行,该如何处理?
declare
begin
for i in (select * into v_emp from emp) loop --i是记录类型变量
dbms_output.put_line(i.empno||' '||i.ename||' '||i.sal);
end loop;
end;
十六、PL/SQL语言开发(2)
***基本结构:顺序、分支、循环
(一)顺序结构
人生的道路一帆风顺。
例:
BEGIN
DBMS_OUTPUT.PUT_LINE(‘我是莫有才’);
DBMS_OUTPUT.PUT_LINE(‘我正在写PL/SQL程序’);
END;
(二)分支结构
人生总要面临各种抉择。
1、单分支语句
语法格式:
if 条件 then
语句块;
end if;
2、多分支语句
语法格式:
if 条件 then
语句块;
elsif 条件 then
语句块;
else
语句块;
end if;
3、CASE语句
语法格式:
CASE 条件
when 常量 then 语句;
…
else 语句;
end case;
(三)循环结构
有些事情不可能一次完成,需要不停的重复去做。
1、FOR语句
语法格式:
for 循环变量 in 下限…上限或数据集
loop
语句块;
end loop;
2、WHILE语句
语法格式:
while 继续循环的条件
loop
语句块;
end loop;
3、LOOP语句
语法格式:
loop
语句块;
exit when 退出循环的条件;
end loop;
人生的道路不可能一帆风顺,就像《真心英雄》歌曲所唱的:
把握生命里的每一分钟,
全力以赴我们心中的梦,
不经历风雨 怎么见彩虹,
没有人能随随便便成功。
(四)举例
1、根据考试批次计算考生成绩
1:+5
2:+3
3 - 4:+0
5: -3
6: -5
(1) 分析
如果批次为1,则成绩+5;
IF 批次为1,THEN 成绩+5 END IF;
如果批次为2,则成绩+3;
IF 批次为2,THEN 成绩+3 END IF;
…
(2) 程序代码
代码1:变量没有初始值
declare
v_pc number(4);
v_CJ number(5);
begin
IF v_PC=1 THEN
v_CJ:=v_CJ+5;
END IF;
dbms_output.put_line(‘成绩=’||v_CJ);
end;
代码2:给变量赋初始值
declare
v_PC number(4):=1;
v_CJ number(5):=0;
begin
IF v_PC=1 THEN
v_CJ:=v_CJ+5;
END IF;
dbms_output.put_line(‘成绩=’||v_CJ);
end;
代码3: 通过键盘输入数据,并把数据赋值给相应的变量
--使用IF语句
accept pc prompt '请输入批次:';
accept cj prompt '请输入成绩:';
declare
v_PC number(4):=&pc;
v_CJ number(5):=&cj;
begin
IF v_PC=1 THEN
v_CJ:=v_CJ+5;
END IF;
IF v_PC=2 THEN
v_CJ:=v_CJ+3;
END IF;
IF v_PC=3 or v_PC=4 THEN
v_CJ:=v_CJ-3;
END IF;
IF v_PC=5 THEN
v_CJ:=v_CJ-5;
END IF;
dbms_output.put_line('成绩='||v_CJ);
end;
--使用CASE语句1,条件放到case子句
accept pc prompt '请输入批次:';
accept cj prompt '请输入成绩:';
declare
v_PC number(4):=&pc;
v_CJ number(5):=&cj;
begin
case v_pc
when 1 THEN
v_CJ:=v_CJ+5;
when 2 THEN
v_CJ:=v_CJ+3;
when 3 THEN
v_CJ:=v_CJ-3;
when 4 THEN
v_CJ:=v_CJ-3;
when 5 THEN
v_CJ:=v_CJ-5;
else
v_cj:=v_cj+0;
END case;
dbms_output.put_line('成绩='||v_CJ);
end;
--使用CASE语句2,把条件放到when子句
accept pc prompt '请输入批次:';
accept cj prompt '请输入成绩:';
declare
v_PC number(4):=&pc;
v_CJ number(5):=&cj;
begin
case
when v_pc=1 THEN
v_CJ:=v_CJ+5;
when v_pc=2 THEN
v_CJ:=v_CJ+3;
when v_pc in(3,4) THEN
v_CJ:=v_CJ-3;
when v_pc=5 THEN
v_CJ:=v_CJ-5;
else
v_cj:=v_cj+0;
END case;
dbms_output.put_line('成绩='||v_CJ);
end;
例2:求1到100数相加的值
***使用FOR语句
declare
s number(5):=0;
begin
for i in 1..100
loop
s:=s+i;
end loop;
dbms_output.put_line('s='||s);
end;
***使用WHILE语句
declare
i number(4):=1;
s number(5):=0;
begin
while i<=100
loop
s:=s+i;
i:=i+1;
end loop;
dbms_output.put_line('s='||s);
end;
***使用LOOP语句
declare
i number(4):=1;
s number(5):=0;
begin
loop
exit when i<=100;
s:=s+i;
i:=i+1;
end loop;
dbms_output.put_line('s='||s);
end;
十七、PL/SQL语言开发(3)
***游标(经常使用,建议理解并掌握)
(一)游标的概念
游标(CURSOR)是Oracle系统在内存中开辟的一个工作区,在其中存放SELECT语句返回的查询结果。
使用游标时,SELECT语句查询的结果可以是单条记录,多条记录,也可以是零条记录。
游标工作区中,存在着一个指针(POINTER),在初始状态它指向查询结果的首记录。
(二)游标的类型
显式游标: 由用户定义、操作,用于处理返回多行数据的SELECT查询。
隐式游标: 由系统自动进行操作,用于处理DML语句(INSERT、UPDATE、DELETE)和返回单行数据的SELECT查询。
(三)显式游标基础
1、使用游标操作步骤
(1) 定义游标
语法:
CURSOR cursor_name[(参数1 数据类型[,参数2 数据类型…])]
IS 查询语句;
说明:
[]表示这部分可以没有;
游标必须在PL/SQL块的声明部分进行定义;
游标定义时可以引用PL/SQL变量,但变量必须在游标定义之前定义;
定义游标时并没有生成数据,只是将定义信息保存到数据字典中;
游标定义后,可以使用cursor_name%ROWTYPE定义游标类型变量。
注意:
定义参数化游标时,只能指定参数的类型,而不能指定参数的长度、精度、刻度;
(2) 打开游标
语法:
OPEN cursor_name[(parameter1[,parameter2…])] ;
说明:
[]表示这部分可以没有;
执行游标定义的select语句,将查询结果检索到工作区中;
游标指针指向第一个元组;
游标一旦打开,就无法再次打开,除非先关闭。
注意:
打开带参数的游标时,实参的个数和数据类型等必须与游标定义时形参个数和数据类型等相匹配。
(3) 检索游标
语法:
FETCH cursor_name INTO 变量或记录变量;
说明:
对游标第一次使用FETCH语句时,指向第一条记录,使用后,游标指针指向下一条记录;
游标指针只能向下移动,不能回退;
INTO子句的变量个数、顺序、类型必须与定义的SELECT子句一致。
(4) 关闭游标
语法 :
CLOSE cursor_name;
2、显式游标的属性
(1) %ISOPEN
布尔型。如果游标已经打开,返回TRUE,否则为FALSE。
(2) %FOUND
布尔型,如果最近一次使用FETCH语句,有返回结果则为TRUE,否则为FALSE;
(3) %NOTFOUND
布尔型,如果最近一次使用FETCH语句,没有返回结果则为TRUE,否则为FALSE;
(4) %ROWCOUNT
数值型,返回到目前为止从游标缓冲区检索的元组数。
3、举例
根据输入的部门号查询某个部门的员工信息,部门号在程序运行时指定。
(1) 使用不带参数的游标
DECLARE
--定义与部门编号类型一样的变量
v_deptno emp.deptno%TYPE;
CURSOR c_emp IS SELECT * FROM emp WHERE deptno=v_deptno;
v_emp c_emp%ROWTYPE;
BEGIN
v_deptno:=&输入部门编号;
OPEN c_emp;
LOOP
FETCH c_emp INTO v_emp;
EXIT WHEN c_emp%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_emp.empno||' '||v_emp.ename||' '||v_emp.sal||' '|| v_deptno);
END LOOP;
CLOSE c_emp;
END;
(2) 使用带参数的游标
DECLARE
--定义与部门编号类型一样的变量
v_deptno emp.deptno%TYPE;
--定义游标c_emp,其参数v_did与部门编号类型一样的变量
CURSOR c_emp(v_did emp.deptno%TYPE) IS SELECT * FROM emp WHERE deptno=v_did;
--定义游标变量
v_emp c_emp%ROWTYPE;
BEGIN
v_deptno:=&输入部门编号;
OPEN c_emp(v_deptno); --打开游标时游标名不能带参数
LOOP
FETCH c_emp INTO v_emp; --fetch时游标名不能带参数
EXIT WHEN c_emp%NOTFOUND; --判断游标属性时游标名不能带参数
DBMS_OUTPUT.PUT_LINE(v_emp.empno||' '||v_emp.ename||' '||v_emp.sal||' '|| v_deptno);
END LOOP;
CLOSE c_emp;
END;
十八、PL/SQL语言开发(4)
四、显式游标的检索
1、利用loop语句实现简单循环检索游标
(1) 语法:
DECLARE
CURSOR cursor_name IS SELECT…;
BEGIN
OPEN cursor_name;
LOOP
FETCH…INTO…;
EXIT WHEN cursor_name%NOTFOUND;
……
END LOOP;
CLOSE cursor_name;
END;
注意:EXIT WHEN子句应该是FETCH…INTO语句的下一条语句。
(2) 例:利用简单循环统计并输出各个部门的平均工资。
DECLARE
CURSOR c_dept_stat
IS
SELECT deptno,avg(sal) as avgsal
FROM emp
GROUP BY deptno;
v_dept c_dept_stat%ROWTYPE;
BEGIN
OPEN c_dept_stat;
LOOP
FETCH c_dept_stat INTO v_dept;
EXIT WHEN c_dept_stat%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_dept.deptno||' '||v_dept.avgsal);
END LOOP;
CLOSE c_dept_stat;
END;
2、利用WHILE循环检索游标
(1) 语法:
DECLARE
CURSOR cursor_name IS SELECT…;
BEGIN
OPEN cursor_name;
FETCH…INTO…;
WHILE cursor_name%FOUND
LOOP
FETCH…INTO…;
……
END LOOP;
CLOSE cursor;
END;
注意:在循环体外进行一次FETCH操作,作为第一次循环的条件。
(2) 例子:利用WHILE循环统计并输出各个部门的平均工资。
DECLARE
CURSOR c_dept_stat IS SELECT deptno,
avg(sal) as avgsal FROM emp
GROUP BY deptno;
v_dept c_dept_stat%ROWTYPE;
BEGIN
OPEN c_dept_stat;
FETCH c_dept_stat INTO v_dept;
WHILE c_dept_stat%FOUND
LOOP
DBMS_OUTPUT.PUT_LINE(v_dept.deptno||' '||
v_dept.avgsal);
FETCH c_dept_stat INTO v_dept;
END LOOP;
CLOSE c_dept_stat;
END;
3、利用FOR循环检索游标
(1) 语法:
DECLARE
CURSOR cursor_name IS SELECT…;
BEGIN
FOR loop_variable IN cursor_name
LOOP
……
END LOOP;
END;
说明:
系统隐含地定义了一个数据类型为%ROWTYPE的变量,并以此作为循环的计算器。
系统自动打开游标,不用显式地使用OPEN语句打开;
系统重复地自动从游标工作区中提取数据并放入计数器变量中。
系统自动进行%FOUND属性检查以确定是否有数据
当游标工作区中所有的记录都被提取完毕或循环中断时,系统自动地关闭游标。
(2) 例子:利用FOR循环统计并输出各个部门的平均工资。
代码1:
DECLARE
CURSOR c_dept_stat
IS
SELECT deptno,avg(sal) as avgsal
FROM emp
GROUP BY deptno;
BEGIN
FOR v_dept IN c_dept_stat
LOOP
DBMS_OUTPUT.PUT_LINE(v_dept.deptno||' '||v_dept.avgsal);
END LOOP;
END;
代码2:优化版
给变量赋初始值由于用FOR循环检索游标时,游标的打开、数据的检索、是否检索到数据的判断以及游标的关闭都是自动进行的,因此,可以不在声明部分定义游标,而在FOR语句中直接使用子查询。
BEGIN
FOR v_dept IN (SELECT deptno,avg(sal) as avgsal FROM emp GROUP BY deptno)
LOOP
DBMS_OUTPUT.PUT_LINE(v_dept.deptno||' '||v_dept.avgsal);
END LOOP;
END;
五、利用游标更新或删除数据
更新或修改数据的语法:
UPDATE|DELETE…
WHERE CURRENT OF cursor_name
注意:如果游标定义时没有使用FOR UPDATE子句,则不能利用该游标修改或删除数据库中的数据。
例:修改员工的工资,如果员工的部门号为10,则工资提高100;如果部门号为20,则工资提高150;如果部门号为30,则工资提高200;否则工资提高250。
DECLARE
CURSOR c_emp IS SELECT * FROM emp FOR UPDATE;
v_increment NUMBER;
BEGIN
FOR v_emp IN c_emp
LOOP
CASE v_emp.deptno
WHEN 10 THEN v_increment:=100;
WHEN 20 THEN v_increment:=150;
WHEN 30 THEN v_increment:=200;
ELSE v_increment:=250;
END CASE;
UPDATE emp SET sal=sal+v_increment WHERE CURRENT OF c_emp;
END LOOP;
COMMIT;
END;