欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MySQL6天学习笔记——day05

程序员文章站 2022-05-30 13:15:51
...


7. DDL语言的学习

7.3 常见约束

-- 常见约束

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

分类:六大约束
	1.NOT NULL:非空,用于保证该字段的值不能为空
		比如姓名、学号等
	2.DEFAULT:默认,用于保证该字段有默认值
		比如性别
	3.PRIMARY KEY:主键,用于保证该字段的值具有唯一性(不可重复),并且非空
		比如学号、员工编号等
	4.UNIQUE:唯一,用于保证该字段的值具有唯一性(不可重复),可以为空
		比如座位号
	5.CHECK:检查约束 [mysql中不支持]
		比如年龄、性别
	6.FOREIGN KEY:外键,用于限制两个表的关系,用于保证该字段的值必须来自于主表的关联列的值
	在从表添加外键约束,用于引用主表中某列的值
		比如学生表的专业编号,员工表的部门编号,员工表的工种编号
	
添加约束的时机:
	1.创建表时
	2.修改表时
	
约束的添加分类:
	列级约束:
		六大约束语法上都支持,但外键约束没有效果
		
	表级约束:
		除了非空、默认外,其他的都支持
		
主键(PRIMARY KEY)和唯一(UNIQUE)的大对比:

		保证唯一性  	是否允许为空    一个表中可以有多少个   	是否允许组合
主键	   √		     	 ×		          至多有1个         √,但不推荐
唯一	   √		       √		          可以有多个        	√,但不推荐

外键:
	1、要求在从表设置外键关系
	2、从表的外键列的类型和主表的关联列的类型要求一致或兼容,名称无要求
	3、主表中的关联列必须是一个key(一般是主键或唯一键)
	4、插入数据时,先插入主表,再插入从表
	删除数据时,先删除从表,再删除主表
*/

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

CREATE DATABASE students;
use students;
-- 1.创建表时添加约束

-- 1.1 添加列级约束
/*
语法:
		直接在字段名和字段类型后面 追加约束类型即可
		只支持:默认、非空、主键、唯一
*/
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 REFERENCES major(id) #外键,引用major表的id字段
);

CREATE TABLE major(
			id INT PRIMARY KEY,
			majorName VARCHAR(20)
);
-- 查看表结构
DESC stuinfo;
-- 查看表中所有的索引,包括主键、外键、唯一
SHOW INDEX FROM stuinfo;

-- 1.2 添加表级约束
/*
语法:在各个字段的最下面
		[constraint 约束名] 约束类型(字段名) 
*/
-- 方式一:
DROP TABLE IF EXISTS stuinfo;
CREATE TABLE stuinfo(
				id INT,
				stuName VARCHAR(20),
				gender CHAR(1),
				seat INT,
				majorid INT,
				
				CONSTRAINT pk PRIMARY KEY(id), #主键
				CONSTRAINT uq UNIQUE(seat), #唯一键
				CONSTRAINT ck CHECK(gender = '男' OR gender = '女'), #检查约束
				CONSTRAINT fk_stuinfo_major FOREIGN KEY(majorid) REFERENCES major(id) #外键
);

-- 方式二:省略 CONSTRAINT 约束名
DROP TABLE IF EXISTS stuinfo;
CREATE TABLE stuinfo(
				id INT,
				stuName VARCHAR(20),
				gender CHAR(1),
				seat INT,
				majorid INT,
				
				PRIMARY KEY(id), #主键
				UNIQUE(seat), #唯一键
				CHECK(gender = '男' OR gender = '女'), #检查约束
				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, 
	sex CHAR(1),
	age INT DEFAULT 18, #默认18
	seat INT UNIQUE, #唯一键
	majorid INT,
	CONSTRAINT fk_stuinfo_major FOREIGN KEY(majorid) REFERENCES major(id) #外键
);

-- 2.修改表时添加约束
/*
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;

-- 2.1 添加非空约束
ALTER TABLE stuinfo MODIFY COLUMN stuname VARCHAR(20) NOT NULL;

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

-- 2.3 添加主键
-- ①列级约束
ALTER TABLE stuinfo MODIFY COLUMN id INT PRIMARY KEY;
-- ②表级约束
ALTER TABLE stuinfo ADD PRIMARY KEY(id);

-- 2.4 添加唯一键
-- ①列级约束
ALTER TABLE stuinfo MODIFY COLUMN seat INT UNIQUE;
-- ②表级约束
ALTER TABLE stuinfo ADD UNIQUE(seat);

-- 2.5 添加外键(CONSTRAINT 键名,也可以省略)
ALTER TABLE stuinfo ADD CONSTRAINT fk_stuinfo_major FOREIGN KEY ( majorid ) REFERENCES major ( id );

-- 2.5.1 添加外键时,添加级联删除(ON DELETE CASCADE)
/*
添加级联删除后,删除主表的记录,与之关联的从表的记录也会被一起删除
*/
ALTER TABLE stuinfo ADD CONSTRAINT fk_stuinfo_major FOREIGN KEY ( majorid ) REFERENCES major ( id ) ON DELETE CASCADE;

-- 2.5.2 添加外键时,添加级联置空(ON DELETE SET NULL)
/*
添加级联置空后,删除主表的记录,与之关联的从表的字段会被置空
*/
ALTER TABLE stuinfo ADD CONSTRAINT fk_stuinfo_major FOREIGN KEY ( majorid ) REFERENCES major ( id ) ON DELETE SET NULL;

-- 3.修改表时删除约束

-- 3.1 删除非空约束
ALTER TABLE stuinfo MODIFY COLUMN stuname VARCHAR(20) [NULL];

-- 3.2 删除默认约束
ALTER TABLE stuinfo MODIFY COLUMN age INT ;

-- 3.3 删除主键
ALTER TABLE stuinfo DROP PRIMARY KEY;

-- 3.4 删除唯一
/*
alter table 表名 drop index 索引名;
*/
ALTER TABLE stuinfo DROP INDEX seat;

-- 3.5 删除外键
/*
alter table 表名 drop foreign key 约束名
*/
ALTER TABLE stuinfo DROP FOREIGN KEY fk_stuinfo_major;

SHOW INDEX FROM stuinfo;

7.3.1 常见约束练习

-- 1. 向表 emp2 的 id 列中添加 PRIMARY KEY 约束(my_emp_id_pk)
ALTER TABLE emp2 MODIFY COLUMN id INT PRIMARY KEY;
ALTER TABLE emp2 ADD CONSTRAINT my_emp_id_pk PRIMARY key(id);

-- 2. 向表 dept2 的 id 列中添加 PRIMARY KEY 约束(my_dept_id_pk)
ALTER TABLE dept2 MODIFY COLUMN id INT PRIMARY KEY;
ALTER TABLE dept2 ADD CONSTRAINT my_dept_id_pk PRIMARY KEY(id);

-- 3. 向表 emp2 中添加列 dept_id,并在其中定义 FOREIGN KEY 约束,与之相关联的列是 dept2 表中的 id 列。
ALTER TABLE emp2 ADD COLUMN dept_id INT;
ALTER TABLE emp2 ADD CONSTRAINT fk_emp2_dept2 FOREIGN KEY(dept_id) REFERENCES dept2(id);

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

7.4 标识列

-- 标识列
/*
又称为自增长列
含义:可以不用手动的插入值,系统提供默认的序列值

特点:
1、标识列必须和主键搭配吗?不一定,但要求是一个key
2、一个表可以有几个标识列?至多一个!
3、标识列的类型只能是数值型
4、标识列可以通过 SET auto_increment_increment=3;设置步长
5、可以通过首次手动插入值,设置起始值
*/
-- 1.创建表时设置标识列

DROP TABLE IF EXISTS tab_identity;
CREATE TABLE tab_identity(
	id INT PRIMARY KEY,
	NAME FLOAT UNIQUE AUTO_INCREMENT, 
	seat INT 
);

TRUNCATE TABLE tab_identity;

INSERT INTO tab_identity(id,NAME) VALUES(NULL,'john');
INSERT INTO tab_identity(NAME) VALUES('lucy');
SELECT * FROM tab_identity;

SHOW VARIABLES LIKE '%auto_increment%';

-- 设置每次自动增长的步长
SET auto_increment_increment=3;

-- 2.修改表时设置标识列
/*
alter table 表名 modify column 字段名 字段类型 约束 auto_increment;
*/
ALTER TABLE tab_identity MODIFY COLUMN id INT PRIMARY KEY AUTO_INCREMENT;

-- 3.修改表时删除标识列
-- 删除表字段id的主键,因为一张表只能有一个主键,所以主键可以默认不写
ALTER TABLE tab_identity MODIFY COLUMN id int; 

8. TCL语言的学习

8.1 事务

-- 事务
/*
Transaction Control Language 事务控制语言

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

案例:转账

张三丰   1000
郭襄	    1000

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

事务的特性:
ACID
原子性(Atomicity):一个事务是不可再分割的,要么都执行要么都不执行
一致性(Consistency):一个事务执行会使数据从一个一致状态切换到另外一个一致状态
隔离性(Isolation):一个事务的执行不受其他事务的干扰,多个事务互相隔离
持久性(Durability):一个事务一旦提交,则会永久的持久化到本地

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

delete from 表 where id =1;

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

-- 关闭当前事务的自动提交
set autocommit=0;

具体步骤:
步骤1:开启事务
set autocommit=0;
start transaction; 可以省略的
步骤2:编写事务中的sql语句(select insert update delete)
语句1;
语句2;
...

步骤3:结束事务
commit; 提交事务
rollback; 回滚事务

savepoint 节点名; 设置保存点
一般搭配rollback to 节点名;

事务的隔离级别:
															脏读					不可重复读					幻读
read uncommitted(读未提交):	  	√							√								√
read committed(读已提交):  			×							√								√
repeatable read(可重复读): 			×							×								√
serializable(可串行化):	  			×             ×               ×

脏读:一个事务读取了其他事务还没有提交的数据,读到的是其他事物"更新"的数据
不可重复读:一个事务多次读取数据,结果都不一样
幻读:一个事务读取了其他事务还没有提交的数据,读到的是其他事物"插入"的数据

mysql中默认 第三个隔离级别 repeatable read
oracle中默认第二个隔离级别 read committed
查看隔离级别(mysql8.0+)
select @@transaction_isolation;
查看隔离级别(mysql 5.7)
select @@tx_isolation;
设置隔离级别
set session transaction isolation level 隔离级别;

开启事务的语句;
update 表 set 张三丰的余额=500 where name='张三丰'

update 表 set 郭襄的余额=1500 where name='郭襄' 
结束事务的语句;
*/

-- 查看mysql的存储引擎
SHOW ENGINES;

-- 查看自动提交的状态
SHOW VARIABLES LIKE 'autocommit';

/*
创建表和插入数据
USE test;

DROP TABLE IF EXISTS account;

CREATE TABLE account(
				id INT PRIMARY KEY AUTO_INCREMENT,
				username VARCHAR(20),
				balance DOUBLE
);

INSERT INTO account(username,balance)
VALUES ('张无忌',1000),('赵敏',1000);
*/
-- 1.演示事务的使用步骤

-- 1.1 开启事务
SET autocommit = 0;
START TRANSACTION;
-- 1.2 编写一组事务的语句
UPDATE account SET balance = 1000 WHERE username = '张无忌';
UPDATE account SET balance = 1000 WHERE username = '赵敏';
-- 1.3 结束事务
ROLLBACK; #回滚事务
COMMIT; #提交事务

SELECT * FROM account;

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

-- 2.1 演示delete
SET autocommit=0;
START TRANSACTION;
DELETE FROM account;
ROLLBACK; #delete支持回滚,回滚后数据还存在

-- 2.2 演示truncate
SET autocommit=0;
START TRANSACTION;
TRUNCATE TABLE account;
ROLLBACK; #truncate不支持回滚,回滚后数据也是删除了

-- 3.演示savepoint的使用
SET autocommit=0;
START TRANSACTION;
DELETE FROM account WHERE id = 1;
SAVEPOINT a; #设置保存点
DELETE FROM account WHERE id = 2;

ROLLBACK TO a; #回滚到保存点处,也就是说id=1的信息会被删除,而id=2的信息会被保存下来

SELECT * FROM account;

9.视图

-- 视图
/*
含义:虚拟表,和普通表一样使用
mysql5.1版本出现的新特性,本身是一个虚拟表,它的数据来自于表,通过执行时动态生成
好处:
1、简化sql语句
2、提高了sql的重用性
3、保护基表的数据,提高了安全性

比如:类似于java中的方法

			创建语法的关键字		   是否实际占用物理空间									使用

视图		create view					只是保存了sql逻辑								一般用于查询

表			create table					保存了数据											增删改查
*/

-- 案例:查询姓张的学生名和专业名
SELECT stuname,majorname FROM stuinfo s
INNER JOIN major m ON s.majorid = m.id
WHERE s.stuname LIKE '张%';

CREATE VIEW v1
AS
SELECT stuname,majorname FROM stuinfo s
INNER JOIN major m ON s.majorid = m.id;

SELECT * FROM v1 WHERE stuname LIKE '张%';

-- 1.创建视图
/*
语法:
		create view 视图名
		as
		查询语句;
*/

-- 案例1:查询姓名中包含a字符的员工名、部门名和工种信息
-- ①创建视图
CREATE VIEW myv1
AS
SELECT last_name,department_name,job_title
FROM employees e
INNER JOIN departments d ON e.department_id = d.department_id
INNER JOIN jobs j ON j.job_id = e.job_id;

-- ②使用视图
SELECT * FROM myv1 WHERE Last_name LIKE '%a%';

-- 案例2:查询各部门的平均工资级别
-- ①创建视图,查看每个部门的平均工资
CREATE VIEW myv2
AS
SELECT AVG(salary) ag,department_id
FROM employees
GROUP BY department_id;

-- ②使用视图
SELECT myv2.ag,j.grade_level
FROM myv2 
INNER JOIN job_grades j
ON myv2.ag BETWEEN j.lowest_sal AND j.highest_sal;

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

-- 案例4:查询平均工资最低的部门名和工资
CREATE VIEW myv3
AS
SELECT * FROM myv2 ORDER BY ag ASC LIMIT 1;

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

-- 2.视图的修改

-- 2.1 方式一:
/*
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;

-- 2.2 方式二:
/*
语法:
alter view 视图名
as 
查询语句;
*/
ALTER VIEW myv3
AS
SELECT * FROM employees;

-- 3.删除视图
/*
语法:drop view 视图名,视图名,...;
*/
DROP VIEW emp_v1,emp_v2,myv3;

-- 4.查看视图
DESC myv3;

SHOW CREATE VIEW myv3;

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

CREATE OR REPLACE VIEW myv1
AS
SELECT last_name,email
FROM employees;

SELECT * FROM myv1
SELECT * FROM employees;

-- 5.1 插入数据
INSERT INTO myv1 VALUES('张飞','[email protected]');

-- 5.2 修改数据
UPDATE myv1 SET last_name = '张无忌' WHERE last_name='张飞';

-- 5.3 删除数据
DELETE FROM myv1 WHERE last_name = '张无忌';

-- 5.4 具备以下特点的视图不允许更新

-- 5.4.1 包含以下关键字的sql语句:分组函数、distinct、group by、having、union或者union all

-- 案例:group by
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; #报错,视图包含了group by

-- 5.4.2 常量视图
CREATE OR REPLACE VIEW myv2
AS
SELECT 'john' NAME;

SELECT * FROM myv2;

-- 下面的sql语句也可以算是常量视图
SELECT (SELECT MAX(salary) FROM employees) 最高工资;

-- 更新
UPDATE myv2 SET NAME='lucy'; #报错,视图里面包含常量

-- 5.4.3 select中包含子查询
CREATE OR REPLACE VIEW myv3
AS
SELECT department_id,(SELECT MAX(salary) FROM employees) 最高工资
FROM departments;

SELECT * FROM myv3;

-- 更新
UPDATE myv3 SET 最高工资=100000; #报错,视图包含子查询

-- 5.4.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'); #报错,语句包含join

-- 5.4.5 from后面加一个不能更新的视图
CREATE OR REPLACE VIEW myv5
AS
SELECT * FROM myv3;

SELECT * FROM myv5;

-- 更新
UPDATE myv5 SET 最高工资=10000 WHERE department_id=60; #报错

-- 5.4.6 where子句的子查询引用了from子句中的表
CREATE OR REPLACE VIEW myv6
AS
SELECT last_name,email,salary
FROM employees
WHERE employee_id IN(
	SELECT manager_id
	FROM employees
	WHERE manager_id IS NOT NULL
);

SELECT * FROM myv6;

-- 更新
UPDATE myv6 SET salary=10000 WHERE last_name = 'k_ing'; #报错

上一篇: xml之DTD约束

下一篇: j2ee_04_DTD