数据库第五天

时间:2021-08-28 04:06:47

常见约束

含义:一种限制,用于限制表中数据,为了保证表中的数据的准确性和可靠性

分类:六大约束
NOT NULL:非空,用于保证该字段的值不能为空
比如姓名 学号等
DEFAULT:默认 用于保证该字段有默认值
比如性别
PRIMARY KEY:主键约束,用于保证该字段的值具有唯一性 并且非空
比如学号 员工编号等
QNIQUE:唯一,用于保证该字段的值具有唯一性 可以为空
比如座位号
CHECK:检查约束[Mysql中不支持]
比如年龄 性别
FOREIGN KEY:外键约束,用于限制两个表的关系,用于保证该字段的值必须来自于主表的关联列的值
在从表中添加 用于引用主表中某列的值
比如学生表的专业编号,员工表的部门编号 员工表的工种编号

添加约束的时机:
1.创建表时
2.修改表时

约束的添加分类:
列级约束
六大约束语法上都支持,但外键约束没有效果
表级约束
除了非空 默认 其他都支持

主键和唯一的大对比

保证唯一性 是否为空 一个表中可以有多少个 是否允许组合
主键 唯一 非空 至多一个 可以但不推荐
唯一 唯一 允许为空 可以有多个 可以但不推荐
insert into major values(1,‘java‘);
insert into major values(2,‘h5‘);
insert into stuinfo values(1,‘john‘,‘男‘,null,19,1);
insert into stuinfo values(2,‘lili‘,‘男‘,null,19,2);
外键:
1.要求再从表设置外键关系
2.从表的外键列的类型和主表的关联列的类型要求一致或兼容,名称无要求
3.主表的关联列必须是一个key(一般是主键或唯一)
4.插入数据时,先插入主表,再插入从表
删除数据时,先删除从表 再删除主表
CREATE TABLE major(
id INT PRIMARY KEY;
majorId VARCHAR(20)
);


CREATE TABLE 表名(
字段名 字段类型 列级约束,
字段名 字段类型,
表级约束
);



一、创建表时 添加约束
1.添加列级约束
语法:
直接在字段名和类型后面追加约束类型即可
只支持:默认、非空、主键、唯一

 

USE students;
CREATE TABLE stuinfo(
id INT PRIMARY KEY,#主键
stuName VARCHAR(20) NOT NULL,#非空
gender CHAR(1) CHECK(gender=‘男‘ or gender=‘女‘),#检查约束
seat INT UNIQUE,#唯一约束
age INT DEFAULT 18,#默认约束
majorId INT PEFERENCES major(id)#外键
)

CREATE TABLE major(
id INT PRIMARY KEY;
majorId VARCHAR(20)
);

查看stuinfo中所有的索引,包括主键、外键、唯一
SHOW INDEX FROM stuinfo;

2.添加表级约束

语法:在各个字段的最下面
【constraint 约束名】 约束类型(字段名)

DROP TABLE IF EXISTS stuinfo;
CREATE TABLE stuinfo(
id INT,
stuname VARCHAR(20),
gender CHAR(1),
seat INT,
age INT,
majorid INT,

CONSTEAINT pk PRIMARY KEY(id,stuname),#主键
CONSTEAINT uq UNIQUE(seat),#唯一键
CONSTEAINT ck CHECK(gender=‘男‘ OR gender=‘女‘),#检查
CONSTEAINT fk_stuinfo_major FOREIGN KEY (majorid) REFERENCES major(id) #外键

);

SHOW INDEX FROM stuinfo;

#通用的写法:

CREATE TABLE IF NOT EXISTS stuinfo(
id INT PRIMARY KEY,
stuname VARCHAR(20) NOT NULL UNIQUE,#非空
sex CHAR(1),
age INT DEFAULT 18,
seat INT UNIQUE,
majorid INT fk_stuinfo_major FOREIGN KEY(majorid) REFERENCES major(id)
)

二、修改表时添加约束

1.添加列级约束
alter table 表名 modify column 字段名 字段类型 新约束;

2.添加表级约束
alter table 表名 add [constraint 约束名] 约束类型(字段名) 【外键的引用】;

 


DROP TABLE IF EXISTS stuinfo;
CREATE TABLE stuinfo(
id INT,
stuname VARCHAR(20),
gender CHAR(1),
seat INT,
age INT,
majorid INT
);
DESC stuinfo;
1.添加非空约束 (只支持列级)
ALTER TABLE stuinfo MODIFY COLUMN stuname VARCHAR(20) NOT NULL;

2.添加默认约束
ALTER TABLE stuinfo MODIFY COLUMN age INT DEFAULT 18;

3.添加主键
1.列级约束
ALTER TABLE stuinfo MODIFY COLUMN id INT PRIMARY KEY;
2.表级约束
ALTER TABLE stuinfo ADD PRIMARY KEY(id);

4.添加唯一
1.列级约束
ALTER TABLE stuinfo MODIFY COLUMN id INT UNIQUE;
2.表级约束
ALTER TABLE stuinfo ADD UNIQUE(id);

5.添加外键
ALTER TABLE stuinfo ADD FOREIGN KEY(majorid) REFERENCES major(id);


三、修改表时删除约束
1.删除非空约束
ALTER TABLE stuinfo MODIFY COLUMN stuname VARCHAR(10) NULL;

2.删除默认约束
ALTER TABLE stuinfo MODIFY COLUMN age INT;


3.删除主键
ALTER TABLE stuinfo DROP PRIMARY KEY;

4.删除唯一
ALTER TABLE stuinfo DROP INDEX seat;

5.删除外键
ALTER TABLE stuinfo DROP FOREIGN KEY fk_stuinfo_major;


SHOW INDEX FROM stuinfo

位置 支持的约束类型 是否可以起约束名
列级约束 列的后面 语法都支持 但外键没有效果 不可以
表级约束 所有列的下面 默认和非空不支持,其他支持 可以(主键没效果)

 

标识列
又称为自增长列
含义:可以不用手动的插入值 系统提供默认的序列值
特点:
1.标识列必须和主键搭配吗?不一定 但要求是一个key
2.一个表中可以有多少个标识列? 至多一个
3.标识列的类型 只能是数值型
4.标识列可以通过 SET auto_increment_increment=3;来设置步长
可以通过手动插入值设置起始值

一、创建表时设置标识列
DROP TABLE IF EXISTS tab_identity;
CREATE TABLE tab_identity(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20)
);

TRUNCATE TABLE tab_identity;
INSERT INTO tab_identity(id,NAME) VALUES(NULL,‘john‘);

INSERT INTO tab_identity(id) VALUES(‘john‘);

SELECT * FROM tab_identity;

SHOW VARIABLES LIKE ‘%auto_increment%‘;

SET auto_increment_increment=3;#设置步长为3


二、修改表时设置标识列

ALTER TABLE tab_identity MODIFY COLUMN id INT PRIMARY KEY AUTO_INCREMENT;

三、修改表时删除标识列
ALTER TABLE tab_identity MODIFY COLUMN id INT;

 

TCL
Transaction Contorl Language 事务控制语言

事务:
一个或一组sql语句组成一个执行单元 这个执行单元要么全部执行,要么全部不执行。

案例:转账

张三丰 1000
郭襄 1000

update 表 set 张三丰的余额=500 where name=‘张三丰‘
意外
update 表 set 郭襄的余额=1500 where name=‘郭襄‘

SHOW ENGINES;#来查看mysql中支持的存储引擎
innodb支持事务 myisam memory不支持事务

事务的ACID属性
1.原子性:(Atomicity)
原子性是指事务是一个不可分割的工作单位 事务中的操作要么都发生 要么不发生。
2.一致性(Consistency)
事务必须使一个一致性状态变换到另一个一致性状态

3.隔离性(Isolation)
事务的隔离性是指一个事物的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。

4.持久性(Durability)
一个事务的提交 它对数据库的改变就是永久性的,接下来其他的操作和数据库故障不应该对其有任何影响。

事务的创建
隐式事务:事务没有明显的开启和结束的标记
比如insert、update、delete语句
delete from 表 where id=1;
update from 表 where id=1;

显式事务:事务具有明显的开始和结束语句的标记
前提:必须先设置自动提交功能为禁用

set auto_commit=0;


开始事务的语句;

步骤一:开启事务
set auto_commit=0;
start transaction;可选的

步骤二:编写事务中的sql语句(select insert update delete)
语句1;
语句2;
...
步骤三:结束事务
commit;提交事务
rollback;回滚事务

savepoint 节点名;设置保存点

 

事务隔离级别:

read uncommitted; 出现脏读 幻读 不可重复读
read committed;避免脏读 出现幻读和不可重复读
repeatable read; 避免脏读 幻读 可重复读
serializable; 避免脏读 不可幻读 不可重复读

mysql中默认第三个隔离级别repeatable read
oracle中默认第二个隔离级别 read commited
查看当前隔离级别
SELECT @@tx_isolation

设置当前mysql连接隔离级别:
set transaction isolation level read committed;

设置数据库系统的全局的隔离级别:
set global transaction isolation level read committed;

 

SHOW VARIABLES LIKE ‘auto_commit‘

1.演示事务的使用步骤

开启事务
SET autocommit=0;
START TRANSACTION;
编写一组事务语句
UPDATE account SET balance = 500 WHERE username=‘张无忌‘;
UPDATE account SET balance = 1500 WHERE username=‘赵敏‘;

结束事务
ROLLBACK; 回滚
COMMIT; 提交

SELECT * FROM account;


2.演示事务对于delete和truncate的处理区别

SET autocommit=0;
START TRANSACTION;

DELETE FROM account;
ROLLBACK;

3.演示savepoint的使用
SET autocommit=0;
START TRANSACTION;
DELETE FROM account WHERE id=25;

SAVEPOINT a;设置保存点
DELETE FROM account WHERE id=28;
rollback to a;回滚到保存点

 

视图
含义:虚拟的表,和普通表一样使用
mysql 5.0.1版本出现的新特性,是通过动态生成的数据

比如:舞蹈班和普通班的对比
创建语法的关键字 是否实际占用物理空间 使用

视图 create view 只保存了sql 增删改查,只是一般不能增删改
表 create table 保存了数据 增删改查

 

案例:查询姓长的学生名和专业名
select stuname,marjorname
FROM stuinfo s
inner join marjor m on s.majorid=m.id
where s.stuname like ‘张%‘;

CREATE VIEW v1
AS
select stuname,marjorname
FROM stuinfo s
inner join marjor m on s.majorid=m.id

SELECT * FROM v1 WHERE stuname LIKE ‘张%‘

一、创建视图

语法:
create view 视图名
as
查询语句;


#1.查询邮箱中包含a字符的员工名 部门名和工种信息

1.创建
CREATE VIEW myv1
AS
SELECT last_name,department_name,job_title
FROM employees e
JOIN departments d ON e.department_id=d.department_id
JOIN jobs j ON j.job_id = e.job_id;

2.使用
SELECT * FROM myv1 WHERE last_name LIKE ‘%a%‘;


2.查询各部门的平均工资级别

CREATE VIEW myv2
AS
SELECT AVG(salary)
FROM employees
GROUP BY department_id;

2.使用
SELECT myv2.ag,g.grade_level
FROM myv2
JOIN job_grades g
ON myv2.ag BETWEEN g.lowest_sal AND g.highest_sal;

 

 

3.查询平均工资最低的部门信息
SELECT * FROM myv2 ORDER BY ag LIMIT 1;


4.查询平均工资最低的部门名和工资

CREATE VIEW myv3
AS
SELECT * FROM myv2 ORDER BY ag LIMIT 1;

SELECT d.*,m.ag FROM myv3 m
JOIN departments d
ON m.department_id=d.department_id;


好处:
sql语句的重用
简化了复杂的sql操作 不必知道它的查询细节
保护数据 提高安全性


二、视图的修改

方式一:
create or replace view 视图名
as
查询语句;
SELECT * FROM myv3

CREATE OR REPLACE VIEW myv3
AS
SELECT AVG(salary),job_id
FROM employees
GROUP BY job_id;

方式二:
语法:alter view 视图名
as
查询语句;

ALTER VIEW myv3
AS
SELECT * FROM employees;


三、删除视图
语法:drop view 视图名,视图名,...;
DROP VIEW myv1,myv2,myv3;

四、查看视图
DESC myv3;
SHOW CREATE VIEW myv3;

五、视图的更新
CREATE OR REPLACE VIEW myv1
AS
SELECT last_name,email,salary*12*(1 IFNULL(commission_pct,0)) "annual salary"
FROM employees

SELECT * FROM myv1;

1.插入
INSERT INTO myv1 VALUES(‘张飞‘,‘[email protected]‘,10000);

2.修改
UPDATE myv1 SET last_name =‘张无忌‘ WHERE last_name=‘张飞‘;

#具备以下特点的视图不能不允许更新
1.包含以下关键字的sql语句:分组函数、distinct、group by、having、union或者union all
CREATE OR REPLACE VIEW myv1
AS
SELECT MAX(salary) m,department_id
FROM employees
GROUP BY department_id;

SELECT *FROM myv1;

更新
UPDATE myv1 SET m=9000 WHERE department_id=10;

2.常量视图
CREATE OR REPLACE VIEW myv2
AS
SELECT ‘john‘ NAME;

SELECT * FROM myv2;

更新
UPDATE myv2 SET NAME =‘lucy‘;

3.SELECT中包含子查询
CREATE OR REPLACE VIEW myv3
AS

SELECT (SELECT MAX(salary) FROM employees) 最高工资;
更新
SELECT * FROM myv3;
UPDATE myv3 SET 最高工资=10000;

4.JOIN
CREATE OR REPLACE VIEW myv4
AS

SELECT last_name,department_name
FROM employees e
JOIN departments d
ON e.department_id=d.department_id

更新
SELECT * FROM myv4
UPDATE myv4 SET last_name =‘张飞‘ WHERE last_name =‘Whalen‘
INSERT INTO myv4 VALUES(‘王五‘,‘xxxx‘);


5.FROM一个不能更新的视图
CREATE OR REPLACE VIEW myv5
AS

SELECT * FROM myv3;

更新

SELECT * FROM myv5;
UPDATE myv5 SET 最高工资=10000 WHERE department_id=60;


6.WHERE 子句的子查询引用了FROM子句中的表
CREATE OR REPLACE VIEW myv6
AS

SELECT last_name,email,salary
WHERE employee_id INDEX(
SELECT manager_id
FROM employees
WHERE manager_id IS NOT NULL

);

SELECT * FROM myv6;
UPDATE myv6 SET salary=10000 WHERE last_name =‘k_ing‘;