资源介绍
1 SQL基础
1.1 基本概念
结构化查询语言(Structured Query Language)简称SQL,是一种关系数据库查询语言,用于存取数据以及查询、更新和管理关系数据库系统。
1.2 语句结构
1.2.1 数据查询语言(DQL)
对数据库进行的信息查询,select。
1.2.2 数据操作语言(DML)
用于操作关系型数据库对象内部的数据,insert、update、delete。
1.2.3 数据定义语言(DDL)
用来建立及定义数据表、字段以及索引等数据库结构,create、alter、drop 。
1.2.4 数据控制语言(DCL)
用于控制对数据库里数据的访问,通常用于创建与用户访问相关的对象以及控制用户的权限,grant、revoke(撤销)。
1.2.5 事务控制命令(TPL)
用于管理数据库事务,commit、rollback、savepoint(在一组事务里创建标记点以用于回退)。
1.3 表的构成
1.3.1 字段
字段是表里的一列,用于保持每条记录的特定信息
1.3.2 记录
记录,也被成为一行数据,是表里的每一行
1.4 完整性的约束条件
1.4.1 实体完整性
关系模型的实体完整性在create table中用primary key约束实现,primary key约束用于定义主键,它保证主键的唯一性和非空性。
1.4.2 参照完整性
关系模型的参照完整性可以通过在create table中用foreign key (<外键>) references <被参照表名> (<与外键对应的主键名>)进行约束定义。
1.4.3 用户定义完整心
在create table语句中可以根据应用要求,定义属性以及元组上的约束。
常见的用户定义的完整性约束有:
not null或null约束。
unique约束:唯一性约束。
default约束:默认值约束。
check约束:检查约束,check约束通过约束条件表达式设置列值应该满足的条件。
1.5 范式
1.5.1 第一范式
1.5.1.1 规范
无重复的列,确保每列保持原子性,即数据库表中的所有字段值都是不可分解的原子值。
1.5.1.2 举例
姓名 年龄 联系电话 地址
省 市 详细地址
1.5.2 第二范式
1.5.2.1 规范
属性完全依赖于主键,确保表中每列都与主键相关。
1.5.2.2 举例
订单表 订单Id 商品Id 总金额 商品名称
001 1 10 苹果
001 2 10 橘子
联合主键订单Id、商品Id =>
商品表 商品Id 商品名称 单价
订单表 订单Id 总金额
1.5.3 第三范式
1.5.3.1 规范
属性不依赖于其它非主属性,确保数据表中的每一列数据都和主键直接相关,而不能间接相关,即要求一个数据库表中不包含已在其它表中已包含的非主关键字信息。
1.5.3.2 举例
党员表 党员Id 党员姓名 组织Code 符合3NF
党员表 党员Id 党员姓名 组织名称 不符合3NF
组织表 组织Code 组织名称
1.6 外连接
1.6.1 准备
create table student_A(
uuid varchar2(32),
name varchar2(100));
create table student_B(
uuid varchar2(32),
name varchar2(100));
insert into student_A values('1','小黄');
insert into student_A values('2','小黑');
insert into student_A values('3','小红');
insert into student_B values('1','大黄');
insert into student_B values('2','大黑');
insert into student_B values('4','大红');
insert into student_B values('4','大紫');
1.6.2 左连接(left join)
1.6.2.1 说明
查询指定的左表的所有行,而不仅仅是联接列所匹配的行;如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值。
1.6.2.2 语法
select A.*,B.*
from student_A A left join student_B B on A.Uuid = B.Uuid;
1.6.2.3 结果
1.6.2.4 (+)表示
select A.*,B.*
from student_A A,student_B B
where A.Uuid = B.Uuid(+)
1.6.3 右连接(right join)
1.6.3.1 说明
查询指定的右表的所有行,而不仅仅是联接列所匹配的行;如果右表的某行在左表中没有匹配行,则在相关联的结果集行中左表的所有选择列表列均为空值。
1.6.3.2 语法
select A.*,B.*
from student_A A right join student_B B on A.Uuid = B.Uuid;
1.6.3.3 结果
1.6.3.4 (+)表示
select A.*,B.*
from student_A A,student_B B
where A.Uuid(+) = B.Uuid
1.6.4 全外连接(full outer join)
1.6.4.1 说明
完整外部联接返回左表和右表中的所有行;当某行在另一个表中没有匹配行时,则另一个表的选择列表列包含空值;如果表之间有匹配行,则整个结果集行包含基表的数据值。
1.6.4.2 语法
select A.*, B.*
from student_A A full outer join student_B B on A.Uuid = B.Uuid;
1.6.4.3 结果
1.6.4.4 全外连接不支持(+)写法
1.6.5 (+)
+ 表示补充,即哪个表有加号,这个表就是匹配表。
1.7 运算符
1.7.1 比较
=、>,<,>=,<=,!=,<>,
1.7.2 确定范围
between and 、not between and
1.7.3 确定集合
in、not in
1.7.4 字符匹配
like(“%”匹配任何长度,“_”匹配一个字符)
1.7.5 转义字符
1.7.5.1 常规转义字符
“\”转义字符,“\%”则表示单纯的字符“%”
1.7.5.2 escape
escape关键字经常用于使某些特殊字符,如通配符:'%','_'转义为它们原来的字符的意义,被定义的转义字符通常使用'\',但是也可以使用其他的符号。
select * from Student_a where name like '%$%%' escape '$';
1.7.6 空值
is null、is not null
1.7.7 集合查询
union(并)、intersect(交)、minus(差)
1.7.8 多重条件
and、or、not
1.7.9 对查询结果分组
1.7.10 分组筛选条件
[having <条件表达式>]
1.7.11 字符串拼接
select 'A' || 'B' from dual; // || 拼接
1.8 函数
1.8.1 聚集函数
count、sum、avg、max、min
1.8.2 case when
1.8.2.1 语法
select t.uuid,
t.score,
case
when t.score > 90 then '优秀'
when t.score > 60 then '及格'
else '不及格'
end
from exam_user_exam t
1.8.3 decode
1.8.3.1 语法
select decode(x,1,'x is 1', 2 , 'x is 2','others') from dual
1.8.3.2 说明
当x等于1时,则返回‘x is 1’,当x等于2时,则返回‘x is 2’,否则,返回‘others’。
1.8.4 nulls first(nulls last)排序
1.8.4.1 语法
select * from dy_info t order by t.degree nulls first
1.8.4.2 说明
控制null显示行位置
1.8.5 Nvl
1.8.5.1 语法
select nvl(t.sap,'空') from dy_info t;
1.8.5.2 说明
如果sap号为空,则返回‘空’,否则返回sap号。
1.8.6 递归查询
1.8.6.1 语法
select t.*
from g_organ t
start with t.organcode = '080'
connect by prior t.parentcode = t.organcode; //递归查询父节点
select t.*
from g_organ t
start with t.organcode = '080'
connect by t.parentcode = prior t.organcode; //递归查询子节点
1.8.7 union 和 union all
1.8.7.1 语法
select * from dual
union all
select * from dual
1.8.7.2 说明
union 会对查询数据进行去重并排序,union all只是简单的将两个结果合并。
1.8.8 wm_concat
1.8.8.1 语法
select wm_concat(t.role_name) from g_role t where t.role_name like '%书记%'
1.8.8.2 说明
拼接字符串,结果为:‘党工委副书记,总支副书记,党支部书记,党委书记,党委副书记,党总支书记,党工委书记,党总支副书记,党支部副书记’
1.8.9 相似度
1.8.9.1 语法
select utl_match.edit_distance_similarity('aaaaa','bbaaaa') from dual;
1.8.10 去格式
1.8.10.1 oracle正则表达式:去除<>>格式
select REGEXP_REPLACE(title,'<[^>]*>','') title from exam_question
1.8.11 rank() over (partition by …)
1.8.11.1 语法
select organcode,score,ranknum
from (
select t.organcode,
t.score,
rank() over (partition by t.organcode order by t.score desc) ranknum
from exam_user_exam t)
where ranknum < 4
1.8.11.2 说明
获取每个组织,考试成绩前三名。
1.9 存储过程
1.9.1 定义
存储过程是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中。用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。
1.9.2 准备
create table t_user
(
username varchar2(20),
password varchar2(20)
);
create table t_user_temp
(
username varchar2(20),
password varchar2(20)
);
insert into t_user(username,password) values('小王','1111');
insert into t_user(username,password) values('小李','1111');
1.9.3 创建存储过程
create or replace procedure adduser as
begin
insert into t_user_temp(username,password)
select username,password
from t_user t
where t.username = '小李';
end adduser;
1.9.4 执行
begin adduser;
end;
1.9.5 验证
select * from t_user;
select * from t_user_temp
2 SQL深入
2.1 常用
2.1.1 表空间
2.1.1.1 创建表空间
create tablespace TS_DJY datafile 'd:/software/oracle/tablespace/ts_djy.dat' size 1024M autoextend on next 100M maxsize 2048M;
2.1.1.2 指定用户表空间
alter user cssdj default tablespace TS_DJY;
2.1.1.3 指定表的表空间
create table t_student(
uuid varchar2(32)
)tablespace TS_DJY;
2.1.2 自增sequence
2.1.2.1 创建
create sequence seq_student_uuid
minvalue 1
maxvalue 999999999999999
start with 1
increment by 1
nocache;
2.1.2.2 使用
select seq_student_uuid.nextval from dual; //获取下一个
select seq_student_uuid.currval from dual; //获取当前
2.1.3 批量插入
2.1.3.1 查询结果批量插入
insert into tablea(cola,colb) select cola,colb from tableb;
2.1.3.2 创建相同的表结构并插入数据(备份表数据)
create tab_new as select * from tab_old;
2.1.3.3 创建相同的表结构不插入数据
create tab_new as select * from tab_old where rownum=0;
2.1.4 伪列伪表
2.1.4.1 伪列
伪列不是表的真实列,但是你可以象使用真实列一样使用伪列,常用伪列:rowid行的绝对物理编号,每一行是唯一的。rownum序号,返回查询结果的每行序号。系统时间sysdate,返回系统当前时间。
2.1.4.2 伪表
select * from dual;
2.1.5 系统表
2.1.5.1 user_tables
当前用户表信息
2.1.5.2 user_tab_columns
当前用户表所有列信息,搜索列所在的表:
select * from user_tab_columns t where t.column_name like '%ORGANCODE%';
2.1.5.3 user_tablespaces
当前用户表空间
2.1.5.4 dba_users
数据库所有用户
2.1.5.5 dba_tables
数据库所有表
2.1.5.6 dba_tablespaces
数据库所有表空间
2.1.6 锁表解锁
2.1.6.1 查看锁表信息
select l.OBJECT_ID,s.SID,s.SERIAL#,s.USERNAME, s.MACHINE
from V$locked_Object l,V$session s
where l.SESSION_ID = s.SID;
2.1.6.2 解锁
alter system kill session 'sid,serial#';
2.1.7 备份与恢复
2.1.7.1 导出
导出用户:
exp cssdj/cssdj@zr owner=(cssdj,cssdj_zsy) file=d:/cssdj.dmp log=d:/cssdj.log
导出用户表:
exp cssdj/cssdj@zr tables=(g_dict,g_dict_item) file=d:/cssdj.dmp log=d:/cssdl.log
2.1.7.2 导入
imp cssdj/cssdj@zr fromuser=cssdj_zsy touser=cssdj file=d:/cssdj.cmp log=d:/cssdj.log
2.1.7.3 数据泵
2.1.8 Dblink
2.1.8.1 创建
create database link orcllink
connect to cssdj identified by cssdj using
'(DESCRIPTION = (ADDRESS_LIST= (ADDRESS=(PROTOCOL = TCP)(HOST = 219.239.110.65)(PORT = 1521))) (CONNECT_DATA=(SID = orcl)))';
2.1.8.2 删除
drop database link orcllink;
2.1.8.3 使用
select * from dy_info@orcllink;
2.2 Oracle与Mysql差异
2.2.1 Group by
2.2.1.1 Oracle
select后面出现的列,如果没有使用集合函数,必须出现在group by 中。
select sno,sname,sum(grade) from student
group by sno,sname; //合法写法
select sno,sname,sum(grade) from student
group by sno; //非法写法
select sno,min(sname),sum(grade) from student
group by sno; //建议用这种写法,效率高些
2.2.1.2 Mysql
select sno,sname,sum(grade) from student
group by sno,sname; //合法写法
select sno,sname,sum(grade) from student
group by sno; //合法写法
2.2.2 分页
2.2.2.1 Oracle
使用rownum来表明分页位置,而且rownum只能小于某值,不能大于某值,故而rownum和where联用才能完成数据范围的控制
2.2.2.2 Mysql
mysql的分页可以用limit startNum,pageNum
2.3 了解
2.3.1 事务
2.3.1.1 Rollback
start transaction; --开始事务
insert into g_dict values('test','测试','1',''); --执行数据操作语言(DML)
select * from g_dict where code = 'test'; --可以查看是否执行正确
rollback; --错误执行rollback操作
commit; --正确执行commit操作
2.3.1.2 Savepoint
start transaction; --开始事务
insert into g_dict values('t1','测试','1',''); --执行数据操作语言(DML)
savepoint pointA;
insert into g_dict values('t2','测试','1',''); --执行数据操作语言(DML)
select * from g_dict where code = 'test33'; --可以查看是否执行正确
rollback to savepoint pointA;
2.3.2 利用执行计划评估SQL语句的性能
2.3.2.1 工具
在PL/SQL Developer中写好一段SQL代码后,按F5,PL/SQL Developer会自动打开执行计划窗口,显示该SQL的执行计划。
2.3.2.2 查看总COST,获得资源耗费的总体印象
一般而言,执行计划第一行所对应的COST(即成本耗费)值,反应了运行这段SQL的总体估计成本,单看这个总成本没有实际意义,但可以拿它与相同逻辑不同执行计划的SQL的总体COST进行比较,通常COST低的执行计划要好一些。
2.3.2.3 了解执行计划的执行步骤
按照从左至右,从上至下的方法,了解执行计划的执行步骤;
执行计划按照层次逐步缩进,从左至右看,缩进最多的那一步,最先执行,如果缩进量相同,则按照从上而下的方法判断执行顺序,可粗略认为上面的步骤优先执行。每一个执行步骤都有对应的COST,可从单步COST的高低,以及单步的估计结果集(对应ROWS/基数),来分析表的访问方式,连接顺序以及连接方式是否合理。
2.3.2.4 分析表的访问方式
表的访问方式主要是两种:全表扫描(TABLE ACCESS FULL)和索引扫描(INDEX SCAN),如果表上存在选择性很好的索引,却走了全表扫描,而且是大表的全表扫描,就说明表的访问方式可能存在问题;若大表上没有合适的索引而走了全表扫描,就需要分析能否建立索引,或者是否能选择更合适的表连接方式和连接顺序以提高效率。
2.3.2.5 分析表的连接方式和连接顺序
表的连接顺序:就是以哪张表作为驱动表来连接其他表的先后访问顺序。
表的连接方式:简单来讲,就是两个表获得满足条件的数据时的连接过程。主要有三种表连接方式,嵌套循环(NESTED LOOPS)、哈希连接(HASH JOIN)和排序-合并连接(SORT MERGE JOIN)。我们常见得是嵌套循环和哈希连接。
嵌套循环:最适用也是最简单的连接方式。类似于用两层循环处理两个游标,外层游标称作驱动表,Oracle检索驱动表的数据,一条一条的代入内层游标,查找满足WHERE条件的所有数据,因此内层游标表中可用索引的选择性越好,嵌套循环连接的性能就越高。
哈希连接:先将驱动表的数据按照条件字段以散列的方式放入内存,然后在内存中匹配满足条件的行。哈希连接需要有合适的内存,而且必须在CBO优化模式下,连接两表的WHERE条件有等号的情况下才可以使用。哈希连接在表的数据量较大,表中没有合适的索引可用时比嵌套循环的效率要高。
2.3.3 优化器
Oracle优化器分为基于规则的优化器(RBO)和基于代价的优化器(CBO)。
2.3.3.1 规则的优化器(RBO)
RBO的优化方式,依赖于一套严格的语法规则,只要按照规则写出的语句,不管数据表和索引的内容是否发生变化,不会影响PL/SQL语句的"执行计划"。
2.3.3.2 基于代价的优化器(CBO)
CBO计算各种可能"执行计划"的"代价",即cost,从中选用cost最低的方案,作为实际运行方案。各"执行计划"的cost的计算根据,依赖于数据表中数据的统计分布,ORACLE数据库本身对该统计分布是不清楚的,须要分析表和相关的索引,才能搜集到CBO所需的数据。
2.3.4 表分析analysis
2.3.4.1 说明
analyze table,一般可以指定分析表、所有字段、所有索引字段、所有索引,若不指定则全部都分析。
2.3.4.2 表分析
analyze table dy_info compute statistics;
2.3.4.3 删除分析数据
analyze table dy_info delete statistics;
2.3.5 oracle添加强制索引
如果使用的是CBO的话,可能SQL不执行索引,则可以添加强制索引执行索引。
2.3.5.1 语法
/*+index(tablename indexname)*/
2.3.5.2 举例
select /*+index(t INDEX_SAP)*/* from dy_info t where t.sap = 'T6000890'