嗨,大家好啊
情人节来了,有点慌,我要怎样才能好装出有女朋友的样子呢?
福利:今天,码歌送你一个女朋友
公众号 嗨码歌 对话框回复“情人节”领取~
(温馨提示:想要女朋友的,移步到公众号领取,另一定要一个人偷偷的听或者戴上耳机)
先把我们未完成的Oracle系列看完,然后再去找女朋友,岂不是爱情事业双丰收。
第七章 DDL语法7.1 DDL介绍
SQL语句主要可以划分为以下3个类别DDL(Data Definition Languages)
语句:数据定义语言,这些语句定义了不同的数据段、数据库、表、列、索引等数据库对象。常用的语句关键字主要包括create
、drop
、alter
等。DML(Data Manipulation Languages)
语句:数据操纵语句,用于添加、删除、更新和查询数据库记录,并检查数据完整性。常用的语句关键字主要包括insert
、delete
、update
和select
等。DCL(Data Control Language)
语句:数据控制语句,用于控制不同数据段直接的许可和访问级别的语句,这些语句定义了数据库、表、字段、用户的访问权限和安全级别,主要的语句关键字包括grant
、revoke
等。DDL
是数据定于语言的缩写,简单来说,就是对数据库内部的对象进行创建、删除、修改等操作的语言。它和DML语言的最大区别是DML只是对表内部数据操作,而不涉及表的定义,结构的修改,更不会涉及其他对象。DDL语句更多的由数据库管理员(DBA)使用,开发人员一般很少使用。DDL(data definition language)
:DDL比DML要多,主要的命令有 CREATE、ALTER、DROP等,DDL主要是用在定义或改变表(TABLE)的结构,数据类型,表之间的链接和约束等初始化工作上,他们大多在建立表时使用。
DDL(Data Definition Language,数据定义语言): 用于定义数据的结构,比如 创建、修改或者删除数据库对象。
DDL包括:DDL语句可以用于创建用户和重建数据库对象。下面是DDL命令: CREATE TABLE:
创建表 ALTER TABLE DROP TABLE:
删除表 CREATE INDEX DROP INDEX
7.1 表操作
7.1.1 创建表
1)创建新表
create table 表名(
字段名 类型(长度) ,
…其他字段…
);
2)从其他表拷贝结构create table 表名 as select 字段列表 from 已有表 where 1!=1;
7.1.2 修改表结构
1)修改表名
rename 原表名 to 新表名rename tb_txt to tb_txt_new;
2)修改列名
alter table 表名 rename column 列名 toalter tb_txt_new rename column txtid to tid;
3)修改字段类型
alter table 表名 modify(字段 类型)alter table tb_txt_new modify(tid vachar2(20));
4)添加列
alter table 表名 add 字段 类型alter table tb_txt_new add col_test_name varchar2(30);
5)删除列
alter table 表名 drop column 字段alter table tb_txt_new drop column col_test_name;
7.1.3 删除表drop table ;
7.2 约束
约束是数据库用来确保数据满足业务规则的手段,不过在真正的企业开发中,除了主键约束这类具有强需求的约束,像外键约束,检查约束更多时候仅仅出现在数据库设计阶段,真实环境却很少应用,更多是放到程序逻辑中去进行处理。这也比较容易理解,约束会一定程度上较低数据库性能,有些规则直接在程序逻辑中处理就可以了,同时,也有可能在面对业务变更或是系统扩展时,数据库约束会使得处理不够方便。不过在我看来,数据库约束是保证数据准确性的最后一道防线,对于设计合理的系统,处于性能考虑数据库约束自然可有可无;不过若是面对关联关系较为复杂的系统,且对系统而言,数据的准确性完整性要高于性能要求,那么这些约束还是有必要的(否则,就会出现各种相对业务规则来说莫名其妙的脏数据,本人可是深有体会的。)。总之,对于约束的选择无所谓合不合理,需要根据业务系统对于准确性和性能要求的侧重度来决定。
数据库约束有五种:
• 主键约束(PRIMARY KEY)
• 唯一性约束(UNIQUE)
• 非空约束(NOT NULL)
• 外键约束(FOREIGN KEY)
• 检查约束(CHECK)
1)主键约束(PRIMARY KEY)
主键是定位表中单个行的方式,可唯一确定表中的某一行,关系型数据库要求所有表都应该有主键,不过Oracle没有遵循此范例要求,Oracle中的表可以没有主键(这种情况不多见)。关于主键有几个需要注意的点:
1.键列必须必须具有唯一性,且不能为空,其实主键约束 相当于 UNIQUE+NOT NULL
2.一个表只允许有一个主键
3.主键所在列必须具有索引(主键的唯一约束通过索引来实现),如果不存在,将会在索引添加的时候自动创建
2)唯一性约束(UNIQUE)
唯一性约束可作用在单列或多列上,对于这些列或列组合,唯一性约束保证每一行的唯一性。
UNIQUE需要注意:
对于UNIQUE约束来讲,索引是必须的。如果不存在,就自动创建一个(UNIQUE的唯一性本质上是通过索引来保证的)
UNIQUE允许null值,UNIQUE约束的列可存在多个null。这是因为,Unique唯一性通过btree索引来实现,而btree索引中不包含null。当然,这也造成了在where语句中用null值进行过滤会造成全表扫描。
3)非空约束(NOT NULL)
非空约束作用的列也叫强制列。顾名思义,强制键列中必须有值,当然建表时候若使用default关键字指定了默认值,则可不输入。
4)外键约束(FOREIGN KEY)
外键约束定义在具有父子关系的子表中,外键约束使得子表中的列对应父表的主键列,用以维护数据库的完整性。不过出于性能和后期的业务系统的扩展的考虑,很多时候,外键约束仅出现在数据库的设计中,实际会放在业务程序中进行处理。外键约束注意以下几点:
1.外键约束的子表中的列和对应父表中的列数据类型必须相同,列名可以不同
2.对应的父表列必须存在主键约束(PRIMARY KEY)或唯一约束(UNIQUE)
3.外键约束列允许NULL值,对应的行就成了孤行了
其实很多时候不使用外键,很多人认为会让删除操作比较麻烦,比如要删除父表中的某条数据,但某个子表中又有对该条数据的引用,这时就会导致删除失败。我们有两种方式来优化这种场景:
第一种方式简单粗暴,删除的时候,级联删除掉子表中的所有匹配行,在创建外键时,通过 on delete cascade 子句指定该外键列可级联删除:
第二种方式,删除父表中的对应行,会将对应子表中的所有匹配行的外键约束列置为NULL,通过 on delete set null 子句实施
第三种方式,默认,强制不让删
5)检查约束(CHECK)
检查约束可用来实施一些简单的规则,比如列值必须在某个范围内。检查的规则必须是一个结果为true或false 的表达式
7.2.1 创建表和约束
表名: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(3) | 性别,默认‘男’,只能是‘男’或‘女’ |
6 | varchar2(30) | 邮箱,唯一 | |
7 | regtime | date | 注册日期,默认当前日期 |
表名: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 |
1)约束没有名字
create tble tb_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(3) default('男') check(gender in('男','女')),
email varchar2(30) unique,
regtime date default(sysdate)
);
create table tb_txt(
txtid number(10) 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);
2)带名字的约束
create table tb_user(
userid number(5),
username varchar2(30) constraint nn_user_name not null ,
userpwd varchar2(20) constraint nn_user_pwd not null ,
age number(3) default(18) ,
gender char(3) default('男'),
email varchar2(30),
regtime date default(sysdate),
constraint pk_user_id primary key (userid),
constraint ck_user_name check(length(username)between 4 and 20) ,
constraint ck_user_pwd check(length(userpwd) between 4 and 18),
constraint ck_user_age check(age>=18),
constraint ck_user_gender check(gender in('男','女')),
constraint uq_user_email unique(email)
);
create table tb_txt(
txtid number(10),
title varchar2(32) constraint nn_txt_title not null,
txt varchar2(1024),
pubtime date default(sysdate),
userid number(5) ,
constraint pk_txt_id primary key(txtid),
constraint ck_txt_id check(length(title)>=4 and length(title)<=30),
constraint fk_txt_ref_user_id foreign key(userid) references tb_user(userid) on delete cascade
);
7.2.2 创建并追加约束
create table tb_user(
userid number(5),
username varchar2(30) ,
userpwd varchar2(20) ,
age number(3) ,
gender char(3) ,
email varchar2(30),
regtime date default(sysdate)
);
--追加约束
alter table tb_user add constraint pk_user_id primary key (userid);
alter table tb_user add constraint ck_user_name check(length(username)between 4 and 20) ;
alter table tb_user add constraint ck_user_pwd check(length(userpwd) between 4 and 18);
alter table tb_user add constraint ck_user_age check(age>=18);
alter table tb_user add constraint ck_user_gender check(gender in('男','女'));
alter table tb_user add constraint uq_user_email unique(email);
--非空与默认
alter table tb_user modify (username constraint nn_user_name not null);
alter table tb_user modify (userpwd constraint nn_user_pwd not null);
alter table tb_user modify (age default(18));
alter table tb_user modify (gender default('男'));
create table tb_txt(
txtid number(10),
title varchar2(32),
txt varchar2(1024),
pubtime date,
userid number(5)
);
--追加约束
alter table tb_txt add constraint pk_txt_id primary key(txtid);
alter table tb_txt add constraint ck_txt_id check(length(title)>=4 and length(title)<=30);
--三种级联删除规则
alter table tb_txt add constraint fk_txt_ref_user_id foreign key(userid) references tb_user(userid);
alter table tb_txt add constraint fk_txt_ref_user_id foreign key(userid) references tb_user(userid) on delete cascade ;
alter table tb_txt add constraint fk_txt_ref_user_id foreign key(userid) references tb_user(userid) on delete set null;
--注意非空 默认
alter table tb_txt modify (title constraint nn_txt_title not null);
alter table tb_txt modify (pubtime default(sysdate));
7.2.3 查看约束
1)查看某个用户的约束
select constrat_name , constraint_type
from user_constraints
where owner = upper('scott');
2)查看表的约束
select constraint_name ,constraint_type
from user_constraints
where table_name=upper('tb_user');
3)查看字段名上的约束
select constraint_name, column_name
from user_cons_columns
where table_name = upper('tb_user');
7.2.3 禁用和启用约束
很多时候由于业务需要,比如我们有大量的历史数据,需要和现有数据合并,当前表存在数据库约束(如非空约束),而这些历史数据又包含违背非空约束的数据行,为了避免导入时由于违反约束而导入失败,我们通过调整约束状态来达到目的。
数据库约束有两类状态
启用/禁用(enable/disable):是否对新变更的数据启用约束验证
验证/非验证 (validate/novalidate) :是否对表中已客观存在的数据进行约束验证
这两类四种状态从语法角度讲可以随意组合,默认是 enable validate
下面我们来看着四类组合会分别出现什么样的效果:
enable validate : 默认的约束组合状态,无法添加违反约束的数据行,数据表中也不能存在违反约束的数据行;
enable novalidate : 无法添加违反约束的数据行,但对已存在的违反约束的数据行不做验证;
disable validate : 可以添加违反约束的数据行,但对已存在的违反约束的数据行会做约束验证(从描述中可以看出来,这本来就是一种相互矛盾的约束组合,只不过是语法上支持这种组合罢了,造成的结果就是会导致DML失败)
disable novalidate : 可以添加违法约束的数据行,对已存在的违反约束的数据行也不做验证。
拿上面的例子来说,我们需要上传大量违反非空约束的历史数据(从业务角度讲这些数据不会造成系统功能异常),可以临时将约束状态转为 disable novalidate,以保证这些不合要求的数据导入表中
7.2.4 删除约束
alter table tb_user drop constraint uq_user_email cascade;
本篇完,记得回复“情人节”,领取码歌送你的女朋友。想要更多资料,找码歌悠悠:1811119218