Oracle SQL学习笔记或教程,教科书版级别的笔记。看完你就会了!!

select简单查询

select查询语法
-- 查询所有
-- 结构/格式  select 查询的信息 from 数据来源
-- * 表示所有,下面语句 表示 查询一张表里的所有数据
select * from 表名;
-- 查询表中的 某个字段的数据 或者列  多个字段用英文逗号隔开
select 字段名1,字段名2 from 表名;

select去重、别名和排序
-- 去重 distinct
select distinct 字段名 from 表名;
-- 别名 给 字段/列 取别名  (俩种方法如下)
select 字段 别名,字段 别名 from 表名;
select 字段 as 别名,字段 as 别名 from 表名;
-- 排序(降序) ordey by 字段 desc
select 字段 from 表名 order by 字段(要排序的字段) desc;
-- 排序(升序) ordey by 字段 asc (asc可写可不写)
select 字段 from 表名 order by 字段(要排序的字段) asc;
-- 解析顺序  from --> select --> order by

select伪列
-- 举例:表中现有员工姓名,员工月薪两个字段 实现查出来有三列数据 姓名,月薪,年薪
select 姓名字段,月薪字段,月薪*12 from 表名;
-- 以上 月薪*12 为年薪 但是表中并没有这个字段 所以称之为伪列
-- 当然 伪列 也可以取别名
select 姓名字段,月薪字段,月薪*12 as 别名 from 表名;
select null处理
-- 举例: 表中现有 工资和提成 俩个字段,实现查询结果有三列数据 工资,提成,月薪
-- 月薪 为伪列  月薪=工资+提成  但有些员工是没有提成的(null值) 
-- 对于没有提成的提成的员工来说 月薪=工资+null 这样算下来 月薪就是null了
-- 所以就要用到 nvl(exp1,res)函数处理了
-- 其中 exp1为可能为null值得字段 , res为赋值 0
select 工资字段,提成字段, 工资字段+nvl(提成字段,0) 月薪 from 表名;
-- 排序 null处理
-- nulls first 将空值放在前面
select * from 表名 order by 字段 desc nulls first;
-- nulls last 将空值放在后面
select * from 表名 order by 字段 desc nulls last;
select 拼接字符
-- 举例:现表中有 姓名 字段 要求实现查询结果为 名字+a
select 字段||'a' from 表名; 
-- 字符拼接格式: 字段||'字符' 
-- 可以将两个字段进行拼接  字段||字段
select 虚表
-- 虚表 dual  没有什么实际意义  一般用来计算
select 999*666 from dual;
-- 最终在窗口显示的就是 999x666的结果

以上为select简单查询 一般用来 查询所有数据或者某一些数据


select条件查询

条件查询结构
select 字段(查询内容) from 表名(数据来源) where 条件
-- 举例: 查询班里所有男同学的信息
select 字段 from 表名 where 性别='男';
-- 解析过程 from --> where(判断性别是否为男) --> select(将满足条件的数据放在结果集)
条件运算
-- =、>、<、>=、<=、<>、!=、^=、between and(判断这个值在不在区间之内 在A和B的中间 包含A和B) in(定值 满足什么条件  )  以上 != <>  ^= 都为不等于
select 字段 from 表名 where 字段=条件;
select 字段 from 表名 where 字段<条件;
select 字段 from 表名 where 字段>条件;
select 字段 from 表名 where 字段!=条件;
select 字段 from 表名 where 字段<>条件;
select 字段 from 表名 where 字段^=条件;
select 字段 from 表名 where 字段 between 条件 and 条件;
select 字段 from 表名 where 字段 in(A,B);
条件链接预算符
-- and(和 前后都要满足)、or(或者 前后满足一个)、not(不,或者取反)
select 查询内容 from 表名 where 条件A and 条件B;
select 查询内容 from 表名 where 条件A or 条件B;
select 查询内容 from 表名 where not 条件;
null运算符
-- is null(为空)、 is not null(不为空) 、 not...is null(不为空)
select 查询内容 from 表名 where 字段 is null;
select 查询内容 from 表名 where 字段 is not null;
select 查询内容 from 表名 where not 字段 is null;

模糊查询like
-- % (占位符,可以表示任意一个或者多个字符)  _(占位符,可以表示一个任意的字符)
-- 举例:现表中有 刘德华、刘淑芳、郭德纲 、马德华 四个同学 要求查询 所有姓刘的同学
select * from 表名 where 字段 like '刘%';
-- 举例:现表中有 刘德华、郭德纲、缺德、马德华 四个同学 要求查询 所有名字带德的同学
select * from 表名 where 字段 like '%德%';
-- 举例:现表中有 刘德华、郭德纲、缺德、马德华 四个同学 要求查询 所有名字最后一个字为华的同学
select * from 表名 where 字段 like '%华';
-- 举例:现表中有 刘德华、郭德纲、缺德、马德华、欧阳德华 四个同学 要求查询 所有名字第二个字为华的同学
select * from 表名 where 字段 like '_华%';
-- 举例:现表中有 刘德华、郭德纲、缺德、马德华、欧阳德华 四个同学 要求查询 所有名字倒数第二个字为德的同学
select * from 表名 where 字段 like '%德_';
where条件子句查询
-- 假如涉及到两张表或多张表
-- 现有 学生表(学号,姓名) 和 班级表(学号,班级) 实现结果集 姓名+班级
-- 假如要查询 3班的学生信息
select 姓名 from 学生表 where 班级=(select 班级 from 班级表 where 班级=3)
-- 子查询 between and 写法
select 数据内容 from 数据来源 where 字段 
between
(select 数据内容 from 数据来源 where 条件)
and
(select 数据内容 from 数据来源 where 条件)

函数

内置函数

单行函数
-- 单行函数:对应在表记录中,一条返回一个结果
字符函数
-- 常用的单行函数
-- concat(x.y) 链接字符串x和y
select concat(字段x,字段y) as 别名 from 表名;
-- instr(x,str,start,n)在x中查找str,可以指定从start开始,也可以指定从第n次开始
    -- 假设有一个字符串'helloword' 请找出'e'
    select instr('hellowork','e')from dual;  
    -- 假设有一个字符串'helloword' 请找出'l'
    select instr('hellowork','l')from dual;  
    -- 假设有一个字符串'helloword' 请找出第二个'l'
    select instr('hellowork','l',1,2)from dual;  
    select instr('hellowork','l',从什么位置找,找第几次出现的)from dual;  
    -- 假设找出 表中某列 并包含'A'
    select instr(字段,'A')from 表名;
-- length(x)返回x的长度
	-- 显示'hello'的字符长度
	select length('hello') from dual;
	-- 查看表中某列的所有数据的各个字符串长度
	select lenght(字段) from 表名;
	-- 将查询的内容按照字符串长度进行排序
	select lenght(字段) from 表名 order by lenght(字段);
-- lower(x)将x转换为小写
select lower(字段) from 表名;
-- upper(x)将x转换为大写
select upper(字段) from 表名;
-- ltrim(x,trim_str)把x左边截去trim_str字符串,缺省截去空格
 	-- 现有字符串'  abc  abc  ' 要去除字符串左边的空格
 	select ltrim('  abc  abc  ')from dual;
 	-- 'aaa123bbb' 去除左边的aaa
 	select ltrim('aaa123bb','aaa')from dual;
-- rtrim(x,trim_str)把x右边截去trim_str字符串,缺省截去空格
	-- 现有字符串'  abc  abc  ' 要去除字符串右边的空格
 	select rtrim('  abc  abc  ')from dual;
 	-- 'aaa123bbb' 去除右边的bbb
 	select rtrim('aaa123bb','bbb')from dual;
-- replace(x,old,new)在x中查找old,并替换为new
	-- 'abc123' 将a换成b
    select replace('abc123','a','b') from dual;
-- substr(x(字段),start(开始),length(长度))返回x的字符串,从start开始,截取length个字符,缺省length,默认到结尾
-- 'abc' 截取 bc
select substr('abc',2)from dual;
-- 'abc' 截取 b
select substr('abc',2,1)from dual;

日期函数
-- sysdate 当前系统时间
select sysdate from dual;
-- 获取后一天的时间
select sysdate+1 from dual;
-- current_date	返回当前的系统日期
select current_date from dual;
-- add_months(d1,n1) 返回在日期d1基础上再加上n1个月后新的日期
select add_months(字段,3(1~12)) from dual;
-- last_day(d1) 返回日期d1所在月份最后一天的日期
    -- 查看本地时间的月份最后一天	
    select last_day(sysdate) from dual;
    -- 查看表中某个字段的 最后一天
    select last_day(字段) from 表名;
-- months_between(d1,d2) 返回日期d1到日期d2之间的月数
select 开始时间,结束时间,months_between(结束时间,开始时间) from 表名;
-- next_day(d1,[c1]) 返回日期d1在下周,星期几(参数c1)的日期
 	-- 举例:获取当前时间点的下一个星期一是什么时候
 	select next_day(sysdate,'星期一') from dual;
 	select 字段,next_day(字段,'星期一') from 表名;
转换函数
-- to_char(x,c) 将日期或数据x按照c的格式转换为char数据类型
	-- yyyy代表年 mm代表月 dd代表天
	select to_char(字段,'mm/dd/yyyy') from 表名;
	select to_char(字段,'mm"月"dd"日"yyyy"年"') from 表名;
-- to_date(x,c) 将字符串x按照c的格式转换为日期
	-- 假如现有字符串 '1990/01/01'
	select to_date('1990/01/01','yyyy/mm/dd') from dual;
	-- 如果to_date('1990/01/01','yyyy/mm/dd')+4 其结果就是 1990/1/5
-- to_number(x) 将字符串x转化为数字型
	-- 一般用于 十六进制的转换 这里作为了解就可以
	select to_number('11','xx') from dual;
	-- 其结果集显示的17
多行函数
-- 多行函数:也称'组函数'或'聚合函数'(重点):此类函数可同时对多条记录进行操作,并返回一个结果

-- 常用的组函数
-- avg()	平均值
select avg(字段) from 表名;
-- sum()	求和
select sum(字段) from 表名;
-- min()	最小值
select min(字段) from 表名:
-- max()	最大值
select max(字段) from 表名;
-- count()	统计
select count(字段) from 表名;
-- 注意:null不参与运算  也就是说 表中某个字段 有5条数据 但是其中有两条为null 则查询出来为3

-- 去重统计
select count(distinct 字段) from 表名;
group by分组
-- 结构
select 字段 from 表名 group by 字段;
having过滤组信息
-- 结构
select 字段 from 表名 having 条件;
过滤行记录和组信息
-- 行记录的过滤是针对每条记录的筛选,组信息是针对组的筛选,是可以同时出现的,先筛选行,再过滤组,
where 筛选行,只出现行信息
having 过滤组,只能出现组信息
-- 结构 
select ... from ... where ... group by ... having...
-- from --> whrer --> group by -->having --> select

分页和去重

分页介绍

真假分页
-- 假分页
假设有100条数据,第一页就是第1条数据到第10条数据,第二页就是从第11条数据到第20条数据,是一下全部查出来的,也只用一条sql语句
好处:和数据库交互少
坏处:浪费内容
-- 真分页
发送sql语句,第一页显示10条数据。但我查询第二页的时候,我需要再次发送sql语句,去查出第1120的数据。
好处:内存少,精确
坏处:需要与数据库频繁交互
rownum分页
 -- rownum不是一个真是存在的列,它是用于从查询返回的行的编号,返回的第一行分配的是1,第二是2,以此类推,这个伪字段可以用于限制查询返回的总行数。
-- 写法结构
select 字段,rownum from 表名;
-- 实现分页
-- 假设表中有十条数据 我要进行分页 每一页显示五条数据
select 字段 from 表名 where rownum<=5;
-- 当我要显示第二页的时候(6~10)
select 字段,rownum from (select 字段,rownum 别名 from 表名) where 别名>5 and 别名<=10; 
rownum分页去除重复记录
-- rowid  介绍
-- 并不是真是存在的 属于伪列 根据每一行数据的物理地址信息编码而成的一个伪列,所以根据一行数据的rowid就能找到一行数据的物理地址信息。从而快速的地位到数据行。 数据库的大多操作都是通过rowid来完成的,而且使用rowid来进行记录定位速度是最快的。

-- 准备数据(备份)
create table 备份表名 as select * from 表名;
-- rowid 结构
select 字段,rowid from 表名;
-- 假设 表中有重复的行数据  将所有相同的记录只保留一份
	-- 实现步骤 
    -- 将数据进行分组  按照重复信息进行分组
	-- 在每一组中 选取一条记录进行保存,找到特性
	-- 删除时,找哪些不在保留范围内的数据。
	delete from 表名 where rowid not in(
    select min(rowid) from 表名 group by 字段,字段,字段;
    );
    commit;  -- 也可以按F10 进行提交
	

表连接

介绍
-- 比方说我需要从一张班级表找出山西地区的学生,在根据这个信息去成绩表里面查询他们的成绩,如果没有夺标链接,那么我们就只能手动将从第一张表中查询出来的信息,作为第二张表的检索信息去查询最后的结果。这样回显得很麻烦,过程过去繁琐

-- 链接查询
-- 1)在查询的时候同时需要多张表(特别时存在外键关系的),此时需要多张表之间的值进行链接。
-- 2)目前sql标准提出过俩种链接查询,第一种是较早的SQL92标准,第二种是目前使用广泛的较新的SQL99标准
-- 3)92形式简单,但编写较为冗(rong)长,而99不仅在底层得到优化,而且形式看上去更加一目了然,逻辑性更强,一般建议使用99标准


92语法
-- SQL92标准 写法/结构
	-- 多张表需要全部放在from之后,所有的连接条件都放在where当中。说白了 它的等值连接、非等值连接、外连接等等其实只是where条件的筛选
	-- 结构 select。。from.. 表1,表2,表3。。where.. 
	
-- 笛卡尔积
	-- 通俗来讲,就是两个集合里面的每一个成员,都与对方集合中的任意一个成员有关联
	-- 举例:假如有个考勤表,记录着100个人每月的打卡信息,理论上每个人每天都有打卡记录,但有忘记打卡,请假,旷工的。对应的就缺少了。那我们在查询的时候 不管是一天一天查还是一个人一个人的查,都会有些麻烦。在这种情况下我们就要针对每个人与每一天做一个笛卡尔积的处理,然后与实际的表去进行关联。就很容易查询出结果了。
select * from1,2 order by 字段;
等值连接
-- 在笛卡尔积的基础上取条件列相同的值 比如查询员信息和部门信息  我们要查询出部门信息,然后根据这个部门信息查询这个部门里面的所有员工信息
-- 写法
select * from1 别名1,2 别名2 where 别名1.字段 = 别名2.字段;
非等值连接
-- !=、>、<、<>、between and
-- 举例: 现有两张表 学生表(学号、姓名、成绩) 成绩表(学号、等级、最低成绩、最高成绩)
-- 要求查询 每个学生的学生等级
select 学号,姓名,成绩,成绩等级 from 学生表 别名1,成绩表 别名2 where 别名1.成绩 between 最低工资 and 最高工资;
自连接
-- 特殊的等值连接(来自于同一张表)
-- 举例: 现有一张员工表(员工编号、员工姓名、上级编号、上级信息)员工A的上级领导是上级B 但是上级B也是有上级领导C的 
-- 实现查询出结果集  格式如下:
-- 员工A编号-员工A姓名-上级B编号--上级B姓名--上级C编号--上级C姓名
select * from 员工表 别名1,员工表 别名2 where 别名1.上级编号 = 别名2.员工编号
外连接
-- 介绍:外连接可以分为左外连接(左边的表是主表)和右外连接(右边的表是主表)或者完整外部连接(可以是两张表为主表)

-- 举例:现有两张表  班级表(班级号、班级名称)  和 学生表(学生姓名和班级号)但是 班级表里有1234四个班级号 但学生表的学生都在123三个班里 也就是说4班是没有人的 现在我要统计每个班级里的学生数
-- 以上情况是内连接来做的话 其结果集只会显示123三个班的人数,而4班是不显示的  所以这个时候我们就要用到外连接了
select * from 班级表 别名1,(select count(*),班级号 from 学生表 group by 班级号) 别名2 where 别名1.班级号 = 别名2.班级号(+)
-- 以上查询出来的4班值为空
select 别名1.班级号,班级名称,nvl(别名3,0) from 班级表 别名1,(select count(*) 别名3,班级号 from 学生表 group by 班级号) 别名2 where 别名1.班级号 = 别名2.班级号(+);
-- 以上查询的结果集4班为0  利用nvl进行null处理
-- 以上带“+”的是附属表,不带“+”的是主表

99语法
-- 99与92的区别:多个字段不在用逗号隔开,而是使用关键字连接
cross join
-- 交叉连接,实现笛卡尔积
select * from1 cross join2;
natural join
-- 需要有(同名列、主外键)   必须有同名列
-- 自然连接,做等值连接 
-- 查询所有员工姓名及所在部门的名称
	-- 举例:现有两张表,学生表(学生姓名,班级编号),班级表(班级编号,班级名称)
	-- 要求查询:学生姓名、班级编号以及学生所在的班级名称
	select 学生姓名,班级编号,班级名称 from 学生表 natural join 班级表;
join using
-- 要求:两张表中必须有同样的列
-- using 连接,等值连接
	-- 举例:现有两张表,学生表(学生姓名,班级编号),班级表(班级编号,班级名称)
	-- 要求查询:学生姓名、班级编号以及学生所在的班级名称
	select 学生姓名,班级编号,班级名称 from 学生表 join 班级表 using(班级编号);
join on
-- on连接,可做等值连接、非等值连接、自连接,可以解决一切连接,关系列必须要区分
	-- 举例:现有两张表,学生表(学生姓名,班级编号),班级表(班级编号,班级名称)
	-- 要求查询:学生姓名、班级编号以及学生所在的班级名称
	select 学生姓名,班级编号,班级名称 from 学生表 join 班级表 on 学生表.班级编号 = 班级表.班级编号;	
outer join
-- 外连接,有主表和从表
-- left[outer]join on 左外连接
    -- 举例: 现有一张员工表(员工编号、员工姓名、上级编号、上级信息)员工A的上级领导是上级B 			但是上级B也是有上级领导C的 
    -- 实现查询出结果集  格式如下:
    -- 员工A编号-员工A姓名-上级B编号--上级B姓名--上级C编号--上级C姓名
    select 别名1.员工编号,别名1.员工姓名,别名1.上级编号,别名2.上级信息 
    from 员工表 别名1 left outer join 员工表 别名2 on 别名1.上级编号 = 别名2.员工编号;
-- left[outer]join using
-- right[outer]join on 右外连接
   -- 举例: 现有一张员工表(员工编号、员工姓名、上级编号、上级信息)员工A的上级领导是上级B 			但是上级B也是有上级领导C的 
    -- 实现查询出结果集  格式如下:
    -- 员工A编号-员工A姓名-上级B编号--上级B姓名--上级C编号--上级C姓名
    select 别名1.员工编号,别名1.员工姓名,别名1.上级编号,别名2.上级信息 
    from 员工表 别名2 right outer join 员工表 别名1 on 别名1.上级编号 = 别名2.员工编号;
-- right[outer]join using
full join on | using
-- 全连接,满足则直接匹配,不满足的相互补充null,确保所有的表记录都至少出现一次。
92与99的区别
-- 92标准
	-- 内连接
	select ... from1,2 where1.字段 =2.字段;
	-- 外连接
	select ... from1,2 where1.字段 =2.字段(+);
-- 99标准
 	-- 内连接(笛卡尔积、等值连接、非等值连接、自连接)
	select ... from1 cross join2 where ...;
	select ... from1 natural join2 where ...;
	select ... from1 join2 using(同名字段) where ...;
	select ... from1 join2 on 连接条件 where ...;
	-- 外连接
	select ... from1 right outer join2 on 连接条件 where ...;
	-- 全连接
	select ... from1 join2 on 连接条件 where ...;
集合操作
-- 通过一些关键字将我们的结果集进行一个拼接操作
	-- 什么时候能做集合操作?但俩个结果集 字段个数和字段类型一一对应的时候才能做集合操作
-- union 并集(去重)对两个结果集进行并集操作,不包括重复行同时进行默认规则的排序;
select 'a','b' from dual union select 'c','d' from dual;
-- union all 全集(不去重)对两个结果集进行并集操作,包括重复行,不进行排序
select 'a','b' from dual union select 'c','d' from dual union all select 'a','b' from dual;
-- intersect 交集(找出重复)对俩个结果集进行交集操作,不包括重复行,同时进行默认规则的排序
(select 'a','b' from dual union select 'c','d' from dual)
intersect
(select 'a','b' from dual union select 'e','f' from dual)
-- Minus 差集(减去重复)对俩个结果集进行差操作,不包括重复行,同时进行默认规则的排序
(select 'a','b' from dual union select 'e','f' from dual)
minus
(select 'a','b' from dual union select 'c','d' from dual)

DDL介绍

-- DDL语句:数据定义语言,这些语句定义了不同的数据段、数据库、表、列、索引等数据库对象。常用的语句关键字主要包括create、drop、alter等。
-- DML语句:数据操作语句,用于添加、删除、更新和查询数据库记录,并检查数据完整性。常用的语句关键字主要包括:insert、dalete、update和select等。
-- DCL语句:数据控制语句,用于控制不同数据段直接的许可和访问级别的语句,这些语句定义了数据库、表、字段、用户的访问权限和安全级别,主要的语句关键字包括grant、revoke等。
表操作
创建表
-- 创建新表
create table 表名(
	字段名 类型(长度),
    ...其他字段...
);
	-- 数据类型
	VARCHAR2(size) 可变长度的字符串,最大长度为size个字节;size的最大值为4000,最小值为1.必须指定
	NVARCHAR2(size)  可变长度的字符串,最大长度为size个字节;size的最大值为4000,必须指定
	NUMBER(p,s)
	LONG 可变长度的字符串,长度可大2G个字节
	DATE 有效日期范围从公元强471211日到公园后47121231日
	RAW(size)长度为size字节的原始二进制数据,size最大值为2000字节,必须指定
	LONG RAW 可变长度的原始二进制数据,长度可大2G个字节
	CHAR(size)固定长度的字符数据,其长度为size个字节,size最大为2000个字节,而最小值和默认值是1
	NCHAR(size)固定长度,根据Unicode标准定义
	CLOB 一个字符大型对象,可容纳单字节的字符,不支持宽度不等的字符集,最大为4G
	NCLOB 一个字符大型对象,可容纳单字节的字符,不支持宽度不等的字符集,最大为4G
	BLOB 一个二进制大型对象,最大4G字节
	BFILE 包含一个大型二进制文件的定位器,其存储在数据库的外面;使得可以以字符流I/O访问存在数据库服务器上的外部LOB;最大4G字节。
-- 从其他表拷贝结构
create table 表名 as select 字段列表 from 已有表 where 1!=1;
修改表结构
-- 修改表名
rename 原表名 to 新表名
-- 修改列名
alter table 表名 rename column 列名 to 新列名
-- 修改字段类型
alter table 表名 modify(字段 类型)
-- 添加列
alter 他变了 表名 add 字段 类型
-- 删除列
alter table 表名 drop column 字段
删除表
drop table 表名;

约束

-- 五种约束  (约束就是对数据更加精确的控制,更加符合实际,满足我们的需求)
主键约束(PRIMARY KRY)
唯一性约束(UNIQUE)
非空约束(NOT NULL)
外键约束(FOREIGN KEY)
检查约束(CHECK
主键约束(PRIMARY KRY)
	主键是定位表中单个行的方式,可唯一确定表中的某一行,关系型数据库要求所有表都应该有主键,不过Orcale没有遵守此范例要求,Orcale种的表可以没有主键(这种情况很少)
	1.键列必须具有唯一性,且不能为空。主键约束就相当于 UNIQUE+NOT NULL
	2.一张表只能有一个主键
	3.主键所在列必须具有索引(主键的唯一约束通过索引来实现),如果不存在,将会在索引添加的时候自动创建
唯一性约束(UNIQUE)
	唯一性约束可作用在单列或多列上,对于这些列或列组合,唯一性约束保证每一行的唯一性。
	UNIQUE需要注意:
	1.对于 UNIQUE约束来讲,索引是必须的。如果不存在,就自动创建一个( UNIQUE的唯一性本质上是通过索引来保证的)
	2.UNIQUE允许null值, UNIQUE约束的列可存在多个null。这是因为, unique 唯一性通过 btree索引来实现,而 btree索引中不包含null。当然,这也造成了在 where 语句中用null值进行过滤会造成全表扫描。
非空约束(NOT NULL)
	非空约束作用的列也叫强制列。顾名思义,强制键列中必须有值,当然键表时候若使用 default 关键字指定了默认值,则不能输入
外键约束(FOREIGN KEY)
	外键约束定义在具有父子关系的子表中,外键约束使得子表中得列对应父表的主键列,用以维护数据库的完整性。不过出于性能和后期的业务系统的扩展的考虑,很多时候,外键约束仅出现在数据库的设计中,实际会放在业务程序中进行处理。
	外键约束需注意一下几点:
	1.外键约束的子表中的列和对应父表中的列数据类型必须相同,列名可以不同。
	2.对应的附表列必须存在主键约束或唯一约束
	3.外键约束列允许 NULL值,对应的行就称了孤行。
检查约束(CHECK)
	检查约束可用来实施一些简单的规则,比如列值必须在某个范围内。检查的规则必须是一个结果为 truefalse的表达式
根据要求创建表及约束

表名:tb_user(用户表)

编号 字段名 字段类型 说明
1 userid number(5) 用户id,主键
2 username varchar2(30) 用户名,非空,4~20个字符
3 userpwd varchar2(20) 密码,非空,4~18个字符
4 age number(3) 年龄,默认18,值大于等于18
5 gender char(2) 性别,默认‘男‘,只能是男和女
6 email varchar2(30) 邮箱,唯一
7 regtime date 注册日期,默认当前日期

注意:根据系统的编码去更改字符长度 比如,utf-8编码中

create table td_user(
	userid number(5) primary key,
    username varchar2(30) check(length(username) between 4 and 20) not null,
    userpwd varchar2(20) not null check(length(userpwd) between 4 and 18),
    age number(3) default(18) check(age>=18),
    gender char(2) default('男') check(gendar in('男','女')),
    email varchar2(30) unique,
    regtime date default(sysdate)
);

表名:tb_txt(文章表)

编号 字段名 字段类型 说明
1 txtid number(5) 文章编号,主键
2 title varchar2(32) 文章标题,非空,长度为4~20字符
3 txt varchar2(1024) 内容,最大长度为1024
4 pubtime date 发布日期,默认当前日期
5 userid number(5) 作者,外键,参考用户表的用户id,删除时,自设为null
create table tb_txt(
	txtid number(5) primary	key,
    title varchar2(32) not null check(length(title)>=4 and length(title)<=30),
    txt varchar2(1024),
    pubtime date default(sysdate),
    userid number(5) references tb_user(userid) on delete set null
);
-- 还有一种方法创建约束   (了解)
create table tb_txt(
    txtid number(5),
    title varchar2(32),
    txt varchar2(1024),
    pubtime date default(sysdate),
    userid number(5),
    constraint pk_txt_id primary key,
    constraint ck_txt_title check (length(title)>=4 and length(title)<=30),
    constraint fk_txt_user_id foreign key(userid) references tb_user(userid) on delete set null
);
追加约束
-- 追加主键约束
alter table 表名 add constraint 约束名字 primary key (要加约束的字段);
-- 追加检查约束
alter table 表名 add constraint 约束名字 check(
	length(要加约束的字段) between 4 and 20
)
-- 追加非空约束
alter table 表名 modify(要加约束的字段 constraint 约束名字 not null);
-- 追加唯一约束
alter table 表名 add constraint 约束名字 unique(加约束的字段);
-- 追加默认约束
alter table 表名 modify(字段 default());
-- 追加外键约束 (强制不让删)
alter table 表名 add constraint 约束名字 foreign key(加约束的字段)references 表名2(字段)
-- 追加外键约束 (自动设为null)
alter table 表名 add constraint 约束名字 foreign key(加约束的字段)references 表名2(字段)on delete set null;
-- 追加外键约束 (级联删除)
alter table 表名 add constraint 约束名字 foreign key(加约束的字段)references 表名2(字段)on delete cascade;
修改约束
-- 修改约束 其实就去 先删除后修改
-- 先删除:
alter table 表名 drop constraint 约束名字;
-- 然后再添加约束(参考上方追加约束)
约束的启用和禁用
-- 启动/禁用(enable/disable)是否对新变更的数据启用约束验证
-- 验证/非验证(validate/novalidate)是否对表中已客观存在的数据进行约束验证
enable validate -- 默认的约束组合状态,无法添加违反约束的数据行,数据表中也不能存在违反约束的数据行
enable novalidate -- 无法添加违反约束的数据行,但对已存在的违反约束的数据行不做验证
disable validate -- 可以添加违反约束的数据行,但对已存在的违法约束的数据行会做约束验证
disable novalidate -- 可以添加违法约束的数据行,对已存在的违法约束的数据行也不做验证
删除约束
alter table 表名 drop constraint 约束名 ;

DML

DML介绍
-- DML数据操控语言,用于操作数据库对象中包含的数据,也就是说操作的单位是记录
-- Oracle数据库的DML表数据的操作有三种:
insert -- 插入:向数据库表插入一条记录
update -- 更新:删除数据表中的一条或多行的记录
delete -- 删除:用于修改已存在表中的记录的内容
DML之insert
-- 结构

-- 默认插入:数据必须和表结构里面字段顺序以及个数保持一致;当某个字段存在默认值时,也必须给出值。
insert into 表名 values(1,'值1','值2',null,sysdate);
commit; -- commit 提交事务 如果不些commit的话 那么这条数据不会立马插入到我们的表中,只是放在缓存中。
-- 如果不用默认时间就用 to_date('1990-1-1','yyyy-mm-dd')

-- 在创建表的同时,添加记录
-- 举例:现有一张表,里面存放了字段1,字段2,字段3,字段4.现在我要创建一张新表,发现新表需要存储的记录,在老表中有。
create table 新表明 as select 字段1,字段2,字段3 from 老表名;

-- 从其他数据表中拷贝数据进来(假设我要在我的新表里面插入数据,发现这些数据在老表中就有存储)
insert into 新表 value(select 字段 from 老表 where 条件);-- 没有条件可以省略 或者1=1


-- 在添加时指定列和顺序
	-- 假设 我表中有 五个字段 字段1,字段2,字段3,字段4,字段5;但是我现在只想给 字段1,字段3,字段5中添加数据
	insert into 表名(字段1,字段3,字段5)values('值','值','值');
	-- 以上的字段的顺序可以随意颠倒,但values中的值就要跟着前面的字段顺序去写入
	-- 如果某些字段,值可以为null或者有默认值,此时我们可以不指定。(例如:上方中我的字段2和字段4就有默认值或者可以为null)
	-- 如果某个字段有默认值,则未指定时使用默认值填充
	-- 如果某个字段没有默认作,但可以为null,未指定时,则使用null填充
	-- 如果某个字段既可以为null,又有默认值,若未指定,则使用默认值填充,想要设为null,必须手动指定。
	
	
	-- 同过指定列的方式,同其他表中查询数据,添加到表中
	insert into 表名1(字段1,字段2,字段3)(select 字段1,字段2,字段3 from 表名2 where 条件)
	-- 此时就不需要哪个字段跟哪个字段对应了,只要字段的数据类型兼容就可以插入
	
	-- 在添加的记录中,存在外键关联时需要注意,可以采取想查询后添加的方式。如下:
	insert into 表名1(字段1,字段2,字段3)values(01,'刘德华',(select 字段3 from 表名2 where 条件));

DML之update
-- 通过update语句可以更新(修改)表中的记录值。
update 表名 set 字段1=1 where 条件;
-- 以上就是update的语法结构,当需要更新多个字段值时需用逗号隔开。

-- 也可以先列出需要修改的字段,通过查询子句设定。如下:
update 表名1 set(字段1,字段2)=(select '值1','值2' from dual) where 条件;

DML之delete
-- 通过delete语句可以删除表中的记录;语法结构如下:
delete from 表名1 where 条件;

-- 当两张表存在主外键关系时,如果删除主表(被参考的表)中被引用(被参考)的记录时会出现以下三种情况:(参考上面的追加外键约束)
	-- 如果默认外键处理方式,强制不让删
	-- 如果是 on delete cascade 一起删除
	-- 如果是 on delete set null 自动设为null

猜你喜欢

转载自blog.csdn.net/Hao1999_/article/details/118737711