SQL高级:

本文深入讲解了SQL高级中的数据完整性概念,包括实体完整性、域完整性和引用完整性,以及如何通过主键约束、唯一约束和自动增长约束来确保数据正确性。还介绍了各类约束的创建方式和多表查询技巧,如合并结果集、连接查询和子查询的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SQL高级:

数据的完整性:

作用:保证用户输入的数据保存到数据库中是正确的,确保数据的完整性=在建表的时候给表添加约束

完整性的分类:实体完整性,域完整性,引用完整性

实体完整性:

定义:表中每一行数据(记录)代表一个实体(entity)

实体完整性的作用:表示每一行数据不重复

约束类型:

主键约束(primary key):(特点)每个表中只有一个主键,被约束的数据唯一,且不能为null

-- 第一种方式:在写列名的时候直接指明主键
CREATE TABLE s1(
	id INT PRIMARY KEY,
	NAME VARCHAR(20)
)CHARSET=utf8;
-- 第二种方式:此种方式的优势在于,可以创建联合主键
CREATE TABLE s2(
	id INT,
	NAME VARCHAR(20),
	PRIMARY KEY(id)
)CHARSET=utf8
-- 第三种方式:单独添加主键
CREATE TABLE s3(
	id INT,
	NAME VARCHAR(20)
)CHARSET=utf8
ALTER TABLE s3 ADD PRIMARY KEY (id);

唯一约束(unique):(特点)数据唯一,可以为null,null不算重复

-- 唯一约束
CREATE TABLE s4(
	id INT UNIQUE,
	NAME VARCHAR(10)
)CHARSET=utf8

自动增长约束(auto_increment):(特点)默人从列最大值+1操作,给主键添加自动增长约束,列只能是整数类型:

-- 自动增长序列
CREATE TABLE s5(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(50)
)CHARSET=utf8;
域完整性:

域完整性的作用:限制单元格的数据正确,不对照此列的其他单元格比较,域代表当前的单元格

域完整性约束分类:

数据类型:

非空约束(Not Null)

默认值约束(default)

check约束(mysql不支持),check(sex=‘男’ or sex=‘女’)

数据类型:

数值类型,日期类型,字符串类型

非空约束:

-- 非空约束
CREATE TABLE s6(
	id INT PRIMARY KEY ,
	NAME VARCHAR(20) NOT NULL,
	sex VARCHAR(10)
)CHARSET=utf8;

默认约束:

-- 默认值约束
CREATE TABLE s7(
	id INT PRIMARY KEY,
	NAME VARCHAR(20) NOT NULL,
	sex VARCHAR(1) DEFAULT '男'
)CHARSET=utf8;
INSERT INTO s7 VALUES(1,'zhngsan',DEFAULT);
引用完整性(参照完整性):
--  引用完整性
CREATE TABLE s8(
	id INT PRIMARY KEY,
	NAME VARCHAR(50) NOT NULL,
	sex VARCHAR(10) DEFAULT '男' 
)CHARSET=utf8;
CREATE TABLE s9(
	 id INT PRIMARY KEY,
	 socre INT,
	 FOREIGN KEY (id) REFERENCES s8(id) -- 外键列的数据类型一定要与逐渐的类型一致
)CHARSET=utf8;
表和表关系:

一对一:

例如t_person表和t_card表,即人和身份证,这种情况需要找出主从关系,即谁是主表,谁是从表,人可以没有身份证,但身份证必须要有人才行,所以人是主表,而身份证是从表。设计从表可以有两种方案:在t_card表中添加外键列(相对于t_user表),并且给外键添加唯一约束;给t_card表的主键添加外键约束(相对于t_user表),即t_card表的主键也是外键

一对多(多对一):

最为常见的就是一对多!一对多和多对一,这是从从哪个角度去看总结出来的,t_user和t_selection的关系,从t_user来看就是一对多,而从t-selection的角度来看就是多对一!这种情况都是在多方创建外键!

多对多:

例如t_stu和s_teacher表,即一个学生可以有多个老师,而一个老师也可以有多个学生,这种情况通常需要创建中间表来处理多对多的关系,例如在创建一张表t_stu_tea表,给出两个外键,已给相对于t_stu表的外键,另一个相对于t_teacher表的外键

多表查询:

1.合并结果集
 -- 查询计算机系的全体学生,以及年龄在19岁以下的学生
 SELECT * FROM student WHERE sdept = 'CS' UNION  SELECT * FROM student WHERE sage < 19;
作用:合并结果集就是把两个select语句的查询结果合并到一起!
要求:被合并的两个结果:列数,列类型必须相同
-- 合并结果集
-- 在进行合并结果集时,两个表的字段个数和类型必须一致
-- 合并结果集时并不是对原表进行合并,是对查出来的虚拟表进行合并
-- union会自动进行去重,union all不会进行去重
-- 当类型有高低等级,会自动转成高等级类型
2.连接查询

2.1等值连接

-- 这种查询的方式是靠两个表之间的公共属性empId实现的
SELECT * FROM emp,bonus WHERE emp.empId = bonus.empId;

2.2自然连接

-- 在等值连接的基础上,把目标列中重复的属性列去掉则为自然连接
-- 注意点:因为在两个表中都出现了empId这个属性,所以我们在引用属性的时候加上前缀
SELECT emp.`empId`,NAME,supervisor,salary,bonus FROM emp,bonus WHERE emp.empId = bonus.empId;
-- 一句sql语句可以同时完成选择和连接查询,这是where子句是由连接谓词和选择谓词组成的复合条件

2.3自身连接

-- 一个表与自己进行连接,称为表的自身连接
-- 查询每一门课的间接先修课(即先修课的先修课)子查询
SELECT c1.`cno`,c2.`cpno` FROM course c1,course c2 WHERE c1.`cpno`=c2.`cno`;

2.4外连接:

 -- 外连接
 -- 在通常的连接操作中,只有满足连接条件的元组才能作为结果输出,如(查询每个学生及其选修课程的情况)结果中没有’201215123‘,’2012151125‘
 -- 这两个学生的信息,原因在于他们没有选课,在sc表中没有相应的元组,导致了student中这些元组在连接时被舍弃了
 -- 但有时想以student表为主体列出每个学生的基本情况及其选课情况,在没有某个学生的信息时,仍把student的悬浮元组保留在结果关系中
 -- 而在sc表的属性上添加空值null,这时就需要使用外连接
 -- 左外连接
  -- 表1 left outer join (表2) on (表1.主码=表2.主码) --->表示表1左外连接上表2(保留表1信息)
 -- 右外连接
 -- 表1 right outer join (表2) on (表1.主码=表2.主码) --->表示表1右外连接上表2(保留表2信息)
 -- 多表连接
 -- 靠主表主码和从表外码进行连接
3.子查询:

定义:一个select语句中包含了另一个完整的select语句,子查询就是嵌套查询,即select中包含select,如果一条语句中存在两个或者两个以上的select,那么就是子查询语句了

子查询出现的位置:

where后,作为被查询条件的一部分

from后,作为表

注意:当子查询出现在where后作为条件时,还可以使用如下关键字:any all(很少用)

子查询结果集形式:

单行单列(用于条件)

单行多列(用于条件)

多行单列(用于条件)

多行多列(用于表)

-- 嵌套查询(不相关嵌套)
 -- 查询与“刘晨”在同一个系学习的学生
-- 第一步先查询“刘晨”所在的系,再以此为根据找出学生信息 
SELECT * FROM student WHERE sdept IN (SELECT sdept FROM student WHERE sname = '刘晨');
-- 自连接查询
SELECT s2.`sname`,s2.`sage`,s2.`sdept`,s2.`sno`,s2.`ssex` FROM student s1,student s2 WHERE s1.sdept=s2.sdept AND s1.sname = '刘晨';
 
 -- 查询选修了课程名为“信息系统”的学生学号和姓名
 -- 先从course表中查出“信息系统”的课程号,再从sc表中查出选了此课的学生学号,最后再从student中查出姓名
 SELECT sname,sno FROM student 
 WHERE sno IN (SELECT sno FROM sc
  WHERE cno IN (SELECT cno FROM course 
    WHERE cname = '信息系统'))
 -- 使用多表连接,可以简化sql语句
 SELECT student.sno,student.sname FROM student,sc,course
 WHERE student.`sno`=sc.`sno` AND sc.`cno`=course.`cno` AND course.`cname` = '信息系统';

MySQL中的函数:

常用日期函数:

addtime(date 2,time_interval)将time_interval加到data2
current_date()当前日期
current_time()当前时间
current_timestamp()当前时间戳
date(datetime)返回datetime的日期部分
date_add(date2,inteval d_value d_type)在date2中加上日期或时间
date_sub(date2,interval d_value d_type)在data2上减去一个时间
datediff(date1,date2)两个日期差
now()当前时间
year|month|day(datetime)年月日

字符串函数:

charset(str)返回字串字符集
concat(string [])连接字串
instr(string,substring)返回substring在string中出现的位置,没有返回0
ucase(string)转换成大写
lcase(string)转换成小写
left(string,length)从string中的左边取length个字符
length(string)length长度
replace(str,search_str,replace_str)在str中用到replace_str替换search_str
strcmp(str1,str2)逐个按照字符比较两个字符串的大小
substring(str,position,[length])从str的postion开始,取length个字符
ltrim(string)rtrim(string)trim去除前端空格,或者后端空格,或去前后空格

常规函数:

abs(num)绝对值
bin(decimal_number)十进制转二进制
ceiling(number1)向上取整
conv(number,from,to)进制转换
floor(num)向下取整
format(num,decimal_places)保留小数位数
hex(decimalNum)转十六进制
least(num1,num2,…)求最小值
mod(numerator,denominator)求余
rand()随机数

自定义函数:

定义:mysql中的函数与存储过程类似,都是一组sql集

与存储过程的区别:函数可以return值,存储过程不能直接return,但是有输出参数可以输出多个返回值;

函数可以嵌入到sql语句中使用,而存储过程不能;

函数一般用于实现简单的有针对性的功能(例如求绝对值,返回当前时间),存储过程用于实现复杂的功能(如复杂的业务逻辑功能);

函数的关键字是function,存储过程是:procedure

自定义函数:

-- 定义函数之前首先需要定义分隔符
DELIMITER ;; -- 自定义分隔符,这里定义的分隔符是;;定义好之后,只有遇到;;才会结束

-- 自定义函数
CREATE DEFINER='root'@'localhost' FUNCTION func_compare(a INT) RETURNS VARCHAR(200) CHARSET utf8
BEGIN -- 函数开始
-- routine body goes here

-- 这里写的是if语句
IF a >= 10 THEN 
	RETURN '大于等于10' ;
ELSE
	RETURN '小于10';
END IF;
END -- 函数结束
;;
-- 重新定义分隔符
DELIMITER ;

-- 使用函数
SELECT func_compare(4);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值