数据库的分类
按照项目的规模分类
- 小型数据库 –负载在百十来号人,成本在1000以内,安全性要求不高。ep留言本、信息发布系统
- access foxbase
- 中型数据库 –负载在5000到15000左右,成本在万元以内,安全性要求均等。ep比如商务网站
- mysql
- sqlserver
- informix
- 大型数据库 –凡在为海量T级别,成本高,联通电信移动,安全性高
- sybase
- oracle
- db2(IBM)
oracle的卸载
停止Oracle所有服务
运行oracle的universal installer卸载oracle
运行regedit,进入注册表,删除时小心别删错
oracle软件有关键值:
HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE
oracle服务:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControSet\Services下以oracle开头的键值
oracle事件日志:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControSet\Services\Eventlog\Application
删除Oracle系统目录C:\program files\oracle
删除oracle环境变量
删除程序菜单中的oracle菜单
重启计算机,然后删除硬盘上的oracle目录,如果该目录不让删除,把这个目录改成别的名字,重启计算机再删除
删除在program files下的oracle目录
oracle的安装
默认生成sys用户和system用户:
1.sys用户是超级用户,具有最高权限,具有sysdba角色,有create database的权限,默认密码是manager
2.system用户是管理操作员,权限也很大,有sysoper角色,没有create database的权限,默认密码是change_on_install
3.一般来讲,对数据库维护,使用system用户登陆就可以了
oracle安装完成后有两部分:
C/S体系结构:
|客户端部分
| sqlplus(oracle提供,对数据进行操作管理的一个client软件,可执行sqlplus和sql命令)
| 进入:
| 使用:查看和当前用户相关的表(sql命令)
| sql>select table_name from user_tables;
| 查看一个表的表结构(sqlplus命令)
| sql>desc emp;
| 退出
| sql>exit;
| iSqlPlus:
| (oracle提供,基于浏览器,对数据进行操作管理的一个client软件,可执行sqlplus和sql命令)
| 进入:http://localhost:8080/apex
|
|服务器部分
| oracleServiceXE(核心服务)、oracleXETNSListener(提供对外支持)
sql相关概念
SQL: (Structure Query Language) 结构化的查询语言,对数据库中的数据进行增、删、改、查等操作。适用于所有的RDBMS.
PL-SQL: 是在SQL命令基础上进行了功能扩展,只能用在oracle.
sqlPlus:oracle提供,用于数据进行操作管理的一个client软件,可执行sqlplus命令和sql命令.
SQL分类:
DQL:data query language 数据查询语言 (select) 【重点】
DDL:data Defination Language 数据定义语言 (create\alter\drop)
DML:data manipulate language 数据操纵语言 (insert\update\delete) 【重点】
DCL:data controller language 数据控制语言 (grant\revoke)
TCL:transaction controller language 事务控制语言 (commit\rollback)
oracle管理工具
- oracle自带的工具软件,主要用于执行sql语句,p1\sql块
- 第一种方式:在开始->程序->oracle orachome90->application developmentp->–(sql*plus)//
- 第二种方式:在”运行栏”输入:–(sqlplusw)即可
- 第三种方式:在开始->程序->oracle orachome90->application developmentp->–(sql*plus worksheet)
- sqlplus dos下操作oracle的工具,其功能和sqlplus功能类似,在”运行栏”输入–sqlplus,–也可在cmd中输入sqlplus//
- oracle的企业管理器(oem oracle enterprise manager)
- 开始->程序->oracle->oracle oraclehome90->enterprise manager console即可启动oracle的企业管理器是一个图形界面环境
- 第三方软件:p1/sql develop,主要用于开发测试优化oracle p1/sql的存储过程,比如触发器,需要单独安装 –plsqldev//
sqlplus常用命令
0.备份的导入导出(需要在dos命令窗口下操作)
exp:导出(导出路径为当前路径,文件名为EXPDAT.DMP)
imp:导入(先进入到文件所在当前目录下执行)
1.清屏:
方法一:同时按SHIFT和DELETE键然后点OK就可以了 。
方法二:如果在window窗口下sqlplus 中清屏命令:host cls 或是clear screen 或只是4位 clea scre。
方法三:如果是在dos的窗口下进入sql/plus就要用clear SCR。
2.连接命令:
启动:
>>lsnrctl start (可填监听的名字,不写的话启动默认的监听)--启动监听
>>oradim -starup -sid orcl --启动oracle实例
连接和断开等:
conn(或connect) 用户名/密码@网络服务名 [as sysdba/sysoper] --当用特权名登录连接时 conn sys as sysdba
例如:conn system/"密码" --显示已连接,用户已然修改成为system
disc --该命令用于断开数据库的连接
passw --该命令用于修改用户的密码,如要修改其他用户的密码,需要用sys/systemdeng登陆
show user --显示当前用户
exit --断开于数据库的连接,同时退出sql*plus
3.文件操作命令:
start或@ --运行脚本
--ep: sql>@d:\a.sql 或者 sql>START d:\a.sql
edit --编辑指定的sql脚本
--ep: sql>edit d:\a.sql
spool --该命令可以将sql*plus屏幕上的内容输出到指定文件中去
--ep: sql>spool d:\bb.txt
-- sql>select * from emp; --注意带分号表示要执行语句
-- sql>spool off
-- 上述文件执行完毕后在d:盘目录新建了bb.txt并且屏幕上刚出现的内容被输出到bb.txt
select --查询
--sql> select * from emp; //无条件查询
--sql> select * from emp where ename='SMITH'; //有条件查询
--sql> select * from emp where ename='&name'; sql>输入 name 的值: SMITH //等价于上述
--如何知道比如scott用户可以操作哪些表?
--建议用plsqldev来看(登陆scott用户,在tables中看)
4.显示和设置环境变量
可以用来控制输出的格式,set show 如果希望永久保存相关的设置,可以去修改glogin.sql脚本
linesize --设置显示行的宽度,默认是80个字符
--sql>show linesize
--sql>set linesie 90
pagesize --设置每一页显示的行数目,默认是14,
--sql>show pagesize
--sql>set pagesize
5.创建和删除用户以及权限的维护
在sys或system中创建用户:--sql>create user kingly identified m123 //用户kingly,密码m123
改密码方式一:--sql>password 用户名 //或者 passw//
改密码方式二:--用dba的权限用户或有alter权限的用户给别人修改密码:--sql>alter 用户名 identified by 新密码
删除用户:一般以dba的身份去删除某个用户,若用其他用户去删除则需要有drop user的权限(不能自己删自己!)
--drop user 用户名 【cascade】 --级联删除
创建的新用户是没有任何权限的,甚至连登陆数据库的权限都没有,需要为其指定权限。
>>给一个用户赋权限使用grant; >>回收用户权限使用命令revoke
--ep: grant create table to zhangsan --把创建表的权利给zhangsan
--ep: grant unlimited tablespace to zhangsan --创建不受限的表空间的权利给zhangsan
--ep: revoke create table from zhangsan; --将zhangsan创建一张表的权限撤销掉
--ep: revoke unlimited from zhangsan; --将zhangsan不受限空间的权限撤销
权限|——系统权限:140多种,用户对数据库的相关权限 ep:create session(登陆数据库的权限)
|——对象权限:关键的有20多种,用户对其他用户的数据对象
(表、视图、函数、过程、包、类型、触发器、工作、库、序列、同义词、表空间、簇……)操作的权限
主要有:select
insert
update
delete
all
create index……
角色(权限的批量授权,ep现实生活中一个人当了"省长"这个角色,他就拥有了"省长"的一系列权限)
|——预定义角色
ep: connect角色(有7种权限)
resource角色(这个角色可让授权的用户在任何表空间建表)
dba角色(管理员)
|——自定义角色
希望xiaoming(connect角色)这个用户可以在system表空间中建表:
--希望xiaoming(connect角色)这个用户可以在system表空间中建表 (普通用户对数据库的相关权限)
--(在system用户中授权给xiaoming)sql>grant resource to xiaoming;
--(在xiaoming用户中建表)sql>create table test(userId varchar2(30), userName varchar2(30));
--(查询表)sql>select * from test;
--(查看表的结构)sql>desc test; //(description)
希望xiaoming(connect角色)这个用户可以查询scott的emp表:
--希望xiaoming(connect角色)这个用户可以查询scott的emp表 (普通用户的对象权限)
--(在sys或system或scott中授权)--sql>grant select on scott.emp to xiaoming;
--sql>grant select on emp to xiaoming;
--(在xiaoming用户中查询scott(方案)的emp表)sql>select * from scott.emp;
--希望xiaoming(connect角色)这个用户可以修改scott的emp表 (普通用户的对象权限)
--(在sys或system或scott中授权)--sql>grant update on scott.emp to xiaoming;
--sql>grant update on emp to xiaoming;
--(在xiaoming用户中修改scott(方案)的emp表)
希望xiaoming(connect角色)这个用户可以增加、删除、修改、查询scott的emp表
--希望xiaoming(connect角色)这个用户可以增加、删除、修改、查询scott的emp表 (普通用户的对象权限)
--(在sys或system或scott中授权)--sql>grant all on scott.emp to xiaoming;
--sql>grant all on emp to xiaoming;
希望收回小明对emp表的查询权限:
--希望收回小明对emp表的查询权限
--(在sys或system或scott中收回)--sql>revoke select on scott.emp from xiaoming;
--sql>revoke select on emp from xiaoming;
希望xiaoming这个用户可以查询scott的emp表,还希望xiaoming可以把这个权限给别人: ***with grant option
--希望xiaoming这个用户可以查询scott的emp表,还希望xiaoming可以把这个权限给别人
--(在sys或system或scott中授权)--sql>grant select on scott.emp to xiaoming with grant option;
--sql>grant select on emp to xiaoming with grant option;
希望xiaoming这个用户可以有connect这个角色(系统权限),还希望xiaoming可以把这个权限给别人:***with admin option
--(在sys或system或scott中授权)--sql>grant connect to xiaoming with admin option;
【注】:系统回收xiaoming的权限,将会影响xiaoming授予其他用户的相应权限。
ep:部长(系统用户)封了个省长(普通用户),省长又封了许多县长(普通用户),
撤掉省长之后,也会株连下面诸多县长的相应权限。 (一人得道,鸡犬升天; 一人受株,全家株连)
6.使用profile管理用户口令:
概述:profile是口令限制,资源限制的命令集合,当建立数据库时,oracle会自动建立名为default的profile,当建立
用户没有指定profile选项,那么oracle就会将default分配给用户。
账户锁定:指定该账户(用户)登录时最多输入密码的次数,也可以指定用户锁定的时间(天)。
一般用dba的身份去执行该命令。
--ep: 指定scott这个用户最多只能尝试登陆3次,锁定的时间为2天。
--//首先创建profile文件
--sql>create profile dog(配置名) limit failed_login_attempts 3 password_lock_2;
--//指定xiaoming账户用这个配置文件
--sql>alter user xiaoming profile dog;
给账户解锁: (给管理员打电话吧)--sql>alter user xiaoming account unlock;
强制定期修改密码(一般是管理员才做这种事):
--ep:给前面创建的用户xiaoming创建一个profile文件,要求用户每隔10天修改自家的登录密码,宽限为2天。
--sql>create profile dog limit password_life_time 10 password_grace_time 2;
--sql>alter user xiaoming profile dog;
解锁:--sql>alter user xiaoming account unlock;
修改密码时不能使用重用密码:
--ep:
--sql>create profile password dog limit password_life_time 10 password_grace_time 2
--proword_reuse_time 10 (10天后才可重用密码)
--sql>alter user xiaoming profile dog;
解锁:--sql>alter user xiaoming account unlock;
删除profile:--sql>drop profile dog 【cascade】;
表查询
表名和列名的命名规则
- 必须以字母开头
- 只能用如下字符:A-Z a-z 0-9 $ # 等
- 不能使用oracle的保留字
- 长度不能超过30个字符
oracle支持的数据类型
字符型
- char,定长,最大2000字符,查询极快,浪费空间 –char(10) ‘小张’ //前四个字符放’小张’,后添6个空格补全
- varchar2,变长,最大4000字符,查询稍慢,节省空间 –varchar(20) ‘小张’//oracle分配4个字符存放’小张’
- clob,字符型大对象,最大4G, 存放txt文件
数字型:
- number,范围 -10^38~10^38 可表示整数,也可以表示小数(10^-38)
- number(5,2,范围 -999.99~999.99 表示一个小数有5位有效数字,2位小数
- number(5),范围 -99999~99999 表示一个5位整数
number(5, 2) 整数位最多为3位,小数位2位(多余的小数位四舍五入) 如123.45 ok, 1234.5 error! 12.3456 ok number(5) 整数位最多为5位,无小数位 如12345、1、123 ok 123.4 error! number 默认小数类型,小数最多占7位,不含小数位的数字位数是38位
- 日期类型:
- date,包括年月日时分秒,精确到秒
- timestamp,对date数据类型的扩展,精确到毫秒
- 多媒体类型:
- blob,二进制数据,可以存放图片/声音 4G,通常的老套路是在一个普通文件夹中存放图片或声音,而在数据库中存放图片或声音的路径,如果要求保密性高的话,可以将声音或者图片存在数据库中
建表、删除表、修改表名
建表:
--学生表
sql>create table student( --表名
xh number(4), --学号
xm varchar2(20), --姓名
sex char(2), --性别
birthday date, --出生日期
sal number(7,2) --奖学金, -99999.99~99999.99 【注】最后没有逗号!
);
--显示表结构sql>disc student;
--【注】也可在图形界面工具中建表(table)
--班级表
sql>create table class(
classid number(2),
ename varchar2(40)
);
删除表:
drop table student;
修改表名:
rename student to stu;
添加、删除、修改一个字段
--增加一个字段:
alter table student add (classid number(2));
--删除一个字段:
alter table student drop column sal;
--修改字段的长度:
alter table student modify(xm varchar2(30));
--修改字段的类型(不能有数据,危险!)
alter table student modify(xm char(30));
--修改字段名
alter table student rename column xm to name;
插入字段内容
--插入所有字段(列):
insert into student values(1, '张三', '男', '27-5月-90', 10); --1990年5月27日, '月'字必须带!
--oracle中默认的日期格式'DD-MM-YY',修改日期的格式命令如下:
--alter session set nls_date_format = 'yyyy-mm-dd'; //修改后就可以用我们熟悉的格式添加日期类型
insert into student values(1, '张三', '男', '1990-05-27', 10);
--插入部分字段(列):
insert into student(xh, xm, sex) values(1, '张三', '男'); --不一定成功,某些字段必须要赋值
--插入空值:
insert into student(xh, xm, sex, birthday) values(4, '王五', '男', null);
--【注】查询空值:select * from student where birthday is null;
--查询非空的值: select * from student where birthday is not null;
删除数据内容
delete from student; --删除所有记录,写日志,可恢复,速度慢
--sql>savepoint aa; //设置保存点aa
--sql>rollback to aa; //回滚到保存点状态,中间的活白干!
truncate table student; --删除表中所有的记录,表结构还在,不写日志,无法找回删除的记录,速度极快!
drop table student; --删除表的结构和数据
delete from student where xh=1; --删除一条记录
--delete
--语法:delete from 表名 [where 过滤条件]
sql> delete from students where stuid=1;
sql> delete from clazz where clazz=2; --error!(原因:从表中有相关数据)
--解决方案:
--方案一:先删除该班的学生,再删除该班级
--方案二:先把该班的学生转到其他班,再删除该班级
--方案三:先去掉外键约束,再删除班级
--【注】在删除数据时,如果删除的是主表(如:班级)中的数据,必须要考虑是否删除后会导致从表中
--(如学生表)的数据会不会丢失引用关系
--开发中常用删除主表通常是逻辑删除,实际上数据还是物理存在的:
create table student(
stuid number(4) constraint PK_id primary key, --PK_id为约束别名
name varchar2(20) [constraint 约束名] not null,
deleteflog number(1) default 0 check(deleteflog in(0, 1)) --逻辑删除标志
);
修改字段内容
update student set sex='女' where xh=1; --修改单个字段
update student set sex='女', birthday='27-5月-90' where xh=1; --修改多个字段
update student set sex='女' where birthday is null; --修改含有空值
update student set sal=sal/2 where sex='男';--把所有男同志的薪水统统减一半
约束相关操作
主键约束:primary key
作用:唯一标识表中的一行数据,如工号、学号……
特点:唯一、非空
外键约束:foreign key
语法:references 主表名(pk字段名) --主表(如班级)、从表(如学生)
作用:标识从表中的外键字段的值,必须引用主表中主键字段pk(唯一键(约束))已存在的值--只有俩班级
如员工所在部门编号、学生所在班级编号
特点:允许为空、允许重复
唯一约束:unique
作用:标识该列的值,不允许重复。如邮箱、银行卡号、身份证号……
特点:唯一、可以为空
非空约束:not null
作用:标识该列的值必须有内容,不允许是null。如姓名、……
特点:可重复、非空
检查约束(自定义约束):check(约束表达式)
作用:标识该列的值必须符合用户的自定义表达式要求。如手机号必须是11位……
check(length(phone_number)=11)
check(sex in('男', '女'))
check(email like '%@%')
给约束指定名字(创建表时):
create table student(
stuid number(4) constraint PK_id primary key, --PK_id为约束别名
name varchar2(20) [constraint 约束名] not null,
deleteflog number(1) default 0 check(deleteflog in(0, 1)) --逻辑删除标志
)
查看约束:
select constraint_name from user_constraints; --显示当前用户中的约束
select constraint_name from user_constraints where table_name='SHOP_ORDER';--显示特定表的约束
删除约束:
alter table 表名 add 约束类型(lie1 lie2)
alter table 表名 drop constraint 约束名
序列相关操作
用于自动生成一组有顺序的数字。
创建:create sequence 序列名; --默认从1开始,每次递增1
create sequence 序列名 start with n; --从n开始,递增1
create sequence 序列名 start with n increment by m; --从n开始,递增m
create sequence student_seq start with 4;
删除:drop sequence 序列名
使用:序列名.nextval --获取序列中的下一个有效值
insert into students values(student_seq.nextval, '小强', '男', '1234567812232')
获取序列当前的值
select seq_students.currval from dual --注意该命令至少要在调用nextval一次后再能用
查看和当前用户相关的序列和表
select sequence_name from uer_sequences
注意:1.序列中的值被所有的表共用
2.序列值一旦产生,则不能重新获取
视图相关操作:
起了查询名称的查询语句。
创建:create view 视图名 as select……
如create view view_stud as select * from student;
使用:select 列名1,列名2 from 视图名
如select * from view_stud;
select sequence_name from uer_sequences
select table_name from user_tables
select constraint_name from user_constraints; --显示当前用户中的约束
select constraint_name from user_constraints where table_name='SHOP_ORDER';--显示特定表的约束
注意:1试图只是给SQL起了个别名,简化SQL。
2不能提高查询效率。
3通过视图查询出的数据不单独占存储空间。
4通过视图,可以进行增删改操作,不建议使用,限制非常多。
删除:drop view 视图名
索引相关操作
类似书前面的目录(字典目录)
创建:create index 索引名 on 表名(列名)
如create index index_student on student(name);
使用:在查询时,只要使用创建了索引的列进行查询,oracle会自动使用索引
注意:1索引能提高查询效率,但不是创建的越多越好(占空间、增删改操作时需要维护索引)
2创建索引的原则:大数据表中查询小部分数据、在经常查询的列上创建索引
3主键和唯一键oracle自动创建索引
删除:drop index 索引名
查询表
(这是数据库部分最重要的部分)
查询语句的执行顺序
sql语句的执行顺序:
sql语法顺序:select……from……where……group by……order by……
sql语句执行顺序:
1.from 确定原始表和原始数据
2.where 对原始表中的数据进行过滤,符合条件则留下
3.group by 对符合条件的数据分组
4.having 对分组后的结果进行过滤,符合条件则留下
5.select 对符合条件的数据,根据select进行计算结果
6.order by 对结果排序
基本
1.查询表的结构:
sql>desc dept;
2.查询所有列:
sql>select * from dept; --切记查询尽量不要使用*,速度会很慢
--【注】:sql>set timing on; //打开"显示操作时间的开关" //off为关闭
3.查询指定列:
sql>select ename, sal, job, depatno from emp;
4.查询(取消重复行):
sql>select deptno, job from emp; --这样查询的结果会有很多重复行
sql>select distinct deptno, job from emp; --查询(没有重复的记录)
5.查询SMITH所在的部门、工作、薪水
sql>select deptno, job, sal from emp where ename='SMITH';
6.查询使用算数表达式:
查询显示每位员工的年工资(不包括emp表中的comm奖金):
sql>select ename, sal*12 "年工资" from emp; --""中的内容为sal*12字段的别名,注意为双引号!
--【注】别名除了显示之用外,只能在order by中使用!
查询显示每位员工的年工资(包括emp表中的comm奖金):
sql>select ename, sal*12+comm*12 "年工资" from emp;
--可是我们发现这样查询出来的有的员工的工资为空,oracle中表达式中有一个值为空,计算表达是就是null
sql>select ename, sal*12+nvl(comm, 0)*13 "年工资" from emp;--OK
--nvl(comm, 0) 函数,表示若comm为空则用0替代,若comm不为空则用其本身的值来替代nvl(comm, 0)
7.连接字符串(||):
sql>select ename || 'is a' || job "哈哈" from emp; --"哈哈"为 ename || 'is a' || job 字段的别名
8.查找显示工资高于3000的员工姓名:
sql>select ename, sal from emp where sal>3000;
查找1982.1.1以后入职的员工:
sql>select ename, hiredate from emp where hiredate>'1-1月-1982';
查找显示工资在2000~2500的员工:
sql>select ename, sal from emp where sal>2000 and sal<2500; --"与"用and,"或"用 or
9.like操作符:
% 表示任意0到多个字符
_ 表示任意单个字符
查询显示首字符为S的员工姓名和工资:
sql>select ename, sal from emp where name leike 'S%';
查询显示第三个字符为大写O的所有员工的姓名和工资:
sql>select ename, sal from emp where ename linke '__O%';
10.where条件中使用in
查询显示empno为123,345,800……的雇员的情况:
sql>select * from emp where empno=123 or empno=345 or empno=800; --速度慢!
sql>select * from emp where empno in(7521, 7876, 7782); --速度快!
11.使用is null的操作符:
查询显示没有上级的雇员的情况:
sql>select * from emp where mgr is null;
12.使用逻辑操作符号:
查询工资高于500或是员工岗位为MANAGER的雇员,同时还要满足他们的姓名首字母是大写的J:
sql>select * from emp where (sal>500 or job='MANAGER') and ename like 'J%';
13.使用order by 字句:
按照工资从低到高的顺序显示雇员的信息:
sql>select * from emp order by sal [asc]; --asc写不写无所谓
按照工资从高到低的顺序显示雇员的信息:
sql>select * from emp order by sal desc;
按照部门号升序、而雇员的工资降序的顺序显示信息:
sql>select * from emp order by deptno, sal desc; --注意deptno和sal的顺序不要搞错!
按照部门号升序、而雇员的入职时间降序的顺序显示信息:
sql>select * from emp order by deptno, hiredate desc;
使用字段(列)的别名排序: ep:按照年薪降序排序
sql>select ename, sal*12+nvl(comm, 0)*12 [as] "年薪" from emp order by "年薪" desc; --as可写可不写
14.case-end语句
case
when(条件1) then 语句1
when(条件2) then 语句2
else 语句N
end
--查询显示工号、姓、工资、工资级别(>20000 A, 10000-20000 B, <10000 C)
select employee_id, last_name, salary,
case
when (salary > 20000) then 'A'
when (salary between 10000 and 20000) then 'B' --注意不加 ;
else 'C'
end as "级别", department_id
from employees;
伪列
在表中字段中没有,但是实际上存在的列
rowid:唯一标识表中的一行数据,根据数据在硬盘上的实际存储地址计算得到
比主键的查询效率高,索引的底层实现就是通过rowid实现的
rownum: 对查询结果(*自动)编号,符合条件的第一条数据编号1,再依次排序编号
主要用在分页中:
select * from emeployees where rownum<=10;
--【注意】rownum 只能进行<、 <= 、=1和>=1 运算
-- 如果想用rownum进行>运算,可以给rownum起个别名rn,那么rn就变成了普通列,就可以进行>运算了。
表别名:
--select *, rownum from employees; --Error!
解决方案:给表起别名。
--【注】表别名定义时,前面不能加 as
select ee.*, rownum from employees ee --OK!
子查询
子查询的概念:
select语句中有嵌套select语句,外面select称为主查询,里层select称为子查询
1.若子查询的结果是一个值,直接代入主查询参与运算
查询具有最高工资的员工
select last_name||' '||first_name from employees where salary=(select max(salary) from employees);
查询工资比平均工资高的员工
select last_name||' '||first_name from employees where salary>(select avg(salary) from employees);
查询各部门具有本部门最高工资的员工(自连接或多表查询)
--方法一:
select * from employees e where salary=(select max(salary) from employees where department_id=e.department_id group by department_id); --后面的group by也可以不写
--方法二:
select ee.* from employees ee, (select department_id, max(salary) maxS from employees group by department_id) ss where ee.department_id=ss.department_id and ee.salary=ss.maxS;
2.若子查询的结果是多个值(N行1列):把子查询的结果当成集合列表直接参与集合运算符in运算
查询和姓King的员工同部门的人
select * from employees where department_id in(select department_id from employees
where last_name='King');
3.子查询的结果是虚表(N行N列):
查工资排前五名的员工
select * from (select * from employees order by salary desc) where rownum<=5;
查询工资排名在第6名到第10名的员工
select * from (select ee.*, rownum rn from (select ename, sal from emp order by sal) ee
where rownum<=10) where rn>=6;
复杂查询
在实际的应用中经常需要执行复杂的数据统计,经常需要显示多张表的数据,下面介绍较为复杂的select语句。
1.数据分组-max, min, avg, sum, count
查询显示共有多少个员工:
sql>select count(*) from emp;
查询显示所有员工中最高和最低工资:
sql>select max(sal), min(sal) from emp; --字段(列)中有分组函数,其他字段中必须为分组函数!
查询显示所有员工中最高工资及其对应的员工:
sql>select ename, sal from emp where sal=(select max(sal) from emp); --用到子查询
--sql>select ename, sal from emp where sal=max(sal); //Error!此处不允许用分组函数!
查询显示工资高于平均工资的员工的信息:
sql>select * from emp where sal>(select avg(sal) from emp);
把那些低于平均工资而且入职时间在1980年12月18日以前的人的工资加100:
sql>update emp set sal=sal-100 where sal<(select avg(sal) from emp) and hiredate<'18-12月-1980';
2.group by 和 having 子句
查询和显示每个部门的平均工资和最高工资
sql>select avg(sal), max(sal), deptno from emp group by deptno; --【注】被分组字段一定要出现!
查询和显示每个部门的每个岗位的平均工资和最高工资
sql>select avg(sal), max(sal), deptno, job from emp group by deptno, job order by deptno;
查询和显示平均工资低于2000的部门号和他平均工资
sql>select avg(sal), max(sal), deptno from emp group by deptno having avg(sal)>2000;
sql>select avg(sal), max(sal), deptno from emp group by deptno having avg(sal)>2000
order by avg(sal) desc;
【小结】:
a.分组函数只能出现在选择列表、having、order by 字句中;
b.如果在select语句中同时包含group by、having、order by,那么他们的顺序是group by、having、order by
c.在选择列中如果有列、表达式、分组函数,那么这些列和表达式必须有一个出现在group by字句中,否则出错!
3.多表查询:
多表查询是指基于两个和两个以上的表或视图的查询。在实际的应用中,查询单个表可能不能满足需求(如显示
sales部门位置和其员工的姓名),这个时候需要使用到dept表和emp表。
查询显示雇员名、雇员工资及其所在部门的名字【笛卡尔集】:--套路:最后面的子句是为了排除无效的笛卡尔集
sql>select ee.ename, ee.sal, dd.dname from emp ee, dept dd where ee.deptno=dd.deptno;
--【注】两张表至少需要1个约束条件
--【注】三张表至少需要2个约束条件
--【注】四张表至少需要3个约束条件
--………………
查询显示部门编号为10的部门名、员工名和工资:
sql>select dd.dname, ee.ename, ee.sal from dept dd, emp ee where dd.deptno=ee.deptno
and dd.deptno=10;
查询显示员工的姓名、工资及其工资的级别:
sql>select ee.ename, ee.sal, ss.grade from emp ee, salgrade ss
where ee.sal between ss.losal and ss.hisal;
查询显示雇员名、雇员工资及其所在部门的名字,并按照部门编号排序
sql>select ee.ename, ee.sal, dd.dname from emp ee, dept dd
where ee.deptno=dd.deptno order by ee.deptno;
4.自连接:
指的是同一张表的连接查询
显示某个员工(ep:FORD)的上级领导的姓名:
sql>select worker.ename, boss.ename from emp worker, emp boss
where worker.empno=boss.empno and worker.ename='FORD';
5.子查询:
子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询。
单行子查询:只返回一行数据的子查询语句
查询显示与SMITH同一部门的所有员工
sql>select ename, deptno from emp where deptno=(select deptno
from emp where ename='SMITH'); --数据库执行sql语句是从左到右
--【注】:在实际中最好能将筛选能力强的语句写在最左边,会大大增加执行速度!
多行子查询:返回多行数据的子查询
查询显示和部门10中的工作相同的雇员的名字、岗位、工资、部门号
sql>select * from emp where job in(select job from emp where deptno=10);
查询和显示工资比部门30的所有员工的工资都高的员工的姓名、工资和部门编号
sql>select ename, sal, deptno from emp where sal>all(select sal from emp where
deptno=30);--方法一,效率低
sql>select ename, sal, deptno from emp where sal>(select max(sal) from emp where
deptno=30);--方法二,效率高,尽可能使用函数解决问题!
在多行子查询中使用any操作符:
查询显示工资比30号部门的任意的一个员工的工资高的员工的姓名、工资和部门号
sql>select ename, sal, deptno from emp
where sal>any(select sal from emp where deptno=30); --方法一
sql>select ename, sal, deptno from emp
where sal>(select min(sal) from emp where deptno=30); --方法二
--【注】只要比30号部门的随便一个员工的工资高就可以,即比其中最低工资高就行
-- 注意与all的区别,all指的是比每一个都怎么怎么样,any是比其中一个怎么怎么样
多列子查询:
查询返回多个列数据的子查询语句
查询显示与SMITH的部门和岗位完全相同的所有雇员
sql>select * from emp
where deptno=(select deptno from emp where ename='SMITH')
and job=(select job from emp where ename='SMITH'); --方法一
sql>select * from emp
where (deptno, job)=(select deptno, job from emp
where ename='SMITH'); --优化方法二
在from子句中使用子查询
显示高于自己部门的平均工资的员工的信息:
sql> select * from emp ee,
(select deptno, avg(sal) avgsal from emp group by deptno) ss
where ee.deptno=ss.deptno
and ee.sal>ss.avgsal order by ee.deptno;
--第一步:查询出各个部门的平均工资和部门编号,得到一张子表ss
--第二步:利用多表查询(ee, ss),查询得到正确结果。
【注】:当在from子句中使用子查询时,该子查询会被作为一个视图来对待,因此称作
内嵌视图,在from子句中使用子查询时,必须给子查询指定别名。
【注】:列取别名客加as,表取别名不加as!
使用子查询插入数据
当使用values子句时,一次只能插入一行数据,而使用子查询插入数据可以做到一条insert语句可插入大量的数据。当处理行迁移或者装载外部表的数据到数据库时,可以使用子查询来插入数据--先创建一张新表
sql>create table kkk (myid number(4), myname varchar2(50), mydeptno number(5));
--再将emp表中的数据导入到新创建的表
sql>insert into kkk(myid, myname, mydeptno) select empno, ename, deptno from emp
where deptno=10;
使用子查询更新数据:
使用update语句更新数据时,既可以使用表达式或者数值直接修改数据,也可以使用子查询修改数据。
更新员工SCOTT的岗位、工资、补助与SMITH员工一样
sql>update emp set (job, sal, comm)=(select job, sal, comm from emp
where ename='SMITH') where ename='SCOTT';
分页查询
oracel分页一共有三种方式:
1.rownum分页: --70000条数据0.1秒(常用)
第一步:rownum分页,将ee当做一个内嵌视图
select ee.*, rownum rn from (select * from emp) ee;
第二步:二分机制来实现取指定的行(记录)出来--ep:取出6-10行记录
select * from (select ee.*, rownum rn from (select * from emp) ee
where rownum<=10) where rn>=6;
--【注】rownum一次只能用一下!并且rownum<=和别名rn>=的顺序不能颠倒!
第三步:指定字段、排序等所有改动都只需要改最里层select就可以了!
select * from (select ee.*, rownum rn from (select ename, sal from emp order by sal) ee
where rownum<=10) where rn>=6;
select * from (select ee.*, rownum rn from (select avg(sal) from emp group by deptno) ee
where rownum<=2) where rn>=1;
2.rowid分页: --70000条数据0.03秒
select * from t_xiaoxi where rowid in
(select rid from
(select rownum rn, rid, from
(select rowid rid, cid from t_xiaoxi
order by cid desc)
where rownum<10000)
where rn>9980)
order by cid desc;
3.分析函数分页: --70000条记录1.01秒
select * from
(select t.*, row_number()
over(order by cid desc) rk
from t_xiaoxi t)
where rk<10000 and rk>9980;
表连接【开发中的重点】
概念:需要查询的内容来自于多张表,此时需要把多张表合成到一张表,称为表连接。
合并后的大表表结构(列):2个表的字段之和
数据行数:取决于表连接的类型
语法:select ???
rom 表名1
join 表名2
on 连接条件
where……group by……having……order by……
类型:内连接、外连接、交叉连接、自连接
具体想用哪种连接,具体情况具体分析
1.内连接([inner] join)
特点:1.内连接的结果——符合(连接)条件的数据
2.必须要有连接条件
3.两个表没有顺序要求
--【注意】表连接后的大表中,若存在同名字段,必须使用表名或是表的别名加以区分
查询员工的工号、姓、工资、所在部门编号(106条)
select employee_id, last_name, employees.department_id
from employees --可加别名
join departments --可加别名
on employees.department_id=departments.department_id --连接条件
--【注】查不到老板107,他没有部门编号
2.外连接(左外连接left[outer] join、右外连接right[outer] join、全部连接full[outer] join) --优先左外
左外连接的特点:
1.左外的结果——符合条件的数据+左表中不符合条件的数据
2.必须要有连接条件
3.两个表没有顺序要求,以左表为主!
4.左表中不符合条件的数据,想显示右表中字段值时,用null填充
查询员工的工号、姓、工资、所在部门编号(107条)
select employee_id, last_name, employees.department_id
from employees --可加别名
left join departments --可加别名
on employees.department_id=departments.department_id --连接条件
--【注】查到了老板107,他虽然没有部门编号
--【注】右外、全部外连接与左外类似
全部连接的特点:
1.全部的结果——符合条件的数据+左表中不符合条件的数据+右表中不符合条件的数据
2.必须要有连接条件
3.两个表没有顺序要求
4.不存在的数据,显示另外一张表中字段值时,用null填充--
查询没有员工的部门
select d.*, e.*
from department d
left join employees e
on e.department_id=d.department_id
where e.employee_id is null;
3.多表连接
select……
from 表名1
join 表名2
on 连接条件1
join 表名3
on 连接条件2
……
4.交叉连接【了解】
笛卡尔集,交叉连接后的结果是:两个表的数据行数的乘积 ep:107*27
select *
from employees e
cross join departments d --效率低
select * from employees aa, departments bb where……
5.自连接
特殊的表连接,参与连接的两张表是同一张表
select * from employees aa left join employees bb on aa.manager_id=bb.employee_id;
用查询结果创建新表
这个命令是一种快捷的创建表的方式
sql>create table newemp(newempno, newname, newsal) as (select empno, ename, sal from emp);
合并查询(oracle特有的查询)
特点:速度快!比and、or等的效率快的多
有时候在实际的应用中,为了合并多个select语句的查询结果,
可以使用集合操作符union, union all, intersect, minus
1.union 取得两个结果集的并集(自动去掉结果集中的重复行,相当于集合中运算(A+B-AB))
--注union all 不会去掉结果集中的重复行,相当于A+B
sql>select ename, sal, job from emp where sal>2500
union select ename, sal, job from emp where job='MANAGER';
2.intersect 取得两个结果集的交集(相当于集合运算的AB)
sql>select ename, sal, job from emp where sal>2500
intersect select ename, sal, job from emp where job='MANAGER';
3.minus 取得两个结果集的差集(相当于集合运算的A-B)
sql>select ename, sal, job from emp where sal>2500
minus select ename, sal, job from emp where job='MANAGER';
数据库设计
1.什么样的数据库设计是好的?
1方便企业应用的调用(表的结构清晰、关系清晰)
2尽量减少数据冗余
3保证数据的正确性(数据完整性)
2.数据库的设计过程:
需求分析:针对用户的业务数据及处理流程 调研
概要设计:E-R图
详细设计:根据E-R,表结构
编码实现:java+jdbc
测试:……
3._E-R图:
实体关系图(entity relationship):~~~类似于类图
复杂性名词:对应实体的名称,如学生、电脑
简单性名称:对应实体的属性,如学生的姓名、学号……
实体和实体之间的关系:
1对1
1对N
N对N
4.根据E-R图,转换为表结构
1.先把实体转化为表
实体名---->表名
属性------>字段
主要属性-->主键字段
2.关系
【1对1】:如学生借电脑
student(sid-PK, name)
s1 zs
s2 ls
compute(cid-PK, ctype)
c1 hp
c2 dell
假设FK放在student表中,看行不行
student(sid-PK, name, computeid-FK)
s1 zs c1
s2 ls c1 --error (原因:站在需求角度,一台电脑只能借给一个学生)
--解决方案:在FK上添加unique约束
s2 ls c2 --OK
假设FK放在compute表中,看行不行
compute(cid-PK, ctype, stuid-FK)
c1 hp s1
c2 dell s1--error(原因:站在需求角度,一个学生只能借一台电脑)
--解决方案:在FK上添加unique约束
c2 dell s2 --OK
--【结论】:如果两个表的关系是1对1,外键可以在任意一方创建,并且同时给FK添加unique约束
--通常定义在相对更重要的一方!
【1对N】
实例:clazz(cid-PK, cname)
c1 java32班
c2 java33班
student(sid-PK, name)
s1 zs
s2 ls
假设,FK设在clazz中
clazz(cid-PK, cname, stuid-FK)
c1 java32 s1
c1 java32 s2 --error(原因:c1违反了PK约束)
--没有解决方案,假设不成立
假设,FK设在student中
student(sid-PK, name, clzid-FK)
s1 zs c1
s2 ls c1 --OK
--【结论】:如果两个表是1对N的关系,外键必须在N的一方创建外键约束
【N对N】
实例:
student(sid-PK, name)
s1 zs
s2 ls
course(cid-PK, ctype)
c1 java
c2 oracle
假设FK在student表中
student(stuid-PK, name, courseid-FK)
s1 zs c1
s1 zs c2 --error(原因:s1违反了PK约束)
假设FK在course表中
course(cid-PK, ctype, stuid-PK)
c1 java s1
c1 java s2 --error(原因:c1违反了PK约束)
--【结论】:如果两个表是N对N,必须引入第三张关系表
第三张关系表:
sc(sid-FK, cid-FK)
s1 c1
s1 c2
s2 c1
s2 c2
--【结论】:把N对N转换为1对N
5.范式理论
概念:数据库设计中可以遵循的一组规范,如果遵循了将会给设计人员提供型对较好的指导性意见。
优点:减少数据的冗余
缺点:导致表的数量增多,影响查询效率
1.【第一范式】:属性的原子性!
错误的方案:
学生表sid sanme slike
1 zs 打球、小说、游戏
2 ls 睡觉、吃饭、打豆豆
3 ww 音乐、电影、游戏
--需求:把兴趣爱好中"游戏"变成"编程",不好改,违反了第一范式!
解决方案:把存在费原子性的
sid slike
1 打球
2 小说
3 游戏
4 睡觉
5 吃饭
6 打豆豆
引入slike外键
sid sname slike
2.【第二范式】:属性不允许部分依赖于主属性!(字段不能依赖于主键的一部分)
学生表
sid sname cid cname score
s1 zs c1 java 90
s1 zs c2 oracle 89
s2 ls c2 oracle 99
PK:sid+cid
--需求:加一门新课
学生表
sid sname cid cname score
s1 zs c1 java 90
s1 zs c2 oracle 89 --数据冗余,但查询效率高
s2 ls c2 oracle 99
null null c3 test null --error(PK不能为空)
s3 ww null null null --error(PK不能为空)
PK:sid+cid
解决方案:把存在部分依赖的属性拆分出来,构成新表
sid sname --查询效率相对低
cid cname
sid cid score
3.【第三范式】:属性不允许传递依赖于主属性
学号表:
sid-PK sname clzid clzname ……
s1 zs 1 java32
s2 ls 1 java32
--需求:新建班
学号表:
sid-PK sname clzid clzname ……
s1 zs 1 java32
s2 ls 1 java32
null null 2 java34 --error(PK不能为null)
解决方案:把传递依赖的属性拆分出来构成新表
clzid-PK clzname
sid-PK sname clzid
jdbc (java database connector)
JDBC的发展
- java->odbc(open-)->DB (jdbc-odbc桥连接)–不能跨平台、效率低、依赖C语言!
- java->本地clientAPI->DB (本地客户端API连接) –本地用户
- java->jdbc->DB (直连)–接口OK,统一标准
- java->webserver->DB (连接池)–在服务器上做配置就可以
- oracle[sun]提供一堆jdbc接口规范,数据库厂商以jar包的形式提供接口的jdbc实现类(驱动)
包含的内容
接口-SUN公司提供jdk中 java.sql.* javax.sql.*
实现类-数据库厂商提供,在数据库厂商主页下载(ojdbc5.jar适用于jdk5.0,6.0|ojdbc6.jar 适用于 jdk7.0)
简单实用
//六个步骤:
//1.注册驱动类
//2.创建连接
//3.创建Statement
//4.执行SQL语句
//5.处理执行结果
//6.释放资源
import java.sql.*;
class Test {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//注册驱动类
Class.forName("oracle.jdbc.driver.OracleDriver");
//--[注]父包oracle.jdbc中也有OracleDriver类
//--第二种方式DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver);
//--第三种System.setProperty("jdbc.drivers", "oracle.jdbc.driver.OracleDriver");
//--不建议使用第二种,会产生同名垃圾注册
//--创建连接
//--url:协议:子协议……:@ip:port:sid 或者 协议:子协议……://ip:port/sid
//--本机ip:localhost 或 127.0.0.1
//--port:oracle默认端口号为1521
//--sid:(DB的唯一标识)在服务中可看到
//--【连接原则】:尽量晚建立,尽量早释放!
String url = "jdbc:orale:thin:@127.0.0.1:1521:orcl";
String username = "scott";
String password = "oracle";
Connection conn = DriverManager.getConnection(url, username, password);
//--创建Statement
Statement stm = conn.createStatement();
//--执行SQL语句
String sql1 = "update student set name='张三', age=23 where stuid=1";
int row = stm.executeUpdate(str);
//--执行insert/update/delete语句
//--有返回值,int,代表影响的行数
//--【注】存在第三方客户端对服务器数据库执行增删改操作后,需第三方客户端commit之后,才能用jdbc对数据库进行增删改操作
String sql2 = "select * from emp";
ResultSet rs = sm.executeQuery("select * from emp");
//--执行select语句,返回结果集(虚表)
while (rs.next()) { //--指针的默认位置在第一行数据的上方,返回boolean
String name = getString("name");
int age = getInt(2); //--getXXX的参数可重载,字段名或是字段在返回结果集中的标号
double score = getDouble(3);
}
//处理执行结果(只针对select)
//释放资源(先创建的后关闭)
if (stm!=null)
stm.close();
if (conn!=null)
conn.close();
}
}
/*
6.开发常见问题:
1)ClassNotFoundException: oracle.jdbc.OraclDriver
解决:检查是否正确导入ojdbc5.jar ; 检查驱动类名是否拼写正确
2)SQLException: IO 错误: The Network Adapter could not establish the connection
解决:检查ip和port ; 检查数据库服务是否启动,以及oracle监听器是否启动正常
3)SQLException: ORA-01017: invalid username/password; logon denied
解决:检查用户名和密码
4)SQLException: No suitable driver found for jdbc:orle:thin:@127.0.0.1:1521:xe
解决:检查协议是否正确
5)SQLException: 缺失逗号/引号/无效标示符/序列不存在/表和视图不存在.....
解决:检查sql命令
*/
事务处理
事务: 用于保证数据的一致性,它由一组相关的dml语句(数据操作语言,增删改语句)组成,
该组的dml语句要么全部成功,要么全部失败。
如网上转账就是典型的要用事务来处理的例子,可以保证数据的一致性。
事务和锁: 当执行事务操作时(dml语句),oracle会在被作用的表上加锁(看门狗),防止其他用户修改表的结构。
这点对用户来说是非常重要的。
提交事务: 执行commit语句可以提交事务。当执行了commit语句后,会确认事务的变化、结束事务、删除保存点、释放锁
当使用commit语句结束事务后,其他事务可以查看到事物变化后的新数据。
--【注】commit;语句执行后,提前做好的保存点(savepoint)统统都不存在了,现在所有事务全部生效。
--【注】exit;语句默认自动commit提交。
回退事务: 保存点(savepoint)是事务中的一点,用于取消部分事务,当结束事务时,会自动删除该事务所定义的所有保存
点。当执行rollback时,通过指定保存点可以回退到指定的点的状态。
--【注】事务的几个重要的动作:
--设置保存点:savepoint aa
--取消部分事务: rollback to aa;
--取消全部事务: rollback
在java程序中使用事务
//在java程序小左数据库时,为了保证数据的一致性,比如转账10$操作:
import java.sql.*;
class Test {
public static void main(String[] args) {
Connection ct = null;
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";
String username = "scott";
String password = "oracle";
ct = DriverManager.getConnection(url, username, password);
ct.setAutoCommit(false); //--加入事务处理,设置为不能默认提交
Statement sm = ct.createStatement();
//--从SCOTT的工资中减去100
sm.excuteUpdate("update emp set sal=sal-100 where ename='SCOTT'");
//--抛个异常
int i = 2/0;
//--给SMITH的工资加上100
sm.excuteUpdate("update emp set sal=sal+100 where ename='SMITH'");
ct.commit(); //--提交事务,从ct.setAutoCommit(false)到ct.commit()是一个事务整体,整体提交
//--关闭资源
sm.close();
ct.close();
} catch (Exception e) {
//--如果发生了异常,就回滚
try {
ct.rollback();
} catch (Exception ee) {
ee.printStackTrace();
}
e.printStackTrace();
}
}
}
只读事务:
只读事务是指只允许执行查询的动作,而不允许执行其他任何的dml操作的事务,使用只读事务可以确保用户只能取得某时间点的数据。
假定机票代售点每天18点开始统计今天的销售情况,这是可以使用只读事务。设置了只读事务后,尽管其他回话可能会提交新的事务,
但是只读事务将不会取得最新的数据的变化,从而可以保证特定时间点的数据信息。
设置只读事务:
set transaction read only
--设置了只读事务之后,该用户就看不到设置点之后发生的事务结果
oracle常用sql函数
【字符函数】:
字符函数式oracle中最常用的函数,常用的有下面的函数:
lower(char) --将字符串转化为小写的格式
upper(char) --将字符串转化为大写的格式
length(char) --返回字符串的长度
substr(char, offm, lengthn) --取子字符的子串
replace(char1, search_string, replace_string) --替换指定字符串
instr(字符串, 字符串) --取子串在字符串中的位置,不存在则返回0
concat(字符串1, 字符串2)--将1、2字符串连接成一个新的字符串
lpad(字段, 总的大小, 填充字符) --左填充(即右对齐)
rpad(字段, 总的大小, 填充字符) --右填充(即左对齐)
trim(一个字符 from 字符串) --去掉字符串首尾的字符
to_char() --将非字符串类型转化成字符串类型--对于日期型可以控制其格式to_char(日期, 格式)
将所有员工的名字按照小写的方式显示
sql>select lower(ename) from emp;
将所有员工的名字按照大写的方式显示
sql>select upper(ename) from emp;
显示正好为5个字符的员工的姓名
sql>select ename from length(ename)=5;
显示所有员工姓名的前三个字符
sql>select substr(ename, 1, 3) from emp;
以首字符大写的方式显示所有员工的姓名
sql>select (upper(substr(ename, 1, 1))||lower(substr(ename, 2, length(ename)-1)))
as "Name" from emp;
以首字符小写的方式显示所有员工的姓名
sql>select (lower(substr(ename, 1, 1))||upper(substr(ename, 2, length(ename)-1)))
as "Name" from emp;
显示所有员工的姓名,用"我是A"替换所有的"A"
sql>select replace(ename, 'A', '我是A') from emp;
查询显示'SM'在'SMITH'所在字段的索引
sql>select instr(ename, 'SM') from emp where ename='SMITH';
连接字符串
sql>select concat(ename, job) from emp;
左填充和右填充
sql>select lpad(sal, 10, '*') from emp;
sql>select rpad(sal, 10, '*') from emp;
去掉字符串首尾的字符串
sql>select trim('S' from ename) from emp;
【数学函数】:
常见的数学函数如下:--【注】在oracle中有一张虚拟的表(dual),一般用来做测试,没有实际含义
cos、sin、tan、acos、asin、atan、cosh、sinh、tanh
exp、sqrt、ln、abs
log(m, n)--以m为底n的对数
power(m, n)--m的n次方
ceil(m)、floor(n)--向上、向下取整
mod(m, n)--取m除以n的余数--sql>select mod(10, 3) from dual;
round(数字, 从第几位开始四舍五入)--远离0四舍五入, 若没有后面的参数(可正可负)则四舍五入到整数
trunc(数字, 从第几位开始截取)--若没有后面的参数(可正可负)则截取到整数
查询显示一个月为30天的情况下所有员工的日薪金,忽略忽略余数
sql>select floor(sal/30) from emp;
【日期函数】:
常见的日期函数如下:--【注】默认的日期格式是dd-mon-yy,如27-5月-90
*sysdate --返回oracle服务器系统时间,默认yy-mon-dd格式 如:sql>select sysdate from dual;
显示昨天这个时候的时期
sql>select sysdate-1 from dual;--sysdate默认的单位是天
*add_months(日期1, 8) --返回从日期1开始再加8个月的时间
显示上个月这个时期的时期
sql>select add_months(sysdate, -1) from dual;
显示上一年这个时期的时期
sql>select add_months(sysdate, -12) from dual;
*trunc(myDate, '日期格式字符串') --截断日期 yyyy mm dd hh mi ss day
sql>select trunc(sysdate, 'yyyy') from dual; --按年截断,结果是'01-1月'
sql>select trunc(sysdate, 'mm') from duan;
sql>select trunc(sysdate, 'day') from duan;
*last_day(myDate) --获取date日期的最后一天
显示一年是不是闰年(看看那一年的2月是28天还是29天)
sql>select last_day(add_months(trunc(sysdate, 'yyyy'), 1)) from dual;
*to_char(myDate, '日期格式字符串')
作用1:根据指定格式显示日期
select to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss day') from dual;
作用2:获取日期的不同部分
select to_char(sysdate, 'yyyy') from dual; --获取当前年
select * from employees where to_char(hire_date, 'yyyy')='1995';
select * from employees where to_char(sysdate, 'yyyy')= to_char(hire_date, 'yyyy');
select * from employees where to_char(sysdate, 'mm')= to_char(hire_date, 'mm');
select to_char(sysdate, 'day') from dual;
*to_date(myStr, '日期格式字符串')
将字符串按照指定的格式转换为日期类型
select to_char(to_date('2008-08-08', 'yyyy-mm-dd'), 'day') from dual;--显示奥运会是星期几
查找8个月多月以前入职的员工
sql>select * form emp where sysdate>add_months(hiredate, 300);
返回满10年服务年限的员工的姓名和受雇日期
sql>select * from emp where sysdate>=add_months(hiredate, 12*10);
查询显示每个员工加入公司的天数
sql>select floor(sysdate-hiredate) "入职天数" from emp;
sql>select trunc(sysdate-hiredate) "入职天数" from emp;
找出各月份倒数第三天受雇的员工
sql>select * from emp where last_day(hiredate)-2=hiredate;
打印本周的星期一时间信息
sql>select trunc(sysdate, 'day')+1 from dual;
【转换函数】:
*to_char(myDate, '日期格式字符串') --将日期类型转换为字符串
*to_char(salary, 'L99,999.99') --将工资显示货币单位--L表示显示本地货币符号,99999.99五位整数,两位小数
--9:显示数字,并忽略前面的0
--0:显示数字,如位数不够则用0补齐
--.:在指定的位置显示小数点
--,:在指定的位置显示逗号
--$:在数字前(后)加美元
--L:在数字前(后)加本地货币符号
--C:在数字前(后)加国际货币符号
--G:在指定位置显示组分隔符
--D:在指定位置显示小数点符号(.)
*to_date(myStr, '日期格式字符串')
转换函数用于将数据从一种类型转化为另一种类型。在某些情况下,oracle_sever允许值的数据类型和实际的不一样
这时候oracle_server会隐含地转化数据类型。
ep: sql>create table t1(id int);
sql>insert into t1 values('10'); --这样oracle会自动将'10'-->10
ep: sql>create table t2(id varchar2(10));
sql>insert into t2 values(10); --这样oracle会自动将10-->'10'
--【注】尽管oracle可以隐含进行隐含地数据类型的转换,但是并不适应所有的情况,为了提高数据的可靠性,
--我们还是应用转换函数进行转换
【系统函数】:
使用该函数可以查询系统一些重要信息:
sys_context:
terminal:当前回话客户所对应的终端的标识符
language:语言
db_name:当前数据库名称
nls_date_format:当前绘画客户所对应的日期格式
session_user:当前回话客户所对应的数据库用户名
current_schema:当前回话客户所对应的数据库方案名(与用户名相同),
一个用户一个方案,oracle以方案的方式管理数据库,
方案中有各种数据对象(表、视图、触发器、存储过程……)
host:返回数据库所在主机的名称
查询显示正在使用哪个数据库:
sql>select sys_context('userenv', 'db_name') from dual;
查询显示正在使用哪种语言:
sql>select sys_context('userenv', 'language') from dual;
查询显示当前回话客户所对应的终端的标识符:
sql>select sys_context('userenv', 'terminal') from dual;
查询显示数据库所在主机的名称
sql>select sys_context('userenv', 'host') from dual;
【专门处理空数据函数】:
nvl(comm, 0)--表示若comm为空则用0替代,若comm不为空则用其本身的值来替代nvl(comm, 0)
sql>select ename, sal*12+nvl(comm, 0)*12 "年工资" from emp;--OK
【组函数】
作用于一组数据,有一组数据,函数执行一次。
--【注】不能使用在where子句中!
max(字段名)
min(字段名)
sum(字段名)
avg(字段名)
--【注】这四个组函数执行时自动忽略null值!
显示所有员工的最大工资
select max(salary) from employees;
count(字段名) --对该列的非空值统计数量 --不为空计数器加1,为空则计数器不加1
count(*) --直接对查询结果统计数量
统计总的员工的数量
sql>select count(*) from employees;
sql>select count(employee_id) from employees; --employee_id是主键(非空, 唯一)
统计有奖金的员工的个数
sql>select count(*) from employees where commission_pct is not null;
sql>select count(commission_pct) from employees;
sql>select count(1) from employees; --结果为107,因为1不为空
sql>select count(null) from employees; --结果为0,因为每次都拿null和null作比较
sql>select count(2) from dual; --结果为1,dual表为1行1列的哑表
【分组】--需求中出现(各个或者每个)
语法:select……from……where……group by 分组字段名1, 分组字段名1…… having……order by……
查询显示各部门的最高工资
--第一步:确定分组依据
--第二步:每个小组求最高工资
sql>select department_id, max(salary) from employees group by department_id;
group by的使用规则
a.只有在group by中出现的列,才能出现在select中! --ep:department_id
b.如果在group by中没有出现的列,那么配合组函数后可以出现在select中 --ep:salary
c.如果在group by中应用了某些函数,在select和order by中必须使用完全相同的函数
--【注】出错:不是group by表达式
--组函数不能使用在where中!
查询各岗位的平均工资
sql>select department_id, round(avg(salary))
from employees group by department_id;
统计各个部门、各个岗位的人数
sql>select department_id, job_id, count(*)
from employees group by department_id, job_id
order by department_id, job_id;
查询1997年各月份入职的员工人数
sql>select to_char(hire_date, 'mm') "月份", count(*) "入职人数"
from employees where to_char(hire_date, 'yyyy')='1997'
group by to_char(hire_date, 'mm') order by "月份";
having 对分组后的条件过滤,符合条件的留下
--where是对原始表条件进行过滤,having是对分组后的数据进行过滤
--where效率要比having效率高,优先使用where
--如果使用分组后的结果(通常是组函数)进行过滤,必须使用having
查询平均工资高于8000元的部门的最高工资
select department_id, avg(salary)
from employees
group by department_id
having avg(salary)>8000
order by department_id;
查询50号部门,60号部门,70号部门的平均工资
sql>select department_id, avg(salary)
from employees
where department_id in(50, 60, 70)
group by department_id
order by department_id; --效率高!
sql>select department_id, avg(salary)
from employees
group by department_id
having department_id in(50, 60, 70)
order by department_id; --效率低!
数据库管理
数据库管理员
每个oracle数据库应该至少有一名数据库管理员(dba),对于小的数据库,
一个dba就够了,但是对于一个大的数据库可能需要多个dba分担不同的管理职责。
职责:安装和升级oracel数据库
建库、表空间、表、视图、索引……
指定并实施备份与恢复计划
数据库权限管理、调优、排除故障
高级dba参与项目开发、编写sal语句、存储过程、触发器、规则、约束、包
主要用户:
sys --董事长
system --总经理
区别:
1.最重要的区别是存储的数据的重要性不同
sys:所有oracle的数据字典的基表和视图都存放在sys用户中,这些基表和视图对于oracle是至关重要
的,由数据库自己维护,任何用户都不能手动更改。sys用户拥有dba、sysdba、sysoper角色或权限,
是oracle权限最高的用户。
system:用于存放次级的内部数据,如oracle的一些特性或工具的管理信息。system拥有dba,sysdba
角色或权限。
2.其次的区别是权限的不同
sys:必须以as sysdba或者as sysoper形式登录,不能以normal方式登录数据库。
system:如果正常登录,它其实就是一个普通的dba用户,但如果以as sysdba登录,其结果实际上是作
为sys用户登录的,从登录信息里面可以看出来。
3.三个角色的权限
sysdba > sysoper > dba
------------------------------------------------------------------------------------------
startup--(启动数据库) 有 可启动实例
shutdown--(关闭数据库) 有 关闭实例
alter database open/mount/backup -- 有 只有在启动数据库之后才能
create database(创建数据库) -- 无 执行各项操作
drop database(删除数据库) -- 无
create spfile -- 有
alter database archivelog(归档日志) -- 有
alter database recover(恢复数据库) -- 只能完全恢复,不能部分恢复
拥有restricted session(会话限制)权限 -- 有
可以让用户作为sys用户连接 -- 有一些基本操作,但不能查看用户数据
登陆后用户是sys -- 登陆后是public
------------------------------------------------------------------------------------------
4.重要操作:
显示初始化参数:
show parameter;
修改初始化参数:
到文件D:\oracle\product\10.2.0\admin\orcl\pfile\init.ora文件中去修改实例的名字
数据库(表)备份与恢复:
--【注】所有导出导入操作需要借助oracle安装目录(D:\oracle\product\10.2.0\db_1\bin)下的
--exp.exe和imp.exe工具,需要将这两个工具的路径加入到系统环境变量path中。
--【注】导出导入操作需要在dos窗口中操作
导出:具体分为导出表、导出方案、导出数据库三种方式
都是通过exp命令完成,改命令的常用的选项有:
userid:用于指定执行导出操作的用户名、口令、连接字符串
tables:用于指定执行导出操作的表
owner:用于指定执行导出操作的方案
full=y:用于指定执行导出操作的数据库
inctype:用于执行导出操作的增量类型
rows:用于指定执行导出操作是否要导出表中的数据
file:用于指定导出文件名
导出自己的表:
--在dos下输入命令:
exp userid=scott/tiger@orcl tables=(emp, dept……) file=d:\e1.dmp
导出其他方案的表:
如果用户要导出其他方案的表,则需要dba的权限或exp_full_database的权限,比如
system就可以导出scott的表:
exp userid=system/manager@orcl tables=(scott.emp, scott.dept……) file=d:\e1.dmp
导出表的结构:
exp userid=scott/tiger@orcl tables=(emp, dept……) file=d:\e1.dmp rows=n
使用直接导出的方式:
exp userid=scott/tiger@orcl tables=(emp, dept……) file=d:\e1.dmp direct=y
--这种方式比默认的常规方式要快,当数据量很大时,可以考虑使用这种方式
--这是需要数据库的字符集和客户端的字符集完全一致,否则会报错。
导出自己的方案:
exp userid=scott/tiger@orcl owner=scott file=d:\e1.dmp [direct=y]
导出其他方案:
如果用户要导出其他方案,则需要dba的权限或是exp_full_database的权限,例如
system用户就可以导出任何方案。
exp system/manager@orcl owner=(scott) file=d:\e1.dmp [direct=y]
导出数据库:
导出数据库是指利用exp导出所有数据库中的对象及数据,要求用户具备dba的权限或
exp_full_database权限
exp userid=system/manager@orcl full=y inctype=complete file=e1.dmp [direct=y]
导入:具体分为导入表、导入方案、导入数据库三种方式
常用选项:
userid:用于指定执行导出操作的用户名、口令、连接字符串
tables:用于指定执行导出操作的表
formuser:用于指定源用户
touser:用于指定目标用户
full=y:用于指定执行导出操作的数据库
inctype:用于执行导出操作的增量类型
rows:用于指定执行导出操作是否要导出表中的数据
file:用于指定导出文件名
ignore:若表存在,则只导入数据
导入自己的表:
imp userid=scott/tiger@orcl tables=(emp) file=d:\e1.dmp
--【注】注意导入的表含有主外键的关系时,如果待导入的方案中没有对应的主外键
--导入时就会失败
导入表结构:
imp userid=scott/tiger@orcl tables=(emp) file=d:\e1.dmp rows=n
导入数据:
如果对象(如表)已经存在可以只导入表的数据:
imp userid=scott/tiger@orcl table=(emp) file=d:\e1.dmp ignore=y
导入自身的方案:
import userid=scott/tiger file=d:\e.dmp
导入其他方案:
要求该用户具有dba的权限
imp userid=system/manager file=d:\e.dmp fromuser=system touer=scott
导入数据库:
在默认的情况下,会导入所有对象结构和数据。
imp userid=system/manager full=y file=d:\e1.dmp
数据字典和动态性能视图
数据字典是oracle数据库中最重要的组成部分,它提供了数据库的一些系统信息。
动态性能视图记载了例程启动后的相关信息。
数据字典的组成:
数据字典基表--存储数据库的基本信息,放在sys方案中,只能查询,维护由系统自动完成,普通用户不能直接访问
数据字典动态视图--基于数据字典基表所建立的视图,普通用户可通过查询数据字典视图取得系统信息
user xxx
如:user_tables:用于显示当前用户所拥有的所有表,它只返回用户所对应方案的所有表
select table_name from user_tables;
all xxx
如:all_tables:用于显示当前用户可以访问的所有表。它不仅返回当前用户方案的表,还会返回当前用
户可以访问的其他方案的表。
select table_name from all_tables;
dba xxx
用于显示所有方案拥有的数据库表。要求用户必须是dba角色或是有select any table系统权限。
如:当用system用户查询数据字典视图dba_tables时,会返回system、sys、scott……方案所对应的数据库表
用户名、权限、角色
在建立用户时,oracle会把用户的信息存放到数据字典中,当给用户授权或授予角色(当官了?)
时,oracle会将权限和角色信息存放到数据字典。
通过查询数据库字典视图 dba_users 可以显示所有数据库用户的详细信息
通过查询数据库字典视图 dba_sys_privs 可以显示用户所具有的系统权限
通过查询数据库字典视图 dba_role_privs 可以显示用户所具有的角色
通过查询数据库字典视图 dba_tab_privs 可以显示用户所具有的对象权限
通过查询数据库字典视图 dba_col_privs 可以显示用户所具有的列权限
desc dba_users; --查询表结构
select username from dba_users;--显示所有数据库用户的名字
select * from dba_role_privs where grantee='SCOTT';--显示scott用户拥有的角色信息
如何查询一个角色包含的权限?
Oracle究竟包含多少种角色?
select * from dba_roles;