SQL
基础—高级
我们怎么存储数据
以前用各种书籍载体在上面按照特定的格式记录信息,就像现在的excel表格,
但是,如果当数据有几千万条的时候,查询就非常慢了
所以我们需要一种高效的解决方案:数据库(其实也是操作一种特殊格式的文件)
数据库不仅仅要存储数据,还要提供方便快捷的查询,修改,删除等功能
需要做到:海量存储,快速查询,多用户同时查询,用户访问安全性,数据存储完整性(正确性)等
?
什么是数据库
数据的仓库,货仓里有很多货架(库文件),货架有不同的种类,不同的架子放不同的货物,
管理仓库的就管理员就对应DBA
数据如何存储
?
?
数据库概述
数据库软件:
现在市面上有很多种数据库:mssqlserver,oracle,db2,access, SQLite等
mssqlserver是微软出品的,大型数据库,和net结合度很高
oracle是甲骨文公司,被谷歌收购了,大型数据库,注重数据安全性
db2也是一个大型数据库
access是微软的一个小型文件数据库,在office套件中
?
数据库实例:用来区别数据库引擎的名字,如果不写那就是默认的"MSSQLSERVER"
SUNCODERBOOK 机器名
115.21.23.58 IP地址
?
验证方式:
windows验证:使用登陆windows的账号和密码
sqlserver验证:填写账号和密码,
????????
?
此错误是没有开数据库服务
?
数据库文件:磁盘上的文件
?
数据库服务:这个才是真正的数据库
数据库运行简易流程
成功安装完数据库之后,会有一个"SQL Server Management Studio",
打开这个软件即可操作数据库,
但真正的数据库并不是这个软件,是系统内一个没有界面的服务程序,
由这个管理工具,发送指令操作这个服务,然后服务操作硬盘上一个".mdf"数据库文件
数据就是存在这个mdf文件里的
数据库中的概念
- 我们所使用的如,mssqlserver oracle等数据库软件
- 打开数据库管理软件可以看到的一个一个实际存放数据的集合
?
建库:建立数据库
注:一个数据库不仅仅只能是一个数据文件和一个日志文件,
?
表概念:在一个数据库(上述第二种概念),如同仓库里面的货架一样,不同的数据放在不同的表里面,根据放的数据不一样,对使用空间进行优化
列,行概念:一张表里面的每一项,就是表示这个表要包含写什么类型的数据,列叫做字段
这张表包含 编号 用户名 用户密码 三列
一共有3条数据 每一行就是一条数据
SQLServer的管理
安装好数据库后,可以使用自带的数据库管理工具进行管理,也可以使用visusl studio进行管理,也可以使用cmd命令管理,
用管理工具管理需要连接数据库
服务器类型:数据库不仅仅只有数据库引擎,还有其他的引擎,数据库引擎就是以存储数据为主要功能的程序核心
à服务器名称:服务器的地址,如果是网络线上服务器,填写这个服务器的ip地址,开发的时候一般数据库就装在本机上,所以这里可以直接填写计算机名字或者是实例名字
à实例名:同一台服务器用来区分多个运行的数据库引擎的名字,开发的时候一般只有一个实例,所以填写"."就可以了,如果安装的数据库版本是express版本的话那么就是"./express"
à身份验证:登陆数据库的验证模式
windows 身份验证,就是使用本机当前登陆的用户的账号密码登陆,
sqlserver身份验证,就是使用安装时或安装后自定义的一个账号和密码登陆
以上两种模式,在数据库安装的时候会有选项供选择
创建数据库
用管理工具连接上数据库之后,在对象资源管理器上右键,有新建数据库选项,点击打开窗口,填写相关信息
住:初始大小,路径
选项中:兼容级别
?
展开新建的表:在"表"上右键,有新建表选项,
?
?
数据类型
工资:monney类型
分类 |
备注和说明 |
类型 |
说明 |
二进制数据类型 |
存储非子符和文本的数据 |
Image |
可用来存储图像 |
文本数据类型 |
字符数据包括任意字母、符号或数字字符的组合 |
Char,8000 |
固定长度的非 Unicode 字符数据。固定长度的字符串相对于可变长度的字符串来说效率要高一些,在数据长度固定的情况下优先选用固定长度,省去了计算长度的过程,提高效率 |
Varchar,8000 |
可变长度非 Unicode 数据 |
||
Nchar,4000 |
固定长度的 Unicode 数据 |
||
Nvarchar,4000 |
可变长度 Unicode 数据 |
||
Text varchar(max) |
存储长文本信息(指针,2G) varchar(max),大字符串类型可以保存非常多的字符,但是对于这种类型的数据DBMS经常将它们保存到单独的空间中,这就导致了数据的保存和加载速度比较慢,因此除非必要,否则不要使用。 |
||
Ntext nvarchar(max) |
Nvarchar(max)代替 |
||
日期和时间 |
日期和时间在单引号内输入 |
Datetime |
日期和时间 |
数字数据 |
该数据仅包含数字,包括正数、负数以及分数 |
int smallint |
整数 |
Float 小数,单精度 real |
数字 |
||
货币数据类型 |
用于十进制货币值,money 和 smallmoney 数据类型精确到它们所代表的货币单位的万分之一。 |
Money(C#:double) 双精度 |
? |
Bit数据类型 |
表示是/否的数据 |
Bit bool |
存储布尔数据类型(1-true 0-false) |
Char,8000 固定长度 非unicode
Varchar,8000 可变长度 非unicode
Nchar,4000 固定长度 unicode
Nvarchar,4000 可变长度 unicode
?
如果实际开发中,对于位数能确定的数据,就用固定长度的
如果有中文的,要用unicode
?
身份证号:18位 ,数字,字母,
银行卡:19 数字, char
?
?
?
?
不允许保存修改,要求重新创建,
?
Unicode 是用两个字节表示一个字符
工具-选项—设计器-去掉勾"阻止保存"
主键(PrimaryKey)
主键的作用
业务主键:
逻辑主键
表间关联、外键(ForeignKey)
为什么要有主外键 示例见批注
?
>练习
- 创建一个HeiMaBlog数据库。
-
创建一个班级表:Class:
- Id (班级编号,自动编号,主键)、
- Name(班级名称)、
- Descr(班级简介)。
-
创建一个学生信息表:Student
- Id(学生编号,自动编号,主键)、
- Name(学生姓名)、Gender(性别)、
- Address(家庭地址)、Phone(电话)、
- Age(年龄)、Birthday(出生日期)、
- CardId(身份证号)、CId(班级Id)
-
分离数据库
- 在需要分离的数据库上点右键-任务-分离
-
附加数据库(在其他计算机上,亲自测试!)
- 在数据库节点上点右键-附加
- 打开数据之前,要打开数据库服务
?
SQL语句入门(脚本、命令)
什么是sql语句
?
使用sql语句创建数据库和表
CREATE DATABASE HeiMaBlog
ON PRIMARY --默认就属于PRIMARY主文件组,可省略
(
NAME=‘HeiMaBlog‘, --主数据文件的逻辑名
FILENAME=‘D:\ HeiMaBlog_data.mdf‘, --主数据文件的物理名
SIZE=5mb, --主数据文件初始大小
MAXSIZE=10mb, --主数据文件最大的值
FILEGROWTH=15% --主数据文件的增长率
)
LOG ON -- 日志文件
(
NAME=‘HeiMaBlog_log‘,
FILENAME=‘D:\HeiMaBlog_log.ldf‘,
SIZE=3mb, --日志文件初始大小
MaxSize=20mb,
FILEGROWTH=1MB
)
GO
主数据文件名和日志文件名不能一样,主数据文件大小最小是5MB,日志文件最小是1MB
?
"GO"关键字是明确告诉管理工具,先把上面的代码执行了,然后在执行下面,该关键字不处于sql语法本身
USE HeiMaBlog--将当前数据库设置为HeiMaBlog
GO
CREATE TABLE Score
(
ScoreId INT IDENTITY(1,1),
SId INT NOT NULL ,
English INT NOT NULL,
Math INT NOT NULL
--Name Varchar(50) not null
)
?
>创建表练习
- 创建数据库TestSchool
- 创建学生成绩表ScoreScoreId(成绩id,主键,自动编号)、SId(学生编号)、English(英语成绩)、Math(数学成绩)
- 创建老师表Teacher
- Id、Name、Gender、Age、Salary、Birthday
?
create table Teacher
(
Id int identity(1,1),
Name nvarchar(10) not null,
Gender bit not null default 0,
Age int not null default 10,
Salary money not null,
Birthday datetime not null default getdate(),
)
?
增删查改
数据插入
insert into students values(null,‘new‘,‘男‘,0,getdate())
default
nvarchar N,
set identity_insert teacher off
数据更新(数据修改)
- Where子句,用id查找,速度快;可以用查询计划按钮来对比,消耗的资源。
- ★and优先于or执行
- set age=age+1;
- 空值的判断where address=NULL → is null,is not null
- 不等于号:<> ,!=两种都可以
- ?
数据删除
delete truncate
drop table Teacher
>练习:
- 插入 几条老师信息 和成绩(注意:bit类型)
- 练习1:给studentId是1的英语成绩加10分
- 练习2:考试题偏难,所有人的成绩加5分
- 练习3:所有女学生的年龄减1岁
- 删除工资大于2000的老师
- ============将老师表清空========
- 删除所有老师
- 删除数据时候 把自增长列的值还原成种子
?
约束-保证数据完整性(数据检查)
非空约束
????建表的时候每一个字段后面的null复选框
?
主键约束(PK) primary key constraint
????设置主键就可以了,数据不重复 且 不能为空
?
唯一约束 (UQ)unique constraint
唯一 允许为空,但只能出现一次
右键"索引/键"里面有
?
默认约束 (DF)default constraint 默认值
????建表设置默认值的时候就添加了这个约束
?
检查约束 (CK)check constraint 范围以及格式限制
????在表的设计界面,在字段上右键,有check约束
????
?
外键约束 (FK)foreign key constraint 表关系:保证外键值来源于主键
增加外键约束时,设置级联更新、级联删除:
[ ON DELETE { NO ACTION | CASCADE | SET NULL | SET DEFAULT } ]
[ ON UPDATE { NO ACTION | CASCADE | SET NULL | SET DEFAULT } ]
?
>练习
-
Teacher表中
- Gender 控制只能是男 女,默认女
- Age 在30-40之间 默认30
- Score表中
- studentId 是外键 先要把Student表中的sId设置为主键
- 测试外键约束:
- 1:在学生表(主表)中删除在成绩表中被引用的学生记录。
- 2:成绩表中添加一条新成绩,studentId在 学生表中没有。
- 保存SQL脚本。再次打开即可执行。
?
数据检索 Select
最基本的检索代码
- 取别名,AS
- 查询无关数据库信息:select getdate()
- order by;desc,asc;汉字排序:用拼音的首字母a-z;多个排序一个个执行,就像嵌套????
- ?
区间条件的查询
- 《 between in
between 。。and。。。:数据库效率,在数据库内部做过特殊优化的;优先使用;。。。范围表识相当于>=,<=
- 分页算法:select * from dbo.strdent where between (num-1)*5+1 and 5*num
- In:select *from dbo.studeent where cid=1 or cid=2比较select *from dbo.studeent where cid in (1,2)
- ?
?
Top、Distinct
select top 10 * from Teacher
查出前面10行
select top 20 percent * from Teacher
查出前面20%的数据
select distinct(age) from teacher
查询年龄列,但只要不重复的
select distinct age,name from teacher
查询两个列都不重复的,可以有其中一个是相等的
distinct:去除重复数据,是针对查询结果去除重复行;distinct先于top执行,也要写在top前面。
聚合函数
max, min, avg, count ······
- 聚合函数,max(age),不能跟列字段一起查询;
- min,avg,sum;count查询满足条件的条数;
- where子句先执行;聚合函数对NULL值不计算,唯有id非空,可以做文章;
- 如果max(Name),查询的是首字母顺序最大的,min最小
?
?
模糊查询(都是针对字符串操作的)
% _ [] ^ not like
- 模糊查询:like ; not like
- _:一个任意字符;
- %:零个或任意多个字符;
- []:代表一个字符的取值区间;
- ^:结合[]的非运算;
- 查询里面不区分大小写
空值处理
Is null
- isnull...可以判断后面的是否可为null,如果为null就用第二个参数代替;is not null
数据排序
AES DESC 汉字
- 数据排序:where子句放在order by前面,想原因,效率?
数据分组
- 查询的结果集里是分组信息,不再是表里的行信息。
- 数据分组:group by ;可以取到分组根据的信息、可以取到聚合函数信息;返回的是每个组的汇总信息
一个班级一张表,然后有个小组表,小组的表的信息只有"一组,二组,三组"这些信息,没有组员名字,年龄等信息,
一个小组包含多个组员的信息,要知道小组的名字,不知道到底要拿哪一个显示
根据"什么"分组,那么可以想象这个分组的名字就是"什么"
Having语句
- 为分组结果 筛选
- having子句:针对于分组之后的信息进行筛选过滤。对比where子句是对分组之前原来的表信息进行筛选。
SQL语句的执行顺序
5>…Select 5-1>选择列,5-2>distinct,5-3>top
1>…From 表
2>…Where 条件
3>…Group by 列
4>…Having 筛选条件
6>…Order by 列
从某某表查询大于多少小于多少的数据,然后根据某某分个组,筛选下不想要的组
?
>Group by 练习
-
从orders表中查询:
- 1.热销售商品排名表,即按照每种商品的总销售数量排序。
- 2.请统计销售总价超过3000元的商品名称和销售总价,并按销售总价降序排序。
- 3.统计各个客户对"可口可乐"的喜爱度(既统计每个购买人对"可口可乐"的购买量)
?
类型转换函数
CAST CONVERT
- select isnull(cast(age as nvarchar(10)),‘保密‘) from student;
- ????convert(varchar(20),getdate(),105);--105是样式标志
联合结果集union(集合运算符)
Union all
使用注意点:
- 同的列数;列有相同的数据类型(相容、可以进行隐式转换);
- 列名由第一个集合确定;
- Union会去除重复项,union all则不会去除
- 联合查询,只能有一个order by子句,这个order by子句是针对整个联合查询的,最后执行。
案例1
要求在一个表格中查询出学生的英语最高成绩、最低成绩、平均成绩
建库脚本à
案例2
查询每位老师的信息,包括姓名、工资,并且在最后一行加上平均工资和最高工资
建库脚本à
一次插入多条数据
- 将结果集作为值插入数据库。
- 结果集的列数量、类型都要一样。
- 一种用select结果集,另外用select联合结果集
- select * into score2 from score where 1<>1
字符串函数(*)
declare @str varchar(10) = ‘ aa ‘
定义一个变量,并且赋值
select LTRIM(@str)--aa --
- 去除左空格
union all
select CONVERT(varchar,DATALENGTH(LTRIM(@str)))—5
- 去除空格后的字节长度
union all
select RTRIM(@str)-- aa-
- 去除右空格
union all
select CONVERT(varchar,DATALENGTH(RTRIM(@str)))—5
- 去除右空格后的字节长度
union all
select LTRIM(RTRIM(@str))--aa—
- 去除右空格又去除左空格
union all
select CONVERT(varchar,DATALENGTH(LTRIM(RTRIM(@str))))--2
- 去除两边空格后字符数
select left(‘abcdefg‘,3)--abc
- 从左向右取3个字符
select right(‘abcdefg‘,3)--efg
- 取最右边的三个字符
select SUBSTRING(‘abcdefg‘,3,4)--cde
- 索引从1开始从第三个字符截取四个长度
select SUBSTRING(‘abcdefg‘,3,40)--cdefg
9.1 从第三个字符截取四十个长度,长度不足,不会报错
select SUBSTRING(‘abcdefg‘,30,40)
9.2 从第三十个字符截取四十个长度,长度不足,不会报错
补充:
- 字符串函数:select len();字符串长度,
- select datalength(),求字节数,一个空格、数字和字符一个字节,一个汉字两个字节,中文标点符号两个字节,英文标点符号一个字节。
- select lower(),select upper()
- ?
?
日期函数
select GETDATE()--2013-02-27 10:25:32.532
获取当前日期
select DATEADD(day,2,getdate())--2013-03-01 10:27:327
在现有基础上加上两天
select DATEDIFF(day,‘2012-05-05‘,GETDATE())--298
取得日期的特定部分
select DATEPART(year,getdate())--2013
select DATEPART(MONTH,GETDATE())--2
select DATEPART(day,GETDATE())--27
select DATEPART(hour,getdate())--10
select DATEPART(minute,GETDATE())--43
select DATEPART(SECOND,GETDATE())--14
select DATEPART(MILLISECOND,GETDATE())--817
?
select * from users where DATEPART(year,dat)=1990
>练习
- 创建一张表,记录电话呼叫员的工作流水,记录呼叫员编号、对方号码、通话开始时间、通话结束时间。建表、插数据等最后都自己写SQL语句。
-
要求:
- 输出所有数据中通话时间最长的5条记录
- 输出所有数据中拨打长途号码(对方号码以0开头)的总时长
- 输出本月通话总时长最多的前三个呼叫员的编号。
- 输出本月拨打电话次数最多的前三个呼叫员的编号
- 按照月份分组。
建库脚本à
?