diff --git "a/03\351\231\210\346\236\253/\344\275\234\344\270\232/.keep" "b/03\351\231\210\346\236\253/\344\275\234\344\270\232/.keep" new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git "a/03\351\231\210\346\236\253/\347\254\224\350\256\260/.keep" "b/03\351\231\210\346\236\253/\347\254\224\350\256\260/.keep" new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git "a/03\351\231\210\346\236\253/\347\254\224\350\256\260/20220831-\346\237\245\350\257\242\345\244\215\344\271\240\347\254\224\350\256\260.md" "b/03\351\231\210\346\236\253/\347\254\224\350\256\260/20220831-\346\237\245\350\257\242\345\244\215\344\271\240\347\254\224\350\256\260.md" new file mode 100644 index 0000000000000000000000000000000000000000..0e2d532feff3105d77149d10ead506fe23e108a3 --- /dev/null +++ "b/03\351\231\210\346\236\253/\347\254\224\350\256\260/20220831-\346\237\245\350\257\242\345\244\215\344\271\240\347\254\224\350\256\260.md" @@ -0,0 +1,219 @@ +#### SQL语法结构 + +**select--from--where--group by--having--order by--limit** + +##### 运行顺序: + +**from--where--group by--having--select--order by--limit--select** + +![img](https://img-blog.csdnimg.cn/img_convert/7e40189b14af998f540389134eccd977.png) + +select 字段名1, 字段名2, 字段名3 from 表名 +结果会根据select后面的字段顺序进行展示 + +(*)是通配符,即select* from world,就会按默认列顺序查询world表中所有列 + +select 字段名 as 别名(as可省略),可以将结果显示的表头展示为别名 + +```sql +select name as 国家名, continent 大洲, population 人口 from world +``` + +##### 去重:即展示的数据不会重复出现 + +```sql +select name as 国家名,continent 大洲,population 人口 from world +``` + +在select distinct后加多个字段,即对字段组合形成的数据去重(理解为每一行都不会一模一样) + +```sql +select distinct name,continent from world +``` + +select中还可以直接进行计算 + +```sql +select name, gdp, population, gdp/population 人均gdp from world; +``` + +##### select 字段名 from 表名 where 条件 + +![img](https://img-blog.csdnimg.cn/img_convert/a9884d2e85785b03c66456a055e5b1fd.png) + +#### 基础查询 + +1. 查询所有行所有列 +2. 指定列查询(姓名,性别,月薪,电话) +3. 指定列查询,并自定义中文列名(姓名,性别,月薪,电话) +4. 查询公司员工所在城市(不需要重复数据) +5. 假设工资普调10%,查询原始工资和调整后的工资,显示(姓名,性别,月薪,加薪后的月薪)(添加列查询)。 + +#### 条件查询 + +**SQL中常用运算符** + +```sql +=:等于,比较是否相等及赋值 +!=:比较不等于 +>:比较大于 +<:比较小于 +>=:比较大于等于 +<=:比较小于等于 +IS NULL:比较为空 +IS NOT NULL:比较不为空 +in:比较是否在其中 +like:模糊查询 +BETWEEN...AND...:比较是否在两者之间 50-100 BETWEEN 50 AND 100 +and:逻辑与(两个条件同时成立表达式成立) +or:逻辑或(两个条件有一个成立表达式成立) +not:逻辑非(条件成立,表达式则不成立;条件不成立,表达式则成立) +``` + + + +#### 模糊查询 + +模糊查询: where 字段名 like '通配符+字符' + +使用like关键字和通配符结合来实现,通配符具体含义如下: + +```sql +%:代表匹配0个字符、1个字符或多个字符。 +_:代表匹配有且只有1个字符。 +[]:代表匹配范围内 +[^]:代表匹配不在范围内 +``` + +查询国家名中以C开头以ia结尾的国家 + +```sql +/*查询国家名中以C开头以ia结尾的国家*/ +select name from world +where name like 'C%ia' ; +``` + +```sql +/*查询国家名中第二个字符为t的国家*/ +select name from world +where name like '_t%' ; +``` + + sql中,and的优先级高于or + +```sql +/*查询国家名中含有三个a且面积大于60万(600000)的国家及其面积, +或者人口大于13亿(1300000000)且面积大于500万(5000000)的国家及其面积*/ +select name, area from world +where (name like '%a%a%a%' and area > 600000) +or ( population > 1300000000 +and area > 5000000 ) ; +``` + + between and 是包括边界的 + +```sql +/*查询1980年除诺贝尔化学奖和诺贝尔医学奖外其余奖项获奖者的所有信息*/ +select * +from nobel +where yr = 1980 +and subject not in ('Chemistry','Medicine') ; +``` + + + +#### 聚合函数& group by + +group by的意义就是相当于创建了一个数据透视表,该透视表经过分组去重。然后方便根据数据透视表中选定的字段进行聚合运算。 + +group by 字段1, 字段2, 字段3 (顺序是有意义的) + +SQL SERVER中聚合函数主要有: + +```sql +count:求数量 +max:求最大值 +min:求最小值 +sum:求和 +avg:求平均值 +``` + + + +ROUND函数用法: + +```sql +round(num,len,[type]) +其中: +num表示需要处理的数字,len表示需要保留的长度,type处理类型(0是默认值代表四舍五入,非0代表直接截取) +select ROUND(123.45454,3) --123.45500 +select ROUND(123.45454,3,1) --123.45400 +``` + + + +#### SQL中常用的时间函数 + +```sql +select DATEDIFF(day, '2019-08-20', getDate()); --获取指定时间单位的差值 +SELECT DATEADD(MINUTE,-5,GETDATE()) --加减时间,此处为获取五分钟前的时间,MINUTE 表示分钟,可为 YEAR,MONTH,DAY,HOUR +select DATENAME(month, getDate()); --当前月份 +select DATENAME(WEEKDAY, getDate()); --当前星期几 +select DATEPART(month, getDate()); --当前月份 +select DAY(getDate()); --返回当前日期天数 +select MONTH(getDate()); --返回当前日期月数 +select YEAR(getDate()); --返回当前日期年数 + +SELECT CONVERT(VARCHAR(22),GETDATE(),20) --2020-01-09 14:46:46 +SELECT CONVERT(VARCHAR(24),GETDATE(),21) --2020-01-09 14:46:55.91 +SELECT CONVERT(VARCHAR(22),GETDATE(),23) --2020-01-09 +SELECT CONVERT(VARCHAR(22),GETDATE(),24) --15:04:07 +Select CONVERT(varchar(20),GETDATE(),14) --15:05:49:330 +``` + +**时间格式控制字符串:** + +| 名称 | 日期单位 | 缩写 | +| ------------ | ----------- | --------- | +| 年 | year | yyyy 或yy | +| 季度 | quarter | qq,q | +| 月 | month | mm,m | +| 一年中第几天 | dayofyear | dy,y | +| 日 | day | dd,d | +| 一年中第几周 | week | wk,ww | +| 星期 | weekday | dw | +| 小时 | Hour | hh | +| 分钟 | minute | mi,n | +| 秒 | second | ss,s | +| 毫秒 | millisecond | ms | + +#### 分组查询 group by + +1. 根据员工所在地区分组统计员工人数 ,员工工资总和 ,平均工资,最高工资和最低工资 +2. 根据员工所在地区分组统计员工人数,员工工资总和,平均工资,最高工资和最低工资,1985 年及以后出身的员工不参与统计。 +3. 根据员工所在地区分组统计员工人数,员工工资总和,平均工资,最高工资和最低工资,要求筛选出员工人数至少在2人及以上的记录,并且1985年及以后出身的员工不参与统计。 + +#### 多表查询 + +##### 简单多表 + +1. **查询员工信息,同时显示部门名称** +2. **查询员工信息,同时显示职级名称** +3. **查询员工信息,同时显示部门名称,职位名称** + +##### 内连接 题目同上 + +##### 综合示例 + +1. 查询出武汉地区所有的员工信息,要求显示部门名称以及员工的详细资料 +2. 查询出武汉地区所有的员工信息,要求显示部门名称,职级名称以及员工的详细资料 +3. 根据部门分组统计员工人数,员工工资总和,平均工资,最高工资和最低工资。 +4. 根据部门分组统计员工人数,员工工资总和,平均工资,最高工资和最低工资,平均工资在10000 以下的不参与统计,并且根据平均工资降序排列。 +5. 根据部门名称,然后根据职位名称,分组统计员工人数,员工工资总和,平均工资,最高工资和最低工资 + + + +**其他链接:左外连接,右外链接,自连接等** + + + diff --git "a/03\351\231\210\346\236\253/\347\254\224\350\256\260/20220904-SQL\351\253\230\347\272\247\347\254\224\350\256\260.md" "b/03\351\231\210\346\236\253/\347\254\224\350\256\260/20220904-SQL\351\253\230\347\272\247\347\254\224\350\256\260.md" new file mode 100644 index 0000000000000000000000000000000000000000..6f219ca53fa5ec1fa68a5ffab1dfb5f19a547847 --- /dev/null +++ "b/03\351\231\210\346\236\253/\347\254\224\350\256\260/20220904-SQL\351\253\230\347\272\247\347\254\224\350\256\260.md" @@ -0,0 +1,317 @@ + +# 数据库设计 + + + +### 信息收集 + +- 应用程序的业务有其针对性,数据库必然存储相关的数据 +- 该阶段的成果从很大程度上决定了将来数据库存储信息的数据结构和容量 +- 明确哪些问题必须关心,哪些问题不用去关心 + +### 建模 + +和面向对象的程序设计一样,在创建数据库之前,也是设计过程的初级阶段,我们需要为后面的主体工作做充分的准备,这些准备包括 + +- 与数据库相关的将来的应用程序的需求分析,主要是信息收集 +- 将这些信息归纳并用图形符号进行标识 + +### E(Entity实体)-R(Relationship关系)图基础 + +#### E-R图绘制步骤 + +![image-20220831183136743](image-20220831183136743.png) + +#### 实体对应关系 + +对应关系也叫影射基数,他指多个实体之间的数量比例关系。 + + + +1个学生 只在一个班级 + +1个班级有多个学生 + +![image-20220831183302254](image-20220831183302254.png) + +在描述关系时增加影射基数 + +![image-20220831183445955](image-20220831183445955.png) + + + +#### E-R图转换为关系模型 + +- 1对1: + - 可以转换为一个独立的关系模式 + - 可以与任意一端对应的关系模式合并,***在任意一方加入对方的主键*(主码)变为其外键(外码),并加入联系本身的属性**。 +- 1对n,n对1: + - 可以转换为一个独立的关系模式 + - 可以与n端对应的关系模式合并**,将1方的主键加入n方作为其外键**,**并将联系的属性也加入n方** +- m对n: + - 可以转换为一个独立的关系模式(新建一张关系表)**,将联系双方的主键(主码)加入其中,并将联系的属性也加入其中。** + +#### 范例: + +![image-20220831183739586](image-20220831183739586.png) + + + +1个用户 可以在 n主贴 发表言论 + +1个主贴 只有1个楼主 + + + +1个主贴有多个跟帖 + +1个跟帖只能在一个主贴下发表 + + + + + +#### 学生系统练习: + +1. 标识实体: + - 学生:代表一个唯一的学生 + - 班级:代表一个班级 +2. 标识属性: + - 学生:编号、姓名、性别,年龄,电话等 + - 班级:编号、名称、班主任、人数 +3. 确定关系: + - 这时候需要细致的分析,做出正确的判断 + - 甚至还需要对该行业的业务逻辑有一定的了解 + + + +最后的完整E-R图就是将来数据库的模型 + +![image-20220831183652683](image-20220831183652683.png) + +**模型转换** + +将数据模型,即E-R图转换为数据库表 + +![image-20220831183712113](image-20220831183712113.png) + +### **数据规范化** + +仅有好的RDBMS并不足以避免数据冗余,必须在数据库的设计中创建好的表结构。 + +Dr E.F.codd 最初定义了规范化的三个级别,范式是具有最小冗余的表结构。这些范式是: + +- 第一范式(1st NF -First Normal Fromate) +- 第二范式(2nd NF-Second Normal Fromate) +- 第三范式(3rd NF- Third Normal Fromate) + + + +#### 第一范式 (1st NF) + +- 第一范式的目标是**确保每列的原子性** +- 如果每列都是不可再分的最小数据单元(也称为最小的原子单元),则满足第一范式(1NF) + +![image-20220831183557091](image-20220831183557091.png) + + + +#### 第二范式 (2nd NF) + +如果一个关系满足第一范式,并且除了主键以外的其他列都依赖于该主键,则满足第二范式(2NF) + +![image-20220831183532105](image-20220831183532105.png) + +#### 第三范式 (3rd NF) + +如果一个关系满足第二范式,并且除了主键以外的其他列都依赖,且直接于主键列,则满足第三范式(3NF) + +订单表(n):订单编号,订购日期,顾客编号 + +顾客表(1):顾客编号,顾客姓名 + +1-->1 + +1--n + +![image-20220831183622900](image-20220831183622900.png) + +**练习** + +1.有如下表结构设计: + +```sql +create table Student --学生表 +( + StuId varchar(20) primary key,--学号 + StuName varchar(20) not null,--学生姓名 + StuContact varchar(50) not null, --联系方式 +) +insert into Student(StuId,StuName,StuContact) +values('001','刘备','QQ:185699887;Tel:13885874587') +select * from Student +``` + +2.有如下表结构设计: + +![image-20220901092024344](C:/Users/Administrator/AppData/Roaming/Typora/typora-user-images/image-20220901092024344.png) + +学生:stuno, stuName + +课程:courseno, courseName + +成绩表:score, 学生号,课程号(联合主键) + + + + + +```sql +--选课成绩表 +create table StudentCourse +( + StuId varchar(20),--学号 + StuName varchar(20) not null,--学生姓名 + CourseId varchar(20) not null,--课程编号 + CourseName varchar(20) not null, --选课课程名称 + CourseScore int not null, --考试成绩 +) +insert into StudentCourse(StuId,StuName,CourseId,CourseName,CourseScore) +values('001','刘备','001','语文',80) +insert into StudentCourse(StuId,StuName,CourseId,CourseName,CourseScore) +values('001','刘备','002','数学',70) +insert into StudentCourse(StuId,StuName,CourseId,CourseName,CourseScore) +values('002','关羽','003','英语',80) +insert into StudentCourse(StuId,StuName,CourseId,CourseName,CourseScore) +values('003','张飞','003','英语',90) + +``` + +3.有如下表结构设计: + +```sql +create table Student +( + StuId varchar(20) primary key,--学号 + StuName varchar(20) not null,--学生姓名 + ProfessionalId int not null,--专业编号 + ProfessionalName varchar(50),--专业名称 + ProfessionalRemark varchar(200), --专业介绍 +) +insert into Student(StuId,StuName,ProfessionalId,ProfessionalName,ProfessionalRemark) +values('001','刘备',1,'计算机','最牛的专业') +insert into Student(StuId,StuName,ProfessionalId,ProfessionalName,ProfessionalRemark) +values('002','关羽',2,'工商管理','管理学的基础专业') +insert into Student(StuId,StuName,ProfessionalId,ProfessionalName,ProfessionalRemark) +values('003','张飞',1,'计算机','最牛的专业') +select * from Student +``` + + + + + + + + + + + +#### 规范化实例 + +假设某建筑公司要设计一个数据库。公司的业务规则概括说明如下: + +- 公司承担多个工程项目,每一项工程有:工程号、工程名称、施工人员等 +- 公司有多名职工,每一名职工有:职工号、姓名、性别、职务(工程师、技术员)等 +- 公司按照工时和小时工资率支付工资,小时工资率由职工的职务决定(例如,技术员的小时工资率与工程师不同) +- 公司定期制定一个工资报表,如下图所示 + +![image-20220831183818803](image-20220831183818803.png) + +![image-20220831183837624](image-20220831183837624.png) + +1. 表中包含大量的冗余,可能会导致数据异常: + + - 更新异常 + + 例如,修改职工号=1001的职务,则必须修改所有职工号=1001的行 + + - 添加异常 + + 若要增加一个新的职工时,首先必须给这名职工分配一个工程。或者为了添加一名新职工的数据,先给这名职工分配一个虚拟的工程。(因为主关键字不能为空) + + - 删除异常 + + 例如,1001号职工要辞职,则必须删除所有职工号=1001的数据行。这样的删除操作,很可能丢失了其它有用的数据。 + + + +2. 采用这种方法设计表的结构,虽然很容易产生工资报表,但是每当一名职工分配一个工程时,都要重复输入大量的数据。这种重复的输入操作,很可能导致数据的不一致性。 + + + +**规范化实例-1NF** + +一张表描述了多件事情,如图-3所示。 + +![image-20220831183902104](image-20220831183902104.png) + +**规范化实例-2NF** + +![image-20220831183921784](image-20220831183921784.png) + +**规范化实例-3NF** + +![image-20220831183941544](image-20220831183941544.png) + + + + + + + + + + + + + +一定要使用三范式吗? + +例如:查询编号1001的员工的姓名和8月份工资总额 + + + + + +### 习题 + +1. 数据库E-R图设计(cdm,pdm):某教学管理系统涉及教员、学生、课程、教室四个实体,他们分别具有下列属性: + + 教师:教室号, 姓名,年龄,职称 学生:学号、姓名、年龄、性别 + + 课程:课程号、课程名、课时数 教室:教室编号、地址 + + 这些实体间的联系如下:一个教师可讲授多门课程,一个课程只能被一个教师讲授:一个学生选修多门课程,每门课程有多个学生选修,学生学习有成绩,一门课只在一个教室上,一个教室可上多门课。 + + 请画出教员,学生,课程,教室的E-R图 + +2.**业务需求说明:** +模拟银行业务,设计简易版的银行数据库表结构,要求可以完成以下基本功能需求: +1.银行开户(注册个人信息)及开卡(办理银行卡)(一个人可以办理多张银行卡,但是最多只能办理3张) +2.存钱 +3.查询余额 +4.取钱 +5.转账 +6.查看交易记录 +7.账户挂失 +8.账户注销 + +**表设计:** + +1.账户信息表:存储个人信息。 +2.银行卡表:存储银行卡信息。 +3.交易信息表(存储存钱和取钱的记录) +4.转账信息表(存储转账信息记录) +5.状态信息变化表(存储银行卡状态变化的记录,状态有1:正常,2:挂失,3:冻结,4:注销) +