title: "Sql"
date: 2019-08-06T17:15:49+08:00
本章内容为:《SQL基础》
作者:nuoccc
这篇文章 主要是进行 最基础的SQL语法学习,感兴趣的可以看看。
首先我们常用的数据库模型就是关系数据库:由一张二维的表构成,表的列表示字段(属性),一行表示其中
的一条记录。
然后我们常见的数据库有:
- Oracle
- MySql
- DB2
- SQL Server
- sqlite
SQL语句分类 :
- DDL(Data Definition Language):数据定义语言,用来定义数据库对象:库、表、列等。
- DML(Data Manipulation Language):数据操作语言,用来定义数据库记录(数据)。
- DCL(Data Control Language):数据控制语言,用来定义访问权限和安全级别。
- DQL(Data Query Language):数据查询语言,用来查询记录(数据)。
我使用的是MySQL,其他数据库我也我不太了解,所以本篇文章只针对MySQL,其他数据库可能不全部适用。
一丶 创建数据库表
首先我们来学如果创建数据库表:
也就是我们SQL语句的DDL,用来定义数据库对象:库、表、列等。
create database db_name character set utf8 collate uft8_general_ci;
-- 创建一个字符集为utf-8的数据库,db_name是你自己要定义的数据库名字
alter database db_name character set gbk;
-- 选择数据库 并把字符集改为GBK编码,这里只是告诉这么用 没必要换成GBK
drop database db_name;
-- 删除数据库,drop 是删除关键字 一定要记住
use db_name;
-- 选择你要使用的数据库
数据库的定义学完后,我们选择当前创立的数据库,然后开始添加数据库表
再添加数据库表前,先了解一下数据库的类型定义,以下是引用w3school中的定义,大概看下就好,不是全部
都会使用:
在 MySQL 中,有三种主要的类型:文本、数字和日期/时间类型。
Text 类型:
数据类型 | 描述 |
---|---|
CHAR(size) | 保存固定长度的字符串(可包含字母、数字以及特殊字符)。在括号中指定字符串的长度。最多 255 个字符。 |
VARCHAR(size) | 保存可变长度的字符串(可包含字母、数字以及特殊字符)。在括号中指定字符串的最大长度。最多 255 个字符。注释:如果值的长度大于 255,则被转换为 TEXT 类型。 |
TINYTEXT | 存放最大长度为 255 个字符的字符串。 |
TEXT | 存放最大长度为 65,535 个字符的字符串。 |
BLOB | 用于 BLOBs (Binary Large OBjects)。存放最多 65,535 字节的数据。 |
MEDIUMTEXT | 存放最大长度为 16,777,215 个字符的字符串。 |
MEDIUMBLOB | 用于 BLOBs (Binary Large OBjects)。存放最多 16,777,215 字节的数据。 |
LONGTEXT | 存放最大长度为 4,294,967,295 个字符的字符串。 |
LONGBLOB | 用于 BLOBs (Binary Large OBjects)。存放最多 4,294,967,295 字节的数据。 |
ENUM(x,y,z,etc.) | 允许你输入可能值的列表。可以在 ENUM 列表中列出最大 65535 个值。如果列表中不存在插入的值,则插入空值。注释:这些值是按照你输入的顺序存储的。可以按照此格式输入可能的值:ENUM('X','Y','Z') |
SET | 与 ENUM 类似,SET 最多只能包含 64 个列表项,不过 SET 可存储一个以上的值。 |
Number 类型:
数据类型 | 描述 |
---|---|
TINYINT(size) | -128 到 127 常规。0 到 255 无符号*。在括号中规定最大位数。 |
SMALLINT(size) | -32768 到 32767 常规。0 到 65535 无符号*。在括号中规定最大位数。 |
MEDIUMINT(size) | -8388608 到 8388607 普通。0 to 16777215 无符号*。在括号中规定最大位数。 |
INT(size) | -2147483648 到 2147483647 常规。0 到 4294967295 无符号*。在括号中规定最大位数。 |
BIGINT(size) | -9223372036854775808 到 9223372036854775807 常规。0 到 18446744073709551615 无符号*。在括号中规定最大位数。 |
FLOAT(size,d) | 带有浮动小数点的小数字。在括号中规定最大位数。在 d 参数中规定小数点右侧的最大位数。 |
DOUBLE(size,d) | 带有浮动小数点的大数字。在括号中规定最大位数。在 d 参数中规定小数点右侧的最大位数。 |
DECIMAL(size,d) | 作为字符串存储的 DOUBLE 类型,允许固定的小数点。 |
* 这些整数类型拥有额外的选项 UNSIGNED。通常,整数可以是负数或正数。如果添加 UNSIGNED 属性,那么范围将从 0 开始,而不是某个负数。
Date 类型:
数据类型 | 描述 |
---|---|
DATE() | 日期。格式:YYYY-MM-DD注释:支持的范围是从 '1000-01-01' 到 '9999-12-31' |
DATETIME() | *日期和时间的组合。格式:YYYY-MM-DD HH:MM:SS注释:支持的范围是从 '1000-01-01 00:00:00' 到 '9999-12-31 23:59:59' |
TIMESTAMP() | *时间戳。TIMESTAMP 值使用 Unix 纪元('1970-01-01 00:00:00' UTC) 至今的描述来存储。格式:YYYY-MM-DD HH:MM:SS注释:支持的范围是从 '1970-01-01 00:00:01' UTC 到 '2038-01-09 03:14:07' UTC |
TIME() | 时间。格式:HH:MM:SS 注释:支持的范围是从 '-838:59:59' 到 '838:59:59' |
YEAR() | 2 位或 4 位格式的年。注释:4 位格式所允许的值:1901 到 2155。2 位格式所允许的值:70 到 69,表示从 1970 到 2069。 |
* 即便 DATETIME 和 TIMESTAMP 返回相同的格式,它们的工作方式很不同。在 INSERT 或 UPDATE 查询中,TIMESTAMP 自动把自身设置为当前的日期和时间。TIMESTAMP 也接受不同的格式,比如 YYYYMMDDHHMMSS、YYMMDDHHMMSS、YYYYMMDD 或 YYMMDD。
看完MySQL中关于数据类型的定义,接下来我们就可以来创建表了
create table table_name;
-- 创建一个表,table_name是你自己定义的表明
create table table_name
(
/*
属性1 类型 约束,
属性2 类型 约束,
...
属性n 类型 约束
这种方法其实更实用,初始定义里面的属性。
*/
)ENGINE=InnoDB DEFAULT CHARST=uf8;
-- 最后一句话定义引擎 已经字符集
show tables;
-- 查看数据库中所有的表
desc table_name;
-- 显示当前表的字段信息
alter table table_name add 属性 数据类型 约束;
/* 用于创建表后再加数据
例如 alter table test add name varchar(20) not null;
给名为test的表添加了一条name属性 长度为20的可变字符串 该属性不能为空,not null就是一种约束。
*/
alter table table_name modify 属性 数据类型 新约束;
-- 用于修改之前定义的约束,modify 修改
alter table table_name drop 属性;
-- 从表中删除这个属性
drop table table_name;
-- 删除整个表
这些就是表的创建操作
二丶约束
之前在定义表的时候,我们发现创建一条数据除了需要数据名也就是属性,数据类型之外,还需要一个约束;
所以我们就来看看什么叫做约束。
-
非空约束:
NOT NULL表示非空约束,定义了此约束后,该属性就不能为NULL,MySQL中默认为NULL,所以当你想让表的属性为非空时,就需要定义非空约束。
-
默认:
DEFAULT 可以给属性添加一个默认值,例如:
alter table test add name varchar(20) default '测试1';
使用上面这条命令后,以后你插入数据时,如果不定义name的值,就会默认为'测试1'而不再是NULL。
-
唯一约束:
UNIQUE,使用此约束后,代表该属性的值不能重复,也就是说你后面插入的数据,同一属性只能有唯一值。
-
主键约束:
PRIMARY KEY,使用该约束后,自动默认这个属性是非空不可重复,因为加上主键约束后,就代表这个属性
是唯一的,能直接识别出实体,例如一个人的属性有姓名,年龄,身份证号,只有身份证号是唯一的,其他都可能跟他人有重复的,所以我们主键一般也用于定义id之类的能代表唯一的数据。
-
自动递增:
AUTO_INCREMENT,以初始值为1,每次增加1,但需要配合主键使用,一般也使用于id之上。
但要注意 例如我创建了五条数据:
id
1
2
3
4
5
如果我创建第六条数据失败,或者是我创建第六条数据后又对他进行删除操作,这个从操作后的加,
就比如我现在id是5,操作之后id就会变成6,不管是失败还是后面删除了,下一条id就会从7开始加,
为了想要连续的id我们一般进行完这类操作后,可以自己给id赋值,这样就会从赋值的继续开始递增。
-
外键约束:
实体间的关联关系分为四种:
一对一:例如夫妻,一个男的只能拥有一个妻子。
一对多:比如一个班的学生,学生有很多个,但这个班只有一个。
多对一:反过来理解罢了,本质跟第二个是一样的。
多对多:就比如 一个学生的老师 可能有很多个,同理一个老师教的学生也有很多个。
了解完关联关系后,在我们表中 各各表也存在这种关系。
我们之前知道了主键可以确定一个实体,那我们其他表想用这个实体怎么办,这时候就需要引入外键。
外键的作用就是在另外的表指定,你就是那个实体。
具体用法为:
create table roles -- 创建一个角色表(主键表) ( id int primary key auto_increment, name varchar(20) not null ); /* id name 1 管理员 2 学生 3 教师 这里我们假设插入这三条数据 */ //用户表(外键表) create table users ( id int primary key auto_increment, name varchar(20) not null, pwd varchar(20) not null, role_id int, -- 外键 foreign key(role_id) references roles(id) /* 这里我们创建了外键role_id,然后我们指明这个键key(role_id)是引用的(references) roles表中的id,这样定义了外键之后,我们当前的这个role_id就代表了roles的id,如果 你插入数据比如我插入一个role_id=4,这时候就会报错,因为我们roles的id只有1-3。 */ );
三丶数据库表插入数据
学完了我们的DDL语句后,我们来学习DML语句,也就是对表中的数据进行增加,删除,修改的操作。
INSERT INTO TABLE_NAME(属性1,属性2,属性3...)VALUES(值1,值2,值3...);
/*
插入数据语句,具体用法如下:
例如我已经创建了一个表 如下
test(表名)
id name age
我要插入响应的数据就应该使用以下语法:
insert into test(id,name,age) values(1,'小明',20);
就会生成以下数据:
test
id name age
1 小明 20
如果要对表中一行数据的所有属性赋值,可以省略前面的,例如:
insert into test values(2,'小花',21);
*/
UPDATE TABLE_NAME SET 属性1=新值1,属性2=新值2,属性3=新值3,...[WHERE 条件]
/*
更新语句,具体用法如下:
在上一个插入语句注释之后,我们的表应该是这个样子
test
id name age
1 小明 20
2 小花 21
如果我们要更新第二条数据,例如名字写错了应该是'小华'而不是'小花',这时候就可以使用更新语句如下:
UPDATE TEST SET NAME='小华' where id=2;
*/
DELETE FROM TABLE_NAME [WHERE 条件]
/*
删除一条数据,具体用法如下:
我们现在表应该是这个样子:
test
id name age
1 小明 20
2 小华 21
如果我们觉得第二条数据现在不需要了,就可以删除语句:
delete from test where name='小华';
这样就会删除名字是小华的数据,表现在就会如下:
test
id name age
1 小明 20
再删除语句中,还有个语句也能删除TRUNCATE TABLE TABLE_NAME
这个语句不需要加条件,因为它是把整张表删除了,然后在创立了一个属性跟原来表一样的新表,
跟delete最大的区别在于,delete其实删除的东西有点像我们windows删数据丢入垃圾回收站,
里面删除的数据,其实我们是能找回来的,而truncate删除的东西,我们找不回来,其实不是找不回来,
只是没那么容易找回来,当然truncate也有好处,就是效率比delete快。
*/
四丶数据库表查询语言
之前的语言我们学完了,最后来学学DQL,也就是数据查询语言,对数据库表进行检索查询。
语法如下
select 属性1,属性2,属性3...from table_name [where 条件] [group by 属性][having 分组条件][order by 需要排序的属性 规则][limit 偏移量,每页总数];
/*
这里面
where:代表条件查询
group by:代表分组查询
having:代表分组条件
order by:代表排序
limit:分页查询
*/
然后我们来细看这些查询使用方法:
简单查询:使用“*”来表示所有的列
-
条件查询:再查询时使用关键字where 跟上条件,可使用以下关键字及运算符:
最常见的比较可以使用:= , != , <> , < , <= , > , >=;
还能使用:between...and(在什么之间),in(set)(在指定的范围内),is null/is not null(是否为空) , and(与) ,
or(或) , not(非)。
-
模糊查询:根据关键字进行查询
语法为:
select * from table_name where 属性 like 关键字
这里关键字一般是通过通配符来进行描速的,
通配符有:"_"(匹配单个任意字符) , "%"(匹配0个以上的任意字符)
例如我们查询一个人的名字: 1)这个人叫张某三(例如:张一三,张二三...) select * from table_name where name like "张_三"; /*"_"相当于理解为一个占位符,任何元素都能满足*/ 2)一个人 名字叫张xx三,xx个数不定(例如:张三,张一三,张一一三,张二三...) select * from table_name where name like "张%三"; 3)一个人的名字包含"张三"(例如:李张三,王张三,张三,王张三二...) select * from table_name where name like "%张三%";
去掉重复数据: distinct,只能写在开头,并且只能去重一个属性,不能多属性
处理null值:ifnull(属性,为null后设置的值),代表如果这个属性原本是null,现在可以赋值来覆盖。
-
列别名:as(可省略),用来把搜索到的属性那一列换个名字,
例如:select name 姓名 from table_name 这样搜索出来的表 列名name就会变成姓名
排序:order by 属性 [asc|desc] (asc:升序排序,默认 desc:降序排序)
-
分组统计:
I.聚合函数
聚合函数是用来做纵向运算的函数:
COUNT():统计指定列不为NULL的记录行数;
MAX():计算指定列的最大值,如果指定列是字符串类型,那么使用字符串排序运算;
MIN():计算指定列的最小值,如果指定列是字符串类型,那么使用字符串排序运算;
SUM():计算指定列的数值和,如果指定列类型不是数值类型,那么计算结果为0;
AVG():计算指定列的平均值,如果指定列类型不是数值类型,那么计算结果为0;
II.分组查询
当需要分组查询时需要使用GROUP BY子句,例如查询每个部门的工资和,这说明要使用部分来分组。注:凡和聚合函数同时出现的列名,则一定要写在group by 之后
-
(9)分页查询
语法:
select * from 表名 limit 偏移量,每页总数;假如curPage为当前页码,maxSize为每页总数,偏移量计算公式:
offset=(curPage-1)*maxSize;