--概念:
SQL(Structured Query Language)结构化查询语言,包括:
1 DDL(data definition language)数据定义语言
column(data type width constraint)
create table, alter table, drop table
2 DML(data manipulation language)数据操作语言
row
insert update delete
3 DQL(data Query Language)数据查询语句
select
4 TCL(transaction control language)事物控制语言
commit rollback
5 DCL(data control language)数据控制语句
DBA: database administrator
DBMS: database management system
关系型数据库,包括:
Oracle
DB2: IBM
SQL Server: MicroSoft
My SQL
--几个单独的命令:
desc (describe 的缩写) Oracle 的语句 不是SQL的
select table_name from user_tables;
show user
--练习:
select
表达式
列别名 表达式 列别名或者"列别名"
nv1(p1,p2)
if p1 is null then
return p2;
else
return p1;
else if;
先 from 再过滤 where 再 select
where 可以用算术表达式 但是尽量不要使用表达式 能不用表达式尽量不要是用表达式
where子句中不能使用组函数
distinct, between and, or, in () =any(), like, order by asc 或者 desc
in <=> (= any) not in<=> (!= all) 如果集合有null,那么用 not in 比较一定不出结果
任何东西跟null比较,结果都是false
ORACLE_HOME: ORACLE产品的安装目录
ORACLE_SID:数据库所对应的实例(instance)
名字(一个实例唯一对应一个数据库,实例确定了,数据库就确定了)
sh
ORACLE_SID = hiloo
export ORACLE_SID
echo $ORACLE_SID
单行函数:
nvl(s1,s2) s1和s2要数据类型一致
字符类型 character
lower:小写函数
upper:大写函数
initcap:首字符大写函数
dual表(调常量的时候用from dual表,试调函数的时候),例如:select lower('FGJKLDS') from dual;
concat(str1,str2): 拼接,将str2拼接到str1后面
substr(str,begnindex,length): 求子串函数
length(str):字符串长度
lpad(列名,位数,补的符号):右对齐函数,不够的往右补指定字符
rpad:左对齐函数
数值类型 number
round(45.923,2)=>45.92 四舍五入,后边的参数代表留几位小数,可以是负数.(45.923,-1)=>50
trunc 舍掉
日期类型 date
转换函数:
to_number(列名 [,'XXX']) 将字符串转换成数值,类似于parseInt,[]中是可选参数,几个X代表有记录是几位的十
六进制字符,所有记录全按16进制转换
to_char(列名[,'$99,999']) 将数值转换成字符串,[]中是可选参数,表示格式化,即输出的格式,如果数的位数大于
格式化位数,即'9'的个数,显示出问题.
fm 可以压缩掉空格或者前导0
rtrim(to_char(start_date,'month')) = 'march'
rtrim 可以压缩空格
多行函数(组函数):不处理空值.
order by 在select之后,可以使用列别名
group by 分组,若有 group by 子句,select 后面有一个是组函数,其他都必须是组函数,
如果有 group by 子句,select 后面可跟 group by (例:dept_id)后面跟的表达式
(例:dept_id)以及组函数,其他都会报错
having 过滤组,where 过滤的是行(group之后是having之后是select),having 后面只能跟组函数或者组
标识,能先过滤的先过滤(尽量使用 where),having和where都不能使用列别名,where 后面不能跟
组函数
avg
sum
count([distinct | all] *|<列名>) : 不处理空值,当所有值都是空值时,返回0.统计每组的个数
max
min
cross join 笛卡尔积
table1 [inner] join table2 on e.dept_id = d.id 内连接(等值连接),自然连接是一种特殊的等值连接
子查询:
非关联子查询:先执行子查询
单列子查询
多列子查询
关联子查询:先执行主查询
标量子查询:可以解决外连接解决的问题
exists
函数(隐式转换),表达式可能会导致索引用不了
处理匹配问题,可以采用:
inner join
1 select e.first_name,m.first_name
2 from s_emp e join s_emp m
3* on e.manager_id = m.id
非关联子查询 in
关联子查询 exists
处理不匹配问题,可以采用:
outer join
not in
not exists
环境变量
NLS_LANG='SIMPLIFIED CHINESE_CHINA.ZHS16GBK'中文的. 'AMERICAN_AMARICA.US7ASCII'
export NLS_LANG
[inner] join 匹配的记录
from t1 join t2
on t1.c1 = t2.c2
[outer] join 匹配不上记录
from t1 left join t2
on t1.c1 = t2.c2
外连接的结果集=内连接的结果集+t1表中匹配不上的记录和t2表中的一条null记录
from t1 right join t2
on t1.c1 = t2.c2
from t1 full join t2
on t1.c1 = t2.c2
外连接+where is NUll 用来解决否定问题 也就是"不是 不包含 没有"的问题,如哪个部门没有员工,哪个员工没有老板(终极boss)
select e.first_name,m.first_name
from s_emp e left join s_emp m
on e.manager_id = m.id;
单行函数:
nvl(s1,s2) s1和s2要数据类型一致
字符类型 character
lower:小写函数
upper:大写函数
initcap:首字符大写函数
dual表(调常量的时候用from dual表,试调函数的时候),例如:select lower('FGJKLDS') from dual;
concat(str1,str2): 拼接,将str2拼接到str1后面
substr(str,begnindex,length): 求子串函数
length(str):字符串长度
lpad(列名,位数,补的符号):右对齐函数,不够的往右补指定字符
rpad:左对齐函数
数值类型 number
round(45.923,2)=>45.92 四舍五入,后边的参数代表留几位小数,可以是负数.(45.923,-1)=>50
trunc 舍掉
日期类型 date
转换函数:
to_number(列名 [,'XXX']) 将字符串转换成数值,类似于parseInt,[]中是可选参数,几个X代表有记录是几位的十
六进制字符,所有记录全按16进制转换
to_char(列名[,'$99,999']) 将数值转换成字符串,[]中是可选参数,表示格式化,即输出的格式,如果数的位数大于
格式化位数,即'9'的个数,显示出问题.
fm 可以压缩掉空格或者前导0
rtrim(to_char(start_date,'month')) = 'march'
rtrim 可以压缩空格
多行函数(组函数):不处理空值.
order by 在select之后,可以使用列别名
group by 分组,若有 group by 子句,select 后面有一个是组函数,其他都必须是组函数,
如果有 group by 子句,select 后面可跟 group by (例:dept_id)后面跟的表达式
(例:dept_id)以及组函数,其他都会报错
having 过滤组,where 过滤的是行(group之后是having之后是select),having 后面只能跟组函数或者组
标识,能先过滤的先过滤(尽量使用 where),having和where都不能使用列别名,where 后面不能跟
组函数
avg
sum
count([distinct | all] *|<列名>) : 不处理空值,当所有值都是空值时,返回0.统计每组的个数
max
min
cross join 笛卡尔积
table1 [inner] join table2 on e.dept_id = d.id 内连接(等值连接),自然连接是一种特殊的等值连接
子查询:
非关联子查询:先执行子查询
单列子查询
多列子查询
关联子查询:先执行主查询
标量子查询:可以解决外连接解决的问题
exists
函数(隐式转换),表达式可能会导致索引用不了
处理匹配问题,可以采用:
inner join
1 select e.first_name,m.first_name
2 from s_emp e join s_emp m
3* on e.manager_id = m.id
非关联子查询 in
关联子查询 exists
处理不匹配问题,可以采用:
outer join
not in
not exists
环境变量
NLS_LANG='SIMPLIFIED CHINESE_CHINA.ZHS16GBK'中文的. 'AMERICAN_AMARICA.US7ASCII'
export NLS_LANG
[inner] join 匹配的记录
from t1 join t2
on t1.c1 = t2.c2
[outer] join 匹配不上记录
from t1 left join t2
on t1.c1 = t2.c2
外连接的结果集=内连接的结果集+t1表中匹配不上的记录和t2表中的一条null记录
from t1 right join t2
on t1.c1 = t2.c2
from t1 full join t2
on t1.c1 = t2.c2
外连接+where is NUll 用来解决否定问题 也就是"不是 不包含 没有"的问题,如哪个部门没有员工,哪个员工没有老板(终极boss)
select e.first_name,m.first_name
from s_emp e left join s_emp m
on e.manager_id = m.id;
单行函数:
nvl(s1,s2) s1和s2要数据类型一致
字符类型 character
lower:小写函数
upper:大写函数
initcap:首字符大写函数
dual表(调常量的时候用from dual表,试调函数的时候),例如:select lower('FGJKLDS') from dual;
concat(str1,str2): 拼接,将str2拼接到str1后面
substr(str,begnindex,length): 求子串函数
length(str):字符串长度
lpad(列名,位数,补的符号):右对齐函数,不够的往右补指定字符
rpad:左对齐函数
数值类型 number
round(45.923,2)=>45.92 四舍五入,后边的参数代表留几位小数,可以是负数.(45.923,-1)=>50
trunc 舍掉
日期类型 date
转换函数:
to_number(列名 [,'XXX']) 将字符串转换成数值,类似于parseInt,[]中是可选参数,几个X代表有记录是几位的十
六进制字符,所有记录全按16进制转换
to_char(列名[,'$99,999']) 将数值转换成字符串,[]中是可选参数,表示格式化,即输出的格式,如果数的位数大于
格式化位数,即'9'的个数,显示出问题.
fm 可以压缩掉空格或者前导0
rtrim(to_char(start_date,'month')) = 'march'
rtrim 可以压缩空格
多行函数(组函数):不处理空值.
order by 在select之后,可以使用列别名
group by 分组,若有 group by 子句,select 后面有一个是组函数,其他都必须是组函数,
如果有 group by 子句,select 后面可跟 group by (例:dept_id)后面跟的表达式
(例:dept_id)以及组函数,其他都会报错
having 过滤组,where 过滤的是行(group之后是having之后是select),having 后面只能跟组函数或者组
标识,能先过滤的先过滤(尽量使用 where),having和where都不能使用列别名,where 后面不能跟
组函数
avg
sum
count([distinct | all] *|<列名>) : 不处理空值,当所有值都是空值时,返回0.统计每组的个数
max
min
cross join 笛卡尔积
table1 [inner] join table2 on e.dept_id = d.id 内连接(等值连接),自然连接是一种特殊的等值连接
子查询:
非关联子查询:先执行子查询
单列子查询
多列子查询
关联子查询:先执行主查询
标量子查询:可以解决外连接解决的问题
exists
函数(隐式转换),表达式可能会导致索引用不了
处理匹配问题,可以采用:
inner join
1 select e.first_name,m.first_name
2 from s_emp e join s_emp m
3* on e.manager_id = m.id
非关联子查询 in
关联子查询 exists
处理不匹配问题,可以采用:
outer join
not in
not exists
环境变量
NLS_LANG='SIMPLIFIED CHINESE_CHINA.ZHS16GBK'中文的. 'AMERICAN_AMARICA.US7ASCII'
export NLS_LANG
[inner] join 匹配的记录
from t1 join t2
on t1.c1 = t2.c2
[outer] join 匹配不上记录
from t1 left join t2
on t1.c1 = t2.c2
外连接的结果集=内连接的结果集+t1表中匹配不上的记录和t2表中的一条null记录
from t1 right join t2
on t1.c1 = t2.c2
from t1 full join t2
on t1.c1 = t2.c2
外连接+where is NUll 用来解决否定问题 也就是"不是 不包含 没有"的问题,如哪个部门没有员工,哪个员工没有老板(终极boss)
select e.first_name,m.first_name
from s_emp e left join s_emp m
on e.manager_id = m.id;
另一种语法:内连接
select t1.c1,t2.c2,t3.c3
from t1,t2
where t1.c1 = t2.c2
and t2.c4 = t3.c3
select t1.c1,t2.c2
from t1,t2
where t1.c1 = t2.c2(+) 等价于 t2.c2(+) = t1.c1 t1是驱动表
and t2.c1 is null
基于数据库的开发 E-R图:
需求分析->设计->开发测试->实施,上线->生产系统
E: entity实体.
有共同属性的一类对象的集合.例子:客户,销售代表,订单
attribute:属性.
通过属性描述实体,区分实体.例子:名字,电话,身份证号
R:relationship关系.
描述实体和实体的关系.例子:客户订货通过客户和订单的关系来表达
语法:
实体和实体的关系从实例之间的数量关系的角度可分为1:1 1:n n:m
实体和实体之间的关系从紧密程度上分为 必须 和 可以
保证数据的一致性
通过数据库的特性或应用程序完成
数据库约束:constrains:约束.
主键(primary key),唯一键(unique key),外键(foreign key)
主键(PK): 要求唯一且非空
联合主键(pk): 多列联合唯一,联合主键任意单一列都可以重复,但是所有联合主键加起来就不能重复,每一列都
不能为null
外键(FK): 在child table上定义FK(dept_id) --> 在parent table(id) pk/uk(id)
1 先create parent table,pk uk. 再建child table
2 先 insert into parent table,再insert into child table
3 删除数据,先delete child table,再delete parent table
4 删除表,先drop child table, 再drop parent table.
表和列分别对应实体和属性
定义命名规范
还需要考虑建索引和视图等
将属性转成列
强制属性定义成非空约束
将唯一标识定义成主键
主键意为非空约束加上唯一约束
一张表上只能有一个pk,其他唯一标识定义成非空性约束且唯一
一对多关系:
一的那一边定义成(pk)或唯一键(UK) parent table
多的那边定成 child table 外键(FK) FK可以为空 要实现必须 还得加非空约束
一对一关系:在外键(FK)列上增加唯一约束(UK)
若 一对一关系在两头都是可选的,任意一边定义成fk
若 一对一关系中有一边是强制的,将其定义成外键(FK)
一对一的例子:
1. 合表 好处 查询容易 不用表链接
2. 分表 好处 可以单独取出一边的信息
对于强制关系:在外键FK上定义非空约束
多对多关系:再加一张表,如 学生选课表 里面有 sid(学生id) cid(课程id) 成绩等.. 将sid和cid定义成uk,
并且把sid定义成fk,cid也定义成fk.多对多用 m:1和1:n实现m:n
多对多的例子:
student (id,name..)
pk (id)
name not null
course(id,name..)
pk(id)
name not null
stu_cou(sid,cid,grade)
pk(sid,cid)
fk(sid) ---> student(id)
fk(cid) ---> course(id)
NF用来最小化数据冗余,减少完整性问题 标识丢失的实体,关系,表
1NF: 有PK就叫1NF,列不可再分
2NF: 所有的非主属性必须完全依赖于主属性,例如:pk(sid,cid) grade(完全依赖) cname(部分依赖,只依赖于cid),
不符合第二范式, 联合主键 有时出现 部分依赖 不满足2NF
3NF: 每个非主属性不能依赖于另外一个非主属性,如:PK(sid) c_id(班id) c_name(班名称), c_name->c_id,不符合
第三范式 把一对多关系合表,不符合第三范式
数据类型:
VARCHAR2 和 CHAR
NUMBER:
不指定宽度 :
38位
指定宽度 :
number(6)
number(4,2) 总共4位,小数占两位
number(3,-3) 正数表示范围是1000-999000
number(2,4) 小数以后4位 只能添两位 最大数是0.0099
DATE:
日期类型不能定义宽度
alter session set nls_date_format = 'yyyy mm dd hh24:mi:ss';
yyyy:
mm
dd
hh24
h12
mi
ss
d用数字表示一周的第几天
day: 用全拼表示星期几(sunday..)
month:用全拼表达的月(march)
ddd:一年的第几天
YY 和 RR: 存储都是四位年,如果用两位年进行输入 用yy格式输入 例如: 99 'yyyy' 就变成当前世纪 2099年
rr:不指定格式就是rr,rr按前50年 后50年区分
尽量不要是用两位年进行插入年份
months_between('01-sep-95','11-JAN-94')
add_months('11-JAN-94',6)
next_day('01-SEP','')
last_day(sysdate) 一个月最后一天,小时 分钟 秒 保留当前
next_day(sysdate,'Friday') 今天之后最先出现的Friday 的年月日和当前时分秒
sysdate = 1995-5-25
round 四舍五入,里边 sysdate 不能换成 '01-JAN-09' 不能转成日期
round(sysdate,'MONTH') -> 01-JUN-95
round(sysdate,'year') -> 01-JAN-95
trunc 舍,里边 sysdate 不能换成 '01-JAN-09' 不能转成日期
trunc(sysdate,'MONTH')
trunc(sysdate,'YEAR')
(DDL) create(创建) drop(删除) alter(更新)
一.主键约束: primary key 唯一非空 只能有一个
可以用列级约束和表级约束完成,效果一样
列级约束: c1 number constraints pk_name(给主键起名字) primary key,
表级约束: c1 number, constraints pk_name(给主键起名字) primary key(c1),
二.联合主键约束:primary key(c1,c2) 联合唯一 联合的每列非空 只能有一个
只能用表级约束完成,例如:
create table ren (
c1 number ,
c2 number,
c3 number,
constraints ren_pk primary key(c1,c2));
不能使用列级约束完成:
create table ren (
c1 number constraints name1 primary key,
c2 number constraints name2 primary key,
c3 number,);
不能有两个主键,报错
三.外键约束:foreign key
可以使用列级约束或者表级约束
列级约束:
create table ren_parent(
c1 number(4) constraints parent_c1_pk primary key);
create table ren_child(
c1 number(3) constraints child_c1_pk primary key,
c2 number(4) constraints child_c2_fk references ren_parent(c1) [on delete cascade]);
注: 1创建表必须先建父表,再建子表.不然会报错
2删除先删除子表,才能删除父表,不然会报错
3或者删除的时候是用 drop table ren_parent cascade constraints;先解除父子表之间的主
外键关系再删除父表,子表还存在,数据也在,父子表之间的主外键关系被删除了,子表自己的主键
还在.
表级约束:
create table ren_parent(
c1 number(4) constraints parent_c1_pk primary key);
create table ren_child(
c1 number(3) constraints child_c1_pk primary key,
c2 number(4),
constraints child_c2_fk foreign key(c2)
references ren_parent(c1) [on delete cascade])
比列级约束多了一个foreign key(c2)字段,就是指定c2属性是父表c1属性的外键
建子表的子外键关系时,加上 on delete cascade,级联删除,当 delete 父表的数据时,先删除子表中引
用了这条记录的记录,再删除父表的数据
on delete set null
Oracle 不支持 on update cascade 但是别的关系型数据库支持
四.唯一约束: unique
可以使用列级约束或表级约束
列级约束:
create table ren(
c1 number(4) constraints ren_c1_pk primary key,
c2 number constriants ren_c2_uk unique,
c3 number constriants ren_c3_uk unique,
)
表级约束:
create table ren(
c1 number(4) constraints ren_c1_pk primary key,
c2 number,
c3 number,
constriants ren_c2_uk unique(c2),
constriants ren_c3_uk unique(c3),
)
五.联合唯一:unique(c1,c2)
constriants ren_c3_uk unique(c2,c3),
c2可以不唯一
c3可以不唯一
但是 c2 和 c3 加一块 必须唯一
六:检查约束: check(c1>100)
可以使用列级约束和表级约束
列级约束:
create table ren(
c1 number constraints ren_c1_ck check(c1>100))
表级约束
create table ren(
c1 number,
constraints ren_c1_ck check(c1>100))
七:非空约束:not null
执行脚本:
不在sqlplus环境中
sqlplus username/password @test.sql
在sql环境中
使用 @test.sql
@ 只在当前cd目录中找,或者使用绝对路径
根据子查询创建表并且插入数据
create table emp_41
as
select id,first_name,title,salary,dept_id
from s_emp
where dept_id = 41;
drop table table_name;--删除表
drop table table_name cascade constraints;--去除FK 删除表
alter table emp_41 --给已经存在的表追加约束
add constraints emp_41_id_pk primary key(id);
--------------------------------------------------------------------------------------
(DML) insert(插入) delete(删除) update(更新)
一.insert
insert into table_name values(
)
二.update
update ren_child
set c2 = 1,
where c2 is null;
1 update ren_emp e
2 set ann_sal = (select ann_sal*(1+commission_pct/100)
3 from ren_emp_comm c
4 where e.id = c.id)
5 where exists(select * from ren_emp_comm c
6 where e.id = c.id);
三.delete
delete table_name
where
--------------------------------------------------------------------------------------
事务
DDL 语句自动提交
锁:
DML锁: tx锁(事务锁,行级锁) 类型为x锁
tm锁(意向锁,表级锁) 属于一种
回滚: 回滚段(rollback segment)
t1表和t2表做内连接,连接条件为on t1.c1 = t2.c2,
假设t1表做驱动表,t2表做匹配表,记录的匹配过程如下:
1、从t1表中读取第一条记录r1,若它的c1值为1
2、根据该值到t2表中查找匹配的记录,即需要遍历t2表,从t2表中的第一条记录开始,若该记录(r1)的c2列的值=1,我们就说这两条记录能够匹配上,那么t1的r1和t2的r1组合起来,作为结果集里的一条记录,否则不能组合起来,即被过滤掉。
3、按照方法2依次将t2表中所有的记录检测一遍,只要匹配就放入结果集中
4、从t1表中读取第二条记录,依次重复步骤2和3,产生最终的结果集
t1表和t2表做内连接,连接条件为on t1.c1 = t2.c2,
假设t1表做驱动表,t2表做匹配表,记录的匹配有如下三
种情况:
1、t1表中的某条记录在t2中找不到任何一条匹配的记录,那么t1表中的该记录不会出现在结果集中
2、t1表中的某条记录在t2表中只有一条匹配的记录,那么t1表中的该记录和t2表中匹配的记录组合成新记录出现在结果集中
3、t1表中的某条记录在t2表中有多条匹配的记录,那么t1表中的该记录会和t2表中每一条匹配的记录组合成新记录出现在结果集中
4、内连接的核心为任何一张表里的记录一定要在另一张表中找到匹配的记录,否则不能出现在结果集中
t1表和t2表做内连接,连接条件为on t1.c1 = t2.c2
有两种方式都能得到结果集记录
1、一种t1表做驱动表,t2表做匹配表
2、另一种t2表做驱动表,t1表做匹配表
3、无论哪种方式最终得到的结果集都一样,所不同的是效率
t1表和t2表做外连接,连接条件为
from t1 left outer join t2 on t1.c1 = t2.c2,
t1表必须做驱动表,t2表做匹配表,记录的匹配过程如下:
1、从t1表中读取第一条记录r1,若它的c1值为1
2、根据该值到t2表中查找匹配的记录,即需要遍历t2表,从t2表中的第一条记录开始,若该记录(r1)的c2列的值=1,我们就说这两条记录能够匹配上,那么t1的r1和t2的r1组合起来,作为结果集里的一条记录,否则不能组合起来,即被过滤掉。
3、按照方法2依次将t2表中所有的记录检测一遍,只要匹配就放入结果集中,若扫描完后,t1的r1记录在t2表中找不到任何匹配的记录,t2表中模拟一条null记录与t1表中r1组合起来,放入结果集中
4、从t1表中读取第二条记录,依次重复步骤2和3,产生最终的结果集
t1表和t2表做外连接,连接条件为
from t1 left outer join t2 on t1.c1 = t2.c2,
t1表必须做驱动表,t2表做匹配表,
1、外连接的结果集=内连接的结果集+t1表中匹配不上的记录和一条null记录的组合
2、外连接的核心可以将匹配不上的记录找回来,即一个都不能少
t1表和t2表做外连接,连接条件为
from t1 right outer join t2 on t1.c1 = t2.c2,
t2表必须做驱动表,t1表做匹配表,
1、外连接的结果集=内连接的结果集+t2表中匹配不上的记录和一条null记录的组合
t1表和t2表做外连接,连接条件为
from t1 full outer join t2 on t1.c1 = t2.c2,
t2表必须做驱动表,t1表做匹配表,
外连接的结果集=内连接的结果集+t2表中匹配不上的记录和一条null记录的组合+t1表中匹配不上的记录和一条null记录的组合
根据GROUP BY子句指定的表达式,将要处理的数据(若有WHERE子句即为通过条件过滤后的数据)分成若干组,每组有唯一的组标识,组内有若干条记录,根据SELECT后面的组函数对每组的记录进行计算,每组对应一个返回值
where和having的区别
WHERE子句过滤的是行(记录)
HAVING子句过滤的是分组以后的聚合结果
WHERE子句包含单行函数
HAVING子句只能包含GROUP BY后面的表达式和组函数
WHERE子句执行在前,HAVING子句执行在后
WHERE子句和HAVING子句都不允许用列别名
先执行子查询,子查询的返回结果作为主查询的条件,再执行主查询。
子查询只执行一遍
若子查询的返回结果为多个值,ORACLE会去掉重复值之后,再将结果返回给主查询
关联子查询采用的是循环(loop)的方式,执行步骤如下:
1 外部查询得到一条记录(查询先从outer表中读取数据)并将其传入到内部查询。
2 内部查询基于传入的值执行。
3 内部查询从其结果中把值传回到外部查询,外部查询使用这些值来完成其处理,若符合条件,outer表中得到的那条记录就放入结果集中,否则放弃,该记录不符合条件。
4 重复执行步骤1-3, 直到把outer表中的所有记录判断一遍。
EXISTS采用的是循环(loop)方式,判断outer表中是否存在记录只要在inner表中找到一条匹配的记录即可。
1 外部查询得到一条记录(查询先从outer表中读取数据)并将其传入到内部查询的表。
2 对inner表中的记录依次扫描,若根据条件存在一条记录与outer表中的记录匹配,立即停止扫描,返回true,将outer表中的记录放入结果集中,若扫描了全部记录,没有任何一条记录符合匹配条件,返回false ,outer表中的该记录被过滤掉,不能出现在结果集中。
3 重复执行步骤1-2, 直到把outer表中的所有记录判断一遍。
NOT EXISTS采用的是循环(loop)方式,判断在outer表中是否不存在记录,它能在inner表中能找到匹配的记录。
1 外部查询得到一条记录(查询先从outer表中读取数据)并将其传入到内部查询的表。
2 对inner表中的记录依次扫描,若根据条件存在一条记录与outer表中的记录匹配,立即停止扫描,返回false, outer表中的该记录被过滤掉,不能出现在结果集中,若扫描了全部记录,没有任何一条记录符合匹配条件,返回true,将outer表中的记录放入结果集中。
3 重复执行步骤1-2, 直到把outer表中的所有记录判断一遍。
EXISTS是用循环(loop)的方式,由outer表的记录数决定循环的次数,对于exists影响最大,所以,外表的记录数要少
IN先执行子查询,子查询的返回结果去重之后,再执行主查询,所以,子查询的返回结果越少,越适合用该方式
事务的特性:ACID
原子性(atomic):一个事务要么完全发生、要么完全不发生
一致性(consistent):事务把数据库从一个一致状态转变到另一个状态
隔离性(isolated):在事务提交之前,其他事务觉察不到事务的影响
持久性(durable):一旦事务提交,它是永久的
数据库应用程序中最常用的隔离级别
Read committed
一个事务只可以读取在事务开始之前提交的数据和本事务正
在修改的数据。
在开发多用户、数据库驱动的应用程序中,关键性的挑战之一是要使并行的访问量达到最大化,同时还要保证每一个用户可以以一致的方式读取并修改数据。
锁(lock)机制
用来管理对一个共享资源的并行访问
多版本一致读
非阻塞查询:写不阻塞读,读不阻塞写
一致读查询:在某一时刻查询产生一致结果
排他锁
如果一个对象上加了X锁,在这个锁被采用commit或rollback
释放之前,该对象上不能施加任何其他类型的锁
共享锁:
如果一个对象被加上了S锁,该对象上可以加其他类型的S锁,但
是,在该锁释放之前,该对象不能被加任何其他类型的X锁
为确保并发用户能正确使用与管理共享资源,如表中的记录,oracle引进锁机制
DML锁:用于保护数据的完整性
TX锁,即事务锁(行级锁),类型为X锁
TM锁,即意向锁(表级锁),属于一种S锁
DDL锁:用于保护数据库对象的结构(例如表、索引的结构定义)
X类型的DDL锁,这些锁定防止其他会话自己获得DDL锁定或
TM(DML)锁定。这意味着可以在DDL其间查询一个表,但不
可以以任何方式进行修改
全表扫描FTS(Full Table Scan)
高水位线:曾经包含数据的最右边的块
将扫描高水位线以下的所有数据块
通过rowid来扫描数据
Rowid:标识一条记录的物理位置
包含如下信息:
该记录属于哪张表的(哪个数据库对象):object_id
该记录在哪个数据文件里:file_id
该记录在数据文件的第几个数据块里:block_id
该记录在数据块里是第几条记录:row_id
索引使用的是B*tree结构
B*tree索引由根节点(root block)、分支块(branch block)、叶子节点(leaf block)组成
根块下面是分支块,用于导航结构,包含了索引列范围和另一索引块(可以是分支块或叶子节点)的地址
最底层为叶子节点,包含索引项(index entry),索引项由key值(被索引列的值)和相应行所对应的rowid组成
索引上叶子节点实际上是双向链接的表。一旦找到叶子节点的“开始”点(一旦找到第一个值),对值进行顺序扫描(索引范围扫描)是很容易的。不必再做结构导航,只要通过叶子节点转发就行
ROWNUM是一个伪列,对查询返回的行编号即行号,由1开始依次递增
WHERE ROWNUM <= 5的执行过程
Oracle获取第一个符合条1件的行,将它叫做第1行
有5行了吗?如果没有,oracle就再返回行,因为它要满足行号
小于等于5的条件,如果到了5行,那么,oracle就不再返回行
Oracle获取下一行,并递增行号(从2,到3,再到4,等等)
返回到第2步
关键点:Oracle的rownum数值是在获取每行之后才赋予的
WHERE ROWNUM = 5的执行过程
Oracle获取第一个符合条1件的行,将它叫做第1行
有5行了吗?如果没有,oracle就再返回行,因为它要满足行号
小于等于5的条件,如果到了5行,那么,oracle就不再返回行
Oracle获取下一行,并递增行号(从2,到3,再到4,等等)
返回到第2步
哈哈,可能有点乱
SQL(Structured Query Language)结构化查询语言,包括:
1 DDL(data definition language)数据定义语言
column(data type width constraint)
create table, alter table, drop table
2 DML(data manipulation language)数据操作语言
row
insert update delete
3 DQL(data Query Language)数据查询语句
select
4 TCL(transaction control language)事物控制语言
commit rollback
5 DCL(data control language)数据控制语句
DBA: database administrator
DBMS: database management system
关系型数据库,包括:
Oracle
DB2: IBM
SQL Server: MicroSoft
My SQL
--几个单独的命令:
desc (describe 的缩写) Oracle 的语句 不是SQL的
select table_name from user_tables;
show user
--练习:
select
表达式
列别名 表达式 列别名或者"列别名"
nv1(p1,p2)
if p1 is null then
return p2;
else
return p1;
else if;
先 from 再过滤 where 再 select
where 可以用算术表达式 但是尽量不要使用表达式 能不用表达式尽量不要是用表达式
where子句中不能使用组函数
distinct, between and, or, in () =any(), like, order by asc 或者 desc
in <=> (= any) not in<=> (!= all) 如果集合有null,那么用 not in 比较一定不出结果
任何东西跟null比较,结果都是false
ORACLE_HOME: ORACLE产品的安装目录
ORACLE_SID:数据库所对应的实例(instance)
名字(一个实例唯一对应一个数据库,实例确定了,数据库就确定了)
sh
ORACLE_SID = hiloo
export ORACLE_SID
echo $ORACLE_SID
单行函数:
nvl(s1,s2) s1和s2要数据类型一致
字符类型 character
lower:小写函数
upper:大写函数
initcap:首字符大写函数
dual表(调常量的时候用from dual表,试调函数的时候),例如:select lower('FGJKLDS') from dual;
concat(str1,str2): 拼接,将str2拼接到str1后面
substr(str,begnindex,length): 求子串函数
length(str):字符串长度
lpad(列名,位数,补的符号):右对齐函数,不够的往右补指定字符
rpad:左对齐函数
数值类型 number
round(45.923,2)=>45.92 四舍五入,后边的参数代表留几位小数,可以是负数.(45.923,-1)=>50
trunc 舍掉
日期类型 date
转换函数:
to_number(列名 [,'XXX']) 将字符串转换成数值,类似于parseInt,[]中是可选参数,几个X代表有记录是几位的十
六进制字符,所有记录全按16进制转换
to_char(列名[,'$99,999']) 将数值转换成字符串,[]中是可选参数,表示格式化,即输出的格式,如果数的位数大于
格式化位数,即'9'的个数,显示出问题.
fm 可以压缩掉空格或者前导0
rtrim(to_char(start_date,'month')) = 'march'
rtrim 可以压缩空格
多行函数(组函数):不处理空值.
order by 在select之后,可以使用列别名
group by 分组,若有 group by 子句,select 后面有一个是组函数,其他都必须是组函数,
如果有 group by 子句,select 后面可跟 group by (例:dept_id)后面跟的表达式
(例:dept_id)以及组函数,其他都会报错
having 过滤组,where 过滤的是行(group之后是having之后是select),having 后面只能跟组函数或者组
标识,能先过滤的先过滤(尽量使用 where),having和where都不能使用列别名,where 后面不能跟
组函数
avg
sum
count([distinct | all] *|<列名>) : 不处理空值,当所有值都是空值时,返回0.统计每组的个数
max
min
cross join 笛卡尔积
table1 [inner] join table2 on e.dept_id = d.id 内连接(等值连接),自然连接是一种特殊的等值连接
子查询:
非关联子查询:先执行子查询
单列子查询
多列子查询
关联子查询:先执行主查询
标量子查询:可以解决外连接解决的问题
exists
函数(隐式转换),表达式可能会导致索引用不了
处理匹配问题,可以采用:
inner join
1 select e.first_name,m.first_name
2 from s_emp e join s_emp m
3* on e.manager_id = m.id
非关联子查询 in
关联子查询 exists
处理不匹配问题,可以采用:
outer join
not in
not exists
环境变量
NLS_LANG='SIMPLIFIED CHINESE_CHINA.ZHS16GBK'中文的. 'AMERICAN_AMARICA.US7ASCII'
export NLS_LANG
[inner] join 匹配的记录
from t1 join t2
on t1.c1 = t2.c2
[outer] join 匹配不上记录
from t1 left join t2
on t1.c1 = t2.c2
外连接的结果集=内连接的结果集+t1表中匹配不上的记录和t2表中的一条null记录
from t1 right join t2
on t1.c1 = t2.c2
from t1 full join t2
on t1.c1 = t2.c2
外连接+where is NUll 用来解决否定问题 也就是"不是 不包含 没有"的问题,如哪个部门没有员工,哪个员工没有老板(终极boss)
select e.first_name,m.first_name
from s_emp e left join s_emp m
on e.manager_id = m.id;
单行函数:
nvl(s1,s2) s1和s2要数据类型一致
字符类型 character
lower:小写函数
upper:大写函数
initcap:首字符大写函数
dual表(调常量的时候用from dual表,试调函数的时候),例如:select lower('FGJKLDS') from dual;
concat(str1,str2): 拼接,将str2拼接到str1后面
substr(str,begnindex,length): 求子串函数
length(str):字符串长度
lpad(列名,位数,补的符号):右对齐函数,不够的往右补指定字符
rpad:左对齐函数
数值类型 number
round(45.923,2)=>45.92 四舍五入,后边的参数代表留几位小数,可以是负数.(45.923,-1)=>50
trunc 舍掉
日期类型 date
转换函数:
to_number(列名 [,'XXX']) 将字符串转换成数值,类似于parseInt,[]中是可选参数,几个X代表有记录是几位的十
六进制字符,所有记录全按16进制转换
to_char(列名[,'$99,999']) 将数值转换成字符串,[]中是可选参数,表示格式化,即输出的格式,如果数的位数大于
格式化位数,即'9'的个数,显示出问题.
fm 可以压缩掉空格或者前导0
rtrim(to_char(start_date,'month')) = 'march'
rtrim 可以压缩空格
多行函数(组函数):不处理空值.
order by 在select之后,可以使用列别名
group by 分组,若有 group by 子句,select 后面有一个是组函数,其他都必须是组函数,
如果有 group by 子句,select 后面可跟 group by (例:dept_id)后面跟的表达式
(例:dept_id)以及组函数,其他都会报错
having 过滤组,where 过滤的是行(group之后是having之后是select),having 后面只能跟组函数或者组
标识,能先过滤的先过滤(尽量使用 where),having和where都不能使用列别名,where 后面不能跟
组函数
avg
sum
count([distinct | all] *|<列名>) : 不处理空值,当所有值都是空值时,返回0.统计每组的个数
max
min
cross join 笛卡尔积
table1 [inner] join table2 on e.dept_id = d.id 内连接(等值连接),自然连接是一种特殊的等值连接
子查询:
非关联子查询:先执行子查询
单列子查询
多列子查询
关联子查询:先执行主查询
标量子查询:可以解决外连接解决的问题
exists
函数(隐式转换),表达式可能会导致索引用不了
处理匹配问题,可以采用:
inner join
1 select e.first_name,m.first_name
2 from s_emp e join s_emp m
3* on e.manager_id = m.id
非关联子查询 in
关联子查询 exists
处理不匹配问题,可以采用:
outer join
not in
not exists
环境变量
NLS_LANG='SIMPLIFIED CHINESE_CHINA.ZHS16GBK'中文的. 'AMERICAN_AMARICA.US7ASCII'
export NLS_LANG
[inner] join 匹配的记录
from t1 join t2
on t1.c1 = t2.c2
[outer] join 匹配不上记录
from t1 left join t2
on t1.c1 = t2.c2
外连接的结果集=内连接的结果集+t1表中匹配不上的记录和t2表中的一条null记录
from t1 right join t2
on t1.c1 = t2.c2
from t1 full join t2
on t1.c1 = t2.c2
外连接+where is NUll 用来解决否定问题 也就是"不是 不包含 没有"的问题,如哪个部门没有员工,哪个员工没有老板(终极boss)
select e.first_name,m.first_name
from s_emp e left join s_emp m
on e.manager_id = m.id;
单行函数:
nvl(s1,s2) s1和s2要数据类型一致
字符类型 character
lower:小写函数
upper:大写函数
initcap:首字符大写函数
dual表(调常量的时候用from dual表,试调函数的时候),例如:select lower('FGJKLDS') from dual;
concat(str1,str2): 拼接,将str2拼接到str1后面
substr(str,begnindex,length): 求子串函数
length(str):字符串长度
lpad(列名,位数,补的符号):右对齐函数,不够的往右补指定字符
rpad:左对齐函数
数值类型 number
round(45.923,2)=>45.92 四舍五入,后边的参数代表留几位小数,可以是负数.(45.923,-1)=>50
trunc 舍掉
日期类型 date
转换函数:
to_number(列名 [,'XXX']) 将字符串转换成数值,类似于parseInt,[]中是可选参数,几个X代表有记录是几位的十
六进制字符,所有记录全按16进制转换
to_char(列名[,'$99,999']) 将数值转换成字符串,[]中是可选参数,表示格式化,即输出的格式,如果数的位数大于
格式化位数,即'9'的个数,显示出问题.
fm 可以压缩掉空格或者前导0
rtrim(to_char(start_date,'month')) = 'march'
rtrim 可以压缩空格
多行函数(组函数):不处理空值.
order by 在select之后,可以使用列别名
group by 分组,若有 group by 子句,select 后面有一个是组函数,其他都必须是组函数,
如果有 group by 子句,select 后面可跟 group by (例:dept_id)后面跟的表达式
(例:dept_id)以及组函数,其他都会报错
having 过滤组,where 过滤的是行(group之后是having之后是select),having 后面只能跟组函数或者组
标识,能先过滤的先过滤(尽量使用 where),having和where都不能使用列别名,where 后面不能跟
组函数
avg
sum
count([distinct | all] *|<列名>) : 不处理空值,当所有值都是空值时,返回0.统计每组的个数
max
min
cross join 笛卡尔积
table1 [inner] join table2 on e.dept_id = d.id 内连接(等值连接),自然连接是一种特殊的等值连接
子查询:
非关联子查询:先执行子查询
单列子查询
多列子查询
关联子查询:先执行主查询
标量子查询:可以解决外连接解决的问题
exists
函数(隐式转换),表达式可能会导致索引用不了
处理匹配问题,可以采用:
inner join
1 select e.first_name,m.first_name
2 from s_emp e join s_emp m
3* on e.manager_id = m.id
非关联子查询 in
关联子查询 exists
处理不匹配问题,可以采用:
outer join
not in
not exists
环境变量
NLS_LANG='SIMPLIFIED CHINESE_CHINA.ZHS16GBK'中文的. 'AMERICAN_AMARICA.US7ASCII'
export NLS_LANG
[inner] join 匹配的记录
from t1 join t2
on t1.c1 = t2.c2
[outer] join 匹配不上记录
from t1 left join t2
on t1.c1 = t2.c2
外连接的结果集=内连接的结果集+t1表中匹配不上的记录和t2表中的一条null记录
from t1 right join t2
on t1.c1 = t2.c2
from t1 full join t2
on t1.c1 = t2.c2
外连接+where is NUll 用来解决否定问题 也就是"不是 不包含 没有"的问题,如哪个部门没有员工,哪个员工没有老板(终极boss)
select e.first_name,m.first_name
from s_emp e left join s_emp m
on e.manager_id = m.id;
另一种语法:内连接
select t1.c1,t2.c2,t3.c3
from t1,t2
where t1.c1 = t2.c2
and t2.c4 = t3.c3
select t1.c1,t2.c2
from t1,t2
where t1.c1 = t2.c2(+) 等价于 t2.c2(+) = t1.c1 t1是驱动表
and t2.c1 is null
基于数据库的开发 E-R图:
需求分析->设计->开发测试->实施,上线->生产系统
E: entity实体.
有共同属性的一类对象的集合.例子:客户,销售代表,订单
attribute:属性.
通过属性描述实体,区分实体.例子:名字,电话,身份证号
R:relationship关系.
描述实体和实体的关系.例子:客户订货通过客户和订单的关系来表达
语法:
实体和实体的关系从实例之间的数量关系的角度可分为1:1 1:n n:m
实体和实体之间的关系从紧密程度上分为 必须 和 可以
保证数据的一致性
通过数据库的特性或应用程序完成
数据库约束:constrains:约束.
主键(primary key),唯一键(unique key),外键(foreign key)
主键(PK): 要求唯一且非空
联合主键(pk): 多列联合唯一,联合主键任意单一列都可以重复,但是所有联合主键加起来就不能重复,每一列都
不能为null
外键(FK): 在child table上定义FK(dept_id) --> 在parent table(id) pk/uk(id)
1 先create parent table,pk uk. 再建child table
2 先 insert into parent table,再insert into child table
3 删除数据,先delete child table,再delete parent table
4 删除表,先drop child table, 再drop parent table.
表和列分别对应实体和属性
定义命名规范
还需要考虑建索引和视图等
将属性转成列
强制属性定义成非空约束
将唯一标识定义成主键
主键意为非空约束加上唯一约束
一张表上只能有一个pk,其他唯一标识定义成非空性约束且唯一
一对多关系:
一的那一边定义成(pk)或唯一键(UK) parent table
多的那边定成 child table 外键(FK) FK可以为空 要实现必须 还得加非空约束
一对一关系:在外键(FK)列上增加唯一约束(UK)
若 一对一关系在两头都是可选的,任意一边定义成fk
若 一对一关系中有一边是强制的,将其定义成外键(FK)
一对一的例子:
1. 合表 好处 查询容易 不用表链接
2. 分表 好处 可以单独取出一边的信息
对于强制关系:在外键FK上定义非空约束
多对多关系:再加一张表,如 学生选课表 里面有 sid(学生id) cid(课程id) 成绩等.. 将sid和cid定义成uk,
并且把sid定义成fk,cid也定义成fk.多对多用 m:1和1:n实现m:n
多对多的例子:
student (id,name..)
pk (id)
name not null
course(id,name..)
pk(id)
name not null
stu_cou(sid,cid,grade)
pk(sid,cid)
fk(sid) ---> student(id)
fk(cid) ---> course(id)
NF用来最小化数据冗余,减少完整性问题 标识丢失的实体,关系,表
1NF: 有PK就叫1NF,列不可再分
2NF: 所有的非主属性必须完全依赖于主属性,例如:pk(sid,cid) grade(完全依赖) cname(部分依赖,只依赖于cid),
不符合第二范式, 联合主键 有时出现 部分依赖 不满足2NF
3NF: 每个非主属性不能依赖于另外一个非主属性,如:PK(sid) c_id(班id) c_name(班名称), c_name->c_id,不符合
第三范式 把一对多关系合表,不符合第三范式
数据类型:
VARCHAR2 和 CHAR
NUMBER:
不指定宽度 :
38位
指定宽度 :
number(6)
number(4,2) 总共4位,小数占两位
number(3,-3) 正数表示范围是1000-999000
number(2,4) 小数以后4位 只能添两位 最大数是0.0099
DATE:
日期类型不能定义宽度
alter session set nls_date_format = 'yyyy mm dd hh24:mi:ss';
yyyy:
mm
dd
hh24
h12
mi
ss
d用数字表示一周的第几天
day: 用全拼表示星期几(sunday..)
month:用全拼表达的月(march)
ddd:一年的第几天
YY 和 RR: 存储都是四位年,如果用两位年进行输入 用yy格式输入 例如: 99 'yyyy' 就变成当前世纪 2099年
rr:不指定格式就是rr,rr按前50年 后50年区分
尽量不要是用两位年进行插入年份
months_between('01-sep-95','11-JAN-94')
add_months('11-JAN-94',6)
next_day('01-SEP','')
last_day(sysdate) 一个月最后一天,小时 分钟 秒 保留当前
next_day(sysdate,'Friday') 今天之后最先出现的Friday 的年月日和当前时分秒
sysdate = 1995-5-25
round 四舍五入,里边 sysdate 不能换成 '01-JAN-09' 不能转成日期
round(sysdate,'MONTH') -> 01-JUN-95
round(sysdate,'year') -> 01-JAN-95
trunc 舍,里边 sysdate 不能换成 '01-JAN-09' 不能转成日期
trunc(sysdate,'MONTH')
trunc(sysdate,'YEAR')
(DDL) create(创建) drop(删除) alter(更新)
一.主键约束: primary key 唯一非空 只能有一个
可以用列级约束和表级约束完成,效果一样
列级约束: c1 number constraints pk_name(给主键起名字) primary key,
表级约束: c1 number, constraints pk_name(给主键起名字) primary key(c1),
二.联合主键约束:primary key(c1,c2) 联合唯一 联合的每列非空 只能有一个
只能用表级约束完成,例如:
create table ren (
c1 number ,
c2 number,
c3 number,
constraints ren_pk primary key(c1,c2));
不能使用列级约束完成:
create table ren (
c1 number constraints name1 primary key,
c2 number constraints name2 primary key,
c3 number,);
不能有两个主键,报错
三.外键约束:foreign key
可以使用列级约束或者表级约束
列级约束:
create table ren_parent(
c1 number(4) constraints parent_c1_pk primary key);
create table ren_child(
c1 number(3) constraints child_c1_pk primary key,
c2 number(4) constraints child_c2_fk references ren_parent(c1) [on delete cascade]);
注: 1创建表必须先建父表,再建子表.不然会报错
2删除先删除子表,才能删除父表,不然会报错
3或者删除的时候是用 drop table ren_parent cascade constraints;先解除父子表之间的主
外键关系再删除父表,子表还存在,数据也在,父子表之间的主外键关系被删除了,子表自己的主键
还在.
表级约束:
create table ren_parent(
c1 number(4) constraints parent_c1_pk primary key);
create table ren_child(
c1 number(3) constraints child_c1_pk primary key,
c2 number(4),
constraints child_c2_fk foreign key(c2)
references ren_parent(c1) [on delete cascade])
比列级约束多了一个foreign key(c2)字段,就是指定c2属性是父表c1属性的外键
建子表的子外键关系时,加上 on delete cascade,级联删除,当 delete 父表的数据时,先删除子表中引
用了这条记录的记录,再删除父表的数据
on delete set null
Oracle 不支持 on update cascade 但是别的关系型数据库支持
四.唯一约束: unique
可以使用列级约束或表级约束
列级约束:
create table ren(
c1 number(4) constraints ren_c1_pk primary key,
c2 number constriants ren_c2_uk unique,
c3 number constriants ren_c3_uk unique,
)
表级约束:
create table ren(
c1 number(4) constraints ren_c1_pk primary key,
c2 number,
c3 number,
constriants ren_c2_uk unique(c2),
constriants ren_c3_uk unique(c3),
)
五.联合唯一:unique(c1,c2)
constriants ren_c3_uk unique(c2,c3),
c2可以不唯一
c3可以不唯一
但是 c2 和 c3 加一块 必须唯一
六:检查约束: check(c1>100)
可以使用列级约束和表级约束
列级约束:
create table ren(
c1 number constraints ren_c1_ck check(c1>100))
表级约束
create table ren(
c1 number,
constraints ren_c1_ck check(c1>100))
七:非空约束:not null
执行脚本:
不在sqlplus环境中
sqlplus username/password @test.sql
在sql环境中
使用 @test.sql
@ 只在当前cd目录中找,或者使用绝对路径
根据子查询创建表并且插入数据
create table emp_41
as
select id,first_name,title,salary,dept_id
from s_emp
where dept_id = 41;
drop table table_name;--删除表
drop table table_name cascade constraints;--去除FK 删除表
alter table emp_41 --给已经存在的表追加约束
add constraints emp_41_id_pk primary key(id);
--------------------------------------------------------------------------------------
(DML) insert(插入) delete(删除) update(更新)
一.insert
insert into table_name values(
)
二.update
update ren_child
set c2 = 1,
where c2 is null;
1 update ren_emp e
2 set ann_sal = (select ann_sal*(1+commission_pct/100)
3 from ren_emp_comm c
4 where e.id = c.id)
5 where exists(select * from ren_emp_comm c
6 where e.id = c.id);
三.delete
delete table_name
where
--------------------------------------------------------------------------------------
事务
DDL 语句自动提交
锁:
DML锁: tx锁(事务锁,行级锁) 类型为x锁
tm锁(意向锁,表级锁) 属于一种
回滚: 回滚段(rollback segment)
t1表和t2表做内连接,连接条件为on t1.c1 = t2.c2,
假设t1表做驱动表,t2表做匹配表,记录的匹配过程如下:
1、从t1表中读取第一条记录r1,若它的c1值为1
2、根据该值到t2表中查找匹配的记录,即需要遍历t2表,从t2表中的第一条记录开始,若该记录(r1)的c2列的值=1,我们就说这两条记录能够匹配上,那么t1的r1和t2的r1组合起来,作为结果集里的一条记录,否则不能组合起来,即被过滤掉。
3、按照方法2依次将t2表中所有的记录检测一遍,只要匹配就放入结果集中
4、从t1表中读取第二条记录,依次重复步骤2和3,产生最终的结果集
t1表和t2表做内连接,连接条件为on t1.c1 = t2.c2,
假设t1表做驱动表,t2表做匹配表,记录的匹配有如下三
种情况:
1、t1表中的某条记录在t2中找不到任何一条匹配的记录,那么t1表中的该记录不会出现在结果集中
2、t1表中的某条记录在t2表中只有一条匹配的记录,那么t1表中的该记录和t2表中匹配的记录组合成新记录出现在结果集中
3、t1表中的某条记录在t2表中有多条匹配的记录,那么t1表中的该记录会和t2表中每一条匹配的记录组合成新记录出现在结果集中
4、内连接的核心为任何一张表里的记录一定要在另一张表中找到匹配的记录,否则不能出现在结果集中
t1表和t2表做内连接,连接条件为on t1.c1 = t2.c2
有两种方式都能得到结果集记录
1、一种t1表做驱动表,t2表做匹配表
2、另一种t2表做驱动表,t1表做匹配表
3、无论哪种方式最终得到的结果集都一样,所不同的是效率
t1表和t2表做外连接,连接条件为
from t1 left outer join t2 on t1.c1 = t2.c2,
t1表必须做驱动表,t2表做匹配表,记录的匹配过程如下:
1、从t1表中读取第一条记录r1,若它的c1值为1
2、根据该值到t2表中查找匹配的记录,即需要遍历t2表,从t2表中的第一条记录开始,若该记录(r1)的c2列的值=1,我们就说这两条记录能够匹配上,那么t1的r1和t2的r1组合起来,作为结果集里的一条记录,否则不能组合起来,即被过滤掉。
3、按照方法2依次将t2表中所有的记录检测一遍,只要匹配就放入结果集中,若扫描完后,t1的r1记录在t2表中找不到任何匹配的记录,t2表中模拟一条null记录与t1表中r1组合起来,放入结果集中
4、从t1表中读取第二条记录,依次重复步骤2和3,产生最终的结果集
t1表和t2表做外连接,连接条件为
from t1 left outer join t2 on t1.c1 = t2.c2,
t1表必须做驱动表,t2表做匹配表,
1、外连接的结果集=内连接的结果集+t1表中匹配不上的记录和一条null记录的组合
2、外连接的核心可以将匹配不上的记录找回来,即一个都不能少
t1表和t2表做外连接,连接条件为
from t1 right outer join t2 on t1.c1 = t2.c2,
t2表必须做驱动表,t1表做匹配表,
1、外连接的结果集=内连接的结果集+t2表中匹配不上的记录和一条null记录的组合
t1表和t2表做外连接,连接条件为
from t1 full outer join t2 on t1.c1 = t2.c2,
t2表必须做驱动表,t1表做匹配表,
外连接的结果集=内连接的结果集+t2表中匹配不上的记录和一条null记录的组合+t1表中匹配不上的记录和一条null记录的组合
根据GROUP BY子句指定的表达式,将要处理的数据(若有WHERE子句即为通过条件过滤后的数据)分成若干组,每组有唯一的组标识,组内有若干条记录,根据SELECT后面的组函数对每组的记录进行计算,每组对应一个返回值
where和having的区别
WHERE子句过滤的是行(记录)
HAVING子句过滤的是分组以后的聚合结果
WHERE子句包含单行函数
HAVING子句只能包含GROUP BY后面的表达式和组函数
WHERE子句执行在前,HAVING子句执行在后
WHERE子句和HAVING子句都不允许用列别名
先执行子查询,子查询的返回结果作为主查询的条件,再执行主查询。
子查询只执行一遍
若子查询的返回结果为多个值,ORACLE会去掉重复值之后,再将结果返回给主查询
关联子查询采用的是循环(loop)的方式,执行步骤如下:
1 外部查询得到一条记录(查询先从outer表中读取数据)并将其传入到内部查询。
2 内部查询基于传入的值执行。
3 内部查询从其结果中把值传回到外部查询,外部查询使用这些值来完成其处理,若符合条件,outer表中得到的那条记录就放入结果集中,否则放弃,该记录不符合条件。
4 重复执行步骤1-3, 直到把outer表中的所有记录判断一遍。
EXISTS采用的是循环(loop)方式,判断outer表中是否存在记录只要在inner表中找到一条匹配的记录即可。
1 外部查询得到一条记录(查询先从outer表中读取数据)并将其传入到内部查询的表。
2 对inner表中的记录依次扫描,若根据条件存在一条记录与outer表中的记录匹配,立即停止扫描,返回true,将outer表中的记录放入结果集中,若扫描了全部记录,没有任何一条记录符合匹配条件,返回false ,outer表中的该记录被过滤掉,不能出现在结果集中。
3 重复执行步骤1-2, 直到把outer表中的所有记录判断一遍。
NOT EXISTS采用的是循环(loop)方式,判断在outer表中是否不存在记录,它能在inner表中能找到匹配的记录。
1 外部查询得到一条记录(查询先从outer表中读取数据)并将其传入到内部查询的表。
2 对inner表中的记录依次扫描,若根据条件存在一条记录与outer表中的记录匹配,立即停止扫描,返回false, outer表中的该记录被过滤掉,不能出现在结果集中,若扫描了全部记录,没有任何一条记录符合匹配条件,返回true,将outer表中的记录放入结果集中。
3 重复执行步骤1-2, 直到把outer表中的所有记录判断一遍。
EXISTS是用循环(loop)的方式,由outer表的记录数决定循环的次数,对于exists影响最大,所以,外表的记录数要少
IN先执行子查询,子查询的返回结果去重之后,再执行主查询,所以,子查询的返回结果越少,越适合用该方式
事务的特性:ACID
原子性(atomic):一个事务要么完全发生、要么完全不发生
一致性(consistent):事务把数据库从一个一致状态转变到另一个状态
隔离性(isolated):在事务提交之前,其他事务觉察不到事务的影响
持久性(durable):一旦事务提交,它是永久的
数据库应用程序中最常用的隔离级别
Read committed
一个事务只可以读取在事务开始之前提交的数据和本事务正
在修改的数据。
在开发多用户、数据库驱动的应用程序中,关键性的挑战之一是要使并行的访问量达到最大化,同时还要保证每一个用户可以以一致的方式读取并修改数据。
锁(lock)机制
用来管理对一个共享资源的并行访问
多版本一致读
非阻塞查询:写不阻塞读,读不阻塞写
一致读查询:在某一时刻查询产生一致结果
排他锁
如果一个对象上加了X锁,在这个锁被采用commit或rollback
释放之前,该对象上不能施加任何其他类型的锁
共享锁:
如果一个对象被加上了S锁,该对象上可以加其他类型的S锁,但
是,在该锁释放之前,该对象不能被加任何其他类型的X锁
为确保并发用户能正确使用与管理共享资源,如表中的记录,oracle引进锁机制
DML锁:用于保护数据的完整性
TX锁,即事务锁(行级锁),类型为X锁
TM锁,即意向锁(表级锁),属于一种S锁
DDL锁:用于保护数据库对象的结构(例如表、索引的结构定义)
X类型的DDL锁,这些锁定防止其他会话自己获得DDL锁定或
TM(DML)锁定。这意味着可以在DDL其间查询一个表,但不
可以以任何方式进行修改
全表扫描FTS(Full Table Scan)
高水位线:曾经包含数据的最右边的块
将扫描高水位线以下的所有数据块
通过rowid来扫描数据
Rowid:标识一条记录的物理位置
包含如下信息:
该记录属于哪张表的(哪个数据库对象):object_id
该记录在哪个数据文件里:file_id
该记录在数据文件的第几个数据块里:block_id
该记录在数据块里是第几条记录:row_id
索引使用的是B*tree结构
B*tree索引由根节点(root block)、分支块(branch block)、叶子节点(leaf block)组成
根块下面是分支块,用于导航结构,包含了索引列范围和另一索引块(可以是分支块或叶子节点)的地址
最底层为叶子节点,包含索引项(index entry),索引项由key值(被索引列的值)和相应行所对应的rowid组成
索引上叶子节点实际上是双向链接的表。一旦找到叶子节点的“开始”点(一旦找到第一个值),对值进行顺序扫描(索引范围扫描)是很容易的。不必再做结构导航,只要通过叶子节点转发就行
ROWNUM是一个伪列,对查询返回的行编号即行号,由1开始依次递增
WHERE ROWNUM <= 5的执行过程
Oracle获取第一个符合条1件的行,将它叫做第1行
有5行了吗?如果没有,oracle就再返回行,因为它要满足行号
小于等于5的条件,如果到了5行,那么,oracle就不再返回行
Oracle获取下一行,并递增行号(从2,到3,再到4,等等)
返回到第2步
关键点:Oracle的rownum数值是在获取每行之后才赋予的
WHERE ROWNUM = 5的执行过程
Oracle获取第一个符合条1件的行,将它叫做第1行
有5行了吗?如果没有,oracle就再返回行,因为它要满足行号
小于等于5的条件,如果到了5行,那么,oracle就不再返回行
Oracle获取下一行,并递增行号(从2,到3,再到4,等等)
返回到第2步
哈哈,可能有点乱