SQL基础

CURD、约束、事务 相关

增查删改(CURD)

数据库连接:
MySQL本地数据库:mysql -u userName -ppassWord
MySQL远程数据库:mysql -h IP_Address -p 3306(port,默认3306) -u userName -ppassWord
-p后面的密码不要有空格,或者-p后直接连接,会提示输入密码

DDL(Data Definition Language)数据定义语言

用来定义数据库对象:数据库,表,列等。关键字:create(创建) drop(删除) alter(修改) truncate(清空数据记录) show等

Create
创建
创建数据库的三种方式:
CREATE DATABASE databaseName
CREATE DATABASE IF NOT EXISTS databaseName
CREATE DATABASE databaseName character set 字符集

创建表(创建表时需要正在使用一个数据库):
CREATE TABLE 表名 (字段名 字段类型,字段名 字段类型,...);
快速创建一个结构相同的表:CREATE TABLE newTableName LIKE oldTableName

MySQL中常用数据类型:
类型 | 描述
| :-: | :-: |
| int | 整型|
| double | 浮点型 |
| varchar | 字符串 |
| date | 日期类型,格式为yyyy-MM-dd,只有年月日,没有时分秒 |

例子:

CREATE TABLE student (
      id INT,
      name VARCHAR(20),
      birthday DATE
);

Show
查看所有数据库:SHOW DATABASES
查看数据库创建信息:SHOW CREATE DATABASE databaseName

查看所有表:SHOW TABLES
查看表结构:DESC tableName
查看创建表的SQL语句:SHOW CREATE TABLE tableName

Desc
describe:形容,描述
查看表结构:DESC tableName

Alter
修改
修改表字符集:ALTER TABLE tableName character set utf8
修改数据库字符集:
ALTER DATABASE databaseName character set utf8;//修改字符编码为utf-8
注意不要写错单词!是Database不是Datebase,Data是数据,Date是日期,更新是update,新旧当然是和日期有关 --一个拼错却找不出bug的菜鸟的碎碎念
编码:

类型 - - - -
Java中的常用编码 UTF-8 GBK GB2312 ISO-8859-1
对应mysql数据库中的编码 utf8 gbk gb2312 latin1

修改表结构(不常用):
添加表列:ALTER TABLE tableName ADD 字段名 类型
修改列类型:ALTER TABLE tableName MODIFY 字段名 新类型
修改列名:ALTER TABLE tableName CHANGE 旧字段名 新字段名 类型
删除列:ALTER TABLE tableName DROP 字段名
Rename:修改表名:RENAME tableName TO newTableName

Drop
删除
删除数据库:DROP DATABASE databaseName

删除表:DROP TABLE tableName
判断表是否存在并删除表:DROP TABLE IF EXISTS tableName

删除所有数据:TRUNCATE TABLE tableName(删除该表并创建相同结构的新表)

Select
选择(查询)
查看正在使用的数据库:SELECT DATABASE();

Use
使用/切换数据库:USE databaseName

DML(Data Manipulation Language)数据操作语言(重点)

在数据库表中更新,增加和删除记录。如 update(更新), insert(插入), delete(删除) 不包含查询

Insert
插入数据:INSERT INTO tableName (字段名1,字段名2,...) VALUES (值1,值2,...)(可以添加部分字段,未添加数据的字段会用null默认)
或者不写字段名:INSERT INTO tableName VALUES ()
此时必须写出所有列的数据,没有可用null表示插入空,并且此时可以使用多个括号同时插入多条数据。
插入时数据需要符合其类型和长度,字符串、日期一般用单引号括起来。

蠕虫复制
在已有表的基础上,将表2的数据复制到表1上:INSERT INTO tableName1 SELECT * FROM tableName2(复制所有数据)
复制特定字段数据:INSERT INTO tableName1(字段1, 字段2...) SELECT 字段1,字段2... FROM tableName2
可以配合创建相同结构表:CREATE TABLE tableName1 LIKE tableName2

Update
修改数据:UPDATE tableName SET 字段名=值强烈禁止不加限定的修改!!!
带条件修改:UPDATE tableName SET 字段名=值 WHERE 条件正确的修改方式

Delete
删除数据:DELETE FROM tableName强烈禁止不加限定的删除
带条件删除:DELETE FROM tableName WHERE 条件正确的删除方式
清空数据:TRUNCATE TABLE tableName(删除该表并创建相同结构的新表)

DQL(Data Query Language) 数据查询语言

数据表记录的查询。关键字select。

Select
查询列数据:SELECT 字段名1,字段名2... FROM tableName(一般不使用不加限定的查询列)
可使用“*”匹配所有列:SELECT * FROM tableName(一般不使用不加限定的查询列)
执行查询时一般使用别称方便阅读:SELECT name AS 姓名, age AS 年龄 FROM student;(不加AS貌似也可以)
去重查询:SELECT DISTINCT 列名 FROM tableName
运算查询:SELECT 列名 + 常量或列名 FROM tableName(参与预算的字段必须是数值类型)

DCL(Data Control Language)数据控制语言(了解)

是用来设置或更改数据库用户或角色权限的语句,如grant(设置权限),revoke(撤销权限),begin transaction等。这个比较少用到。

注释

单行注释:#,或者--(注意--后面有个空格)
多行注释:/* */

# 这是单行注释
-- 这也是单行注释
/*
  这是多行注释
*/

SQL之约束

条件限制

查询时可使用一下比较运算符和逻辑运算符进行条件限制:

约束 符号
大于 >
小于 <
大于等于 >=
小于等于 <=
等于 =
不等于 != , <>
and(&&)
or(
not(!)

比如查询年龄大于20且性别为男的学生:
SELECT * FROM tableName WHERE age > 20 AND sex = '男';

In
IN可用作多个条件时的查询:
比如查询条件是id为1、3、5的:WHERE id IN (1,3,5)

Between ... And ...
Between and 和用作在一定范围之内的查询:
比如查询条件为English在60到100之间的数据:WHERE english BETWEEN 60 AND 100


Like
模糊查询,可以使用通配字符串:WHERE 字段名 LIKE '通配字符串'
MySQL的通配符有两个:

  • %:匹配任意个字符
  • _:匹配一个字符

例如查询所有姓马的学员:SELECT * FROM tableName WHERE name LIKE '马%';
名字有马的:WHERE name LIKE '%马%'
两个字的姓马的:WHERE name LIKE '马_'

排序

Order By
SELECT 字段 FROM 表名 ORDER BY 排序的字段1 ASC或者DESC, 排序的字段2 ASC或者DESC...
ASC:升序(默认),ascend:上升
DESC:降序,descend:下降

聚合函数

聚合函数为纵向查询,null不做统计

Count:计算指定列个数
Sum:计算指定列的数值和,如果不是数值类型,那么计算结果为0
Max:最大值
Min:最小值
avg:平均值
ifnull(列名, 默认值):null和任何值相加都为null,该关键字可以判断是否为null,若为null则返回默认值
例子:查询总数:SELECT COUNT(*) FROM tableName;
年龄大于20的数量:SELECT COUNT(*) FROM tableName WHERE age > 20;
查询最大年龄:SELECT MAX(age) FROM tableName
查询id=1的英语和数学分数的总和:select sum(ifnull(math, 0) + ifnull(english,0)) from tableName where id=1

分组

Group By:对查询进行分组
例子:查询产品及其价格和,并以产品名分组,select product, sum(price) from ord group by product;

Having
where后面不允许添加聚合函数,因此可以使用having配合group by来进行约束。
例子:查询每一种商品的总价大于30的商品,并显示总价:select product ,sum(price) from ord group by product having sum(price) > 30;
注意:having 必须配合group by使用,并且和where 使用方法一样,具体区别为:

  1. having 通常与group by 分组结合使用。 where 和分组无关。
  2. having 可以书写聚合函数 (聚合函数出现的位置: having 之后)
  3. where 是在分组之前进行过滤的。having 是在分组之后进行过滤的。

例子:select ... from ... where 条件1 ... group by ... having 条件2
执行顺序为从前至后,条件1过滤 -> 分组 -> 条件2过滤
一般遇到每种每个时都使用分组。

Limit

Limit
限制查询条数:select * from tableName limit offset, row_count;
查询下标从0开始,第二个参数为查询条数(若第一个参数为0则可以省略)。

数据库备份与还原

备份命令:mysqldump -u root -p 数据库名 > d:\dir\A\1.sql
导入命令:mysql -u root -p 数据库名 < d:\dir\A\1.sql(恢复数据库需要手动创建数据库)
大于号小于号可以看做箭头

约束

约束种类

  • PRIMARY KEY: 主键约束(主键不能为空不能重复)
  • UNIQUE: 唯一约束(不能重复)
  • NOT NULL: 非空约束(不能是null)
  • DEFAULT: 默认值(添加默认值)
  • FOREIGN KEY: 外键约束

Auto_Increment
自增,一般设置为主键。

DELETE和TRUNCATE的区别:TRUNCATE可以重置自增,Delete不能。

外键约束

添加外键约束:

constraint 外键约束名称 foreign key(当前表中的列名) references  被引用表名(被引用表的列名)
举例:constraint coder_project_id foreign key(coder_id) references coder(id);

constraint: 添加约束,可以不写
foreign key(当前表中的列名): 将某个字段作为外键
references 被引用表名(被引用表的列名) : 外键一般引用主表的主键

添加外键约束的两种方式:

  1. 给已创建的表添加外键约束:ALTER TABLE tableName FOREIGN KEY(被约束列) REFERENCES 引用表(引用列)
    使用这种方式添加未级联的外键约束之后再次添加级联外键会导致两种约束同时存在,而不是更新,此时由于未级联约束的存在,级联约束相当于不生效
  2. 创建表时添加外键约束:
CREATE TABLE tableName(
      first_id int,
      second_id int,
      CONSTRAINT conName1 FOREIGN KEY(first_id) REFERENCES otherTable1(id),
      CONSTRAINT conName2 FOREIGN KEY(second_id) REFERENCES otherTable2(id)
);

外键级联

ON UPDATE CASCADE:级联更新,主键发生更新时,外键也会更新
ON DELETE CASCADE:级联删除,主键发生删除时,外键也会删除

上例中就可以添加外间的级联操作:

CREATE TABLE tableName(
      first_id int,
      second_id int,
      CONSTRAINT conName1 FOREIGN KEY(first_id) REFERENCES otherTable1(id) ON UPDATE CASCADE ON DELETE CASCADE,
      CONSTRAINT conName2 FOREIGN KEY(second_id) REFERENCES otherTable2(id)ON UPDATE CASCADE ON DELETE CASCADE
);

表关系

一对多:一对多的时候可以在多的表里添加一列,并使用少的表的主键作为约束。(例如作者与书籍,可以在书籍表里添加一列)
一对一:使用较少,在哪个表里添加都可以。
多对多:建立中间表

数据库范式及多表查询

数据库范式

关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式),一般来说满足第三范式即可。(贴个简单易懂的博客

  • 1NF: 字段是最小的的单元不可再分
  • 2NF:满足1NF,表中的字段必须完全依赖于全部主键而非部分主键 (一般我们都会做到)
  • 3NF:满足2NF,非主键外的所有字段必须互不依赖
  • BCNF:满足3NF,只能有一个候选键(即可以选为主键的属性)
  • 4NF:满足3NF,消除表中的多值依赖

简单来说:

  • 第一范式要求:表中的字段不能再拆分(字段原子性)
  • 第二范式要求:
    1. 一张表描述一件事情
    2. 每个表都提供主键
  • 第三范式要求:从表的外键必须使用主表的主键
  • 巴斯科德范式要求:不允许存在除主键外每行都不相同的列(可以选为主键的列)

多表查询

多表查询方式:SELECT * FROM tableName1, tableName2
这种方法会产生笛卡尔积,一般限制主键=外键来得到有效结果。
例子:SELECT * FROM tableName1, tableName2 WHERE tableName1.id = tableName2.id

内连接
隐式内连接:看不到JOIN关键字,条件使用WHERE指定,如上例。
显式内连接(标准内连接):SELECT * FROM tableName1 INNER JOIN tableName2 ON 条件(INNER可以省略)

左外链接
无论表2有无都会查询表1的数据:SELECT * FROM tableName1 LEFT OUTER JOIN tableName2 ON 条件(OUTER可省略)

右外连接
无论表1有无都会查询表2的数据:SELECT * FROM tableName1 RIGHT OUTER JOIN tableName2 ON 条件(OUTER可省略)

子查询

一条查询语句结果作为另一条查询语法一部分,该查询即为子查询。

子查询结果是单行单列时:
查询工资最高的员工信息:SELECT * FROM employee WHERE salary=(SELECT MAX(salary) FROM employee);
该查询还有另外一种实现:SELECT * FROM employee ORDER BY salary DESC LIMIT 1;
两种查询性能孰优孰劣先不做讨论,但子查询可以实现更多需求:
查询工资高于平均工资的员工:SELECT * FROM employee WHERE salary > (SELECT AVG(salary) FROM employee);

子查询结果是多行单列时:
SELECT 查询字段 FROM 表 WHERE 字段 IN (子查询);

子查询结果是多行多列时:
SELECT 查询字段 FROM 表1 表1别名,(子查询) 子查询表别名 WHERE 条件;
例如:在员工表emp和部门表dept查询2011年以后入职的员工信息,包括部门名称:SELECT * FROM dept d, (SELECT * FROM emp WHERE join_date>'2011-1-1') e WHERE d.id=e.dept_id;
另一种方式是使用表链接:SELECT d.*, e.* FROM dept d INNER JOIN emp e ON d.id = e.dept_id WHERE e.join_date > '2011-1-1';(d.*和e.*可以省略为*)

简单练习:
现在有四张表:学生表(student)、课程表(course)、学生课程表(studentCourse)、教师表(teacher),表关系如下:
SQL基础

1、查询最高分的学生信息

-- 查询获得最高分的学生信息。
# 暴力三重查询
SELECT 
  * 
FROM
  student 
WHERE id IN 
  (SELECT 
    `student_id` 
  FROM
    `studentcourse` 
  WHERE score = 
    (SELECT 
      MAX(score) 
    FROM
      `studentcourse`)) ;

# 内联加子查询
SELECT 
  s.* 
FROM
  student s 
  INNER JOIN `studentcourse` sc 
    ON s.`id` = sc.`student_id` 
WHERE sc.`score` = 
  (SELECT 
    MAX(score) 
  FROM
    `studentcourse`) ;

# 仅使用子查询
SELECT 
  * 
FROM
  student 
WHERE id = 
  (SELECT 
    `student_id` 
  FROM
    `studentcourse` 
  ORDER BY score DESC 
  LIMIT 1) ;

# 仅使用内联
SELECT 
  s.* 
FROM
  student s 
  INNER JOIN `studentcourse` sc 
    ON s.`id` = sc.`student_id` 
ORDER BY sc.`score` DESC 
LIMIT 1 ;
上一篇:Mysql Shell 脚本


下一篇:eclipse启动tomcat内存溢出的解决方式