基础SQL教程

2023-05-16

转载自廖雪峰老师的教程: 

SQL教程 - 廖雪峰的官方网站

一 概述

简单地说,SQL就是访问和处理关系数据库的计算机标准语言。

数据据库作为一种专门管理数据的软件。应用程序不需要自己管理数据,而是通过数据库软件提供的接口来读写数据。

常见类型

名称

类型

说明

INT

整型

4字节整数类型,范围约+/-21亿

BIGINT

长整型

8字节整数类型,范围约+/-922亿亿

REAL

浮点型

4字节浮点数,范围约+/-10

38

DOUBLE

浮点型

8字节浮点数,范围约+/-10

308

DECIMAL(M,N)

高精度小数

由用户指定精度的小数,例如,DECIMAL(20,10)表示一共20位,其中小数10位,通常用于财务计算

CHAR(N)

定长字符串

存储指定长度的字符串,例如,CHAR(100)总是存储100个字符的字符串

VARCHAR(N)

变长字符串

存储可变长度的字符串,例如,VARCHAR(100)可以存储0~100个字符的字符串

BOOLEAN

布尔类型

存储True或者False

DATE

日期类型

存储日期,例如,2018-06-22

TIME

时间类型

存储时间,例如,12:20:59

DATETIME

日期和时间类型

存储日期+时间,例如,2018-06-22 12:20:59

通常来说,BIGINT能满足整数存储的需求,VARCHAR(N)能满足字符串存储的需求,这两种类型是使用最广泛的。

教程约定:SQL关键字总是大写,以示突出,表名和列名均使用小写。

二 安装

mysql两种引擎

  • InnoDB:由Innobase Oy公司开发的一款支持事务的数据库引擎,2006年被Oracle收购;
  • MyISAM:MySQL早期集成的默认数据库引擎,不支持事务。

分支:

  • MariaDB:由MySQL的创始人创建的一个开源分支版本
  • Aurora:由Amazon改进的一个MySQL版本
  • PolarDB:由Alibaba改进的一个MySQL版本

登录: mysql -u root -p,然后输入口令

三 关系模型

  • 表的每一行称为记录(Record),记录是一个逻辑意义上的数据。
  • 表的每一列称为字段(Column),同一个表的每一行记录都拥有相同的若干字段。字段定义了数据类型(整型、浮点型、字符串、日期等),以及是否允许为NULL。注意null不是0,也不是空串""。

在关系数据库中,关系是通过主键和外键来维护的。对于关系表,有个很重要的约束,就是任意两条记录不能重复。能够通过某个字段唯一区分出不同的记录,这个字段被称为主键

对主键的要求,最关键的一点是:记录一旦插入到表中,主键最好不要再修改。选取主键的一个基本原则是:不使用任何业务相关的字段作为主键

一般把这个字段命名为id。常见的可作为id字段的类型有:

  • 自增整数类型:数据库会在插入数据时自动为每一条记录分配一个自增整数,这样我们就完全不用担心主键重复,也不用自己预先生成主键;
  • 全局唯一GUID类型:使用一种全局唯一的字符串作为主键,类似8f55d96b-8acc-4636-8cb8-76bf8abc2f57。

可以使用多个列作为联合主键,但联合主键并不常用。 

在students表中,通过class_id的字段,可以把数据与另一张表关联起来,这种列称为外键。

由于外键约束会降低数据库的性能,大部分互联网应用程序为了追求速度,并不设置外键约束,而是仅靠应用程序自身来保证逻辑的正确性

通过中间表,我们就定义了一个“多对多”关系。还有一些应用会把一个大表拆成两个一对一的表,目的是把经常读取和不经常读取的字段分开,以获得更高的性能。

索引的效率取决于索引列的值是否散列。使用主键索引的效率是最高的,因为主键会保证绝对唯一。通过创建唯一索引,可以保证某一列的值具有唯一性。

四 查询数据

使用SELECT * FROM students时,SELECT是关键字,表示将要执行一个查询,*表示“所有列”,FROM表示将要从哪个表查询。SELECT查询的结果是一个二维表。

SELECT语句其实并不要求一定要有FROM子句。许多检测工具会执行一条SELECT 1;来测试数据库连接。

通过WHERE条件查询,可以筛选出符合指定条件的记录,而不是整个表的所有记录。

使用<>判断不相等

score <> 80

name <> 'abc'

使用LIKE判断相似

name LIKE 'ab%'

name LIKE '%bc%'

%表示任意字符,例如'ab%'将匹配'ab','abc','abcd'

使用SELECT *表示查询表的所有列,使用SELECT 列1, 列2, 列3则可以仅返回指定列,这种操作称为投影。可以对结果集的列进行重命名 SELECT 列1 别名1, 列2 别名2 FROM XXX

使用ORDER BY可以对结果集进行排序;可以对多列进行升序、倒序排序。ASC DESC

使用LIMIT OFFSET 可以对结果集进行分页,每次查询返回结果集的一部分;

OFFSET是可选的,如果只写LIMIT 15,那么相当于LIMIT 15 OFFSET 0。OFFSET超过了查询的最大数量并不会报错,而是得到一个空的结果集。

SQL提供了专门的聚合函数,使用聚合函数进行查询,就是聚合查询。除了COUNT()函数外,SQL还提供了如下聚合函数:

函数

说明

COUNT

计算某一列数量

SUM

计算某一列的合计值,该列必须为数值类型

AVG

计算某一列的平均值,该列必须为数值类型

MAX

计算某一列的最大值

MIN

计算某一列的最小值

要特别注意:如果聚合查询的WHERE条件没有匹配到任何行,COUNT()会返回0,而SUM()、AVG()、MAX()和MIN()会返回NULL

GROUP BY可以进行分组

多表查询又称笛卡尔查询,使用笛卡尔查询时要非常小心,结果集是目标表的行数乘积。使用多表查询可以获取M x N行记录;

SQL还允许给表设置一个别名,让我们在投影查询中引用起来稍微简洁一点。

最常用的一种内连接——INNER JOIN。

  • 先确定主表,仍然使用FROM 的语法;
  • 再确定需要连接的表,使用INNER JOIN 的语法;
  • 然后确定连接条件,使用ON ,这里的条件是s.class_id = c.id,表示students表的class_id列与classes表的id列相同的行需要连接;
  • 可选:加上WHERE子句、ORDER BY等子句

假设查询语句是:

SELECT ... FROM tableA  JOIN tableB ON tableA.column1 = tableB.column2;

我们把tableA看作左表,把tableB看成右表。

INNER JOIN是选出两张表都存在的记录:

LEFT OUTER JOIN是选出左表存在的记录:

RIGHT OUTER JOIN是选出右表存在的记录:

FULL OUTER JOIN则是选出左右表都存在的记录:

五 增删改

增: INSERT

如:

INSERT INTO students (class_id, name, gender, score) VALUES (2, '大牛', 'M', 80);

也可以插入多条,如

INSERT INTO students (class_id, name, gender, score) VALUES (1, '大宝', 'M', 87), (2, '二宝', 'M', 81);

改: UPDATE

UPDATE students SET name='大牛', score=66 WHERE id=1;

在UPDATE语句中,更新字段时可以使用表达式。

UPDATE students SET score=score+10 WHERE score<80;

最后,要特别小心的是,UPDATE语句可以没有WHERE条件,例如:

UPDATE students SET score=60;

这时,整个表的所有记录都会被更新。

删: DELETE

DELETE FROM students WHERE id=1;

要特别小心的是,和UPDATE类似,不带WHERE条件的DELETE语句会删除整个表的数据:

DELETE FROM students;

这时,整个表的所有记录都会被删除。所以,在执行DELETE语句时也要非常小心,最好先用SELECT语句来测试WHERE条件是否筛选出了期望的记录集,然后再用DELETE删除。

六 MYSQL

客户端

MySQL Client和MySQL Server的关系如下:

在MySQL Client中输入的SQL语句通过TCP连接发送到MySQL Server。

登录语句:

mysql -h 10.0.1.99 -u root -p

命令行程序

mysql实际上是MySQL客户端,真正的MySQL服务器程序是mysqld,在后台运行

管理MYSQL

要列出所有数据库,使用命令SHOW:

mysql> SHOW DATABASES;

要创建一个新数据库,使用命令CREATE:

mysql> CREATE DATABASE test;

要删除一个数据库,使用命令DROP:

mysql> DROP DATABASE test;

对一个数据库进行操作时,要首先将其切换为当前数据库USE:

mysql> USE test;

列出当前数据库的所有表,使用命令SHOW:

mysql> SHOW TABLES;

要查看一个表的结构,使用命令DESC:

mysql> DESC students;

还可以使用以下命令查看创建表的SQL语句SHOW CREATE TABLE:

mysql> SHOW CREATE TABLE students;

创建表使用CREATE TABLE语句,而删除表使用DROP TABLE语句:

mysql> DROP TABLE students;

修改表就比较复杂,使用ALTER TABLE。如果要给students表新增一列birth:

ALTER TABLE students ADD COLUMN birth VARCHAR(10) NOT NULL;

要修改birth列,例如把列名改为birthday,类型改为VARCHAR(20):

ALTER TABLE students CHANGE COLUMN birth birthday VARCHAR(20) NOT NULL;

要删除列,使用:

ALTER TABLE students DROP COLUMN birthday;

退出MySQL

使用EXIT命令退出MySQL:

mysql> EXIT

实用语句

使用REPLACE语句,这样就不必先查询,再决定是否先删除再插入:

REPLACE INTO students (id, class_id, name, gender, score) VALUES (1, 1, '小明', 'F', 99);

希望插入一条新记录(INSERT),但如果记录已经存在,就更新该记录,此时,可以使用INSERT INTO ... ON DUPLICATE KEY UPDATE ...语句:

INSERT INTO students (id, class_id, name, gender, score) VALUES (1, 1, '小明', 'F', 99) ON DUPLICATE KEY UPDATE name='小明', gender='F', score=99;

希望插入一条新记录(INSERT),但如果记录已经存在,就啥事也不干直接忽略,此时,可以使用INSERT IGNORE INTO ...语句:

INSERT IGNORE INTO students (id, class_id, name, gender, score) VALUES (1, 1, '小明', 'F', 99);

如果想要对一个表进行快照,即复制一份当前表的数据到一个新表,可以结合CREATE TABLE和SELECT:

-- 对class_id=1的记录进行快照,并存储为新表students_of_class1:

CREATE TABLE students_of_class1 SELECT * FROM students WHERE class_id=1;

用一条语句写入各班的平均成绩:

INSERT INTO statistics (class_id, average) SELECT class_id, AVG(score) FROM students GROUP BY class_id;

使用FORCE INDEX强制查询使用指定的索引。例如:

> SELECT * FROM students FORCE INDEX (idx_class_id) WHERE class_id = 1 ORDER BY id DESC;

前提是索引idx_class_id必须存在。

七 事务

1 概念

这种把多条语句作为一个整体进行操作的功能,被称为数据库事务。

数据库事务具有ACID这4个特性:

  • A:Atomic,原子性,将所有SQL作为原子工作单元执行,要么全部执行,要么全部不执行;
  • C:Consistent,一致性,事务完成后,所有数据的状态都是一致的,即A账户只要减去了100,B账户则必定加上了100;
  • I:Isolation,隔离性,如果有多个事务并发执行,每个事务作出的修改必须与其他事务隔离;
  • D:Duration,持久性,即事务完成后,对数据库数据的修改被持久化存储。

单条SQL语句,数据库系统自动将其作为一个事务执行,这种事务被称为隐式事务。

要手动把多条SQL语句作为一个事务执行,使用BEGIN开启一个事务,使用COMMIT提交一个事务,这种事务被称为显式事务

BEGIN; UPDATE accounts SET balance = balance - 100 WHERE id = 1; UPDATE accounts SET balance = balance + 100 WHERE id = 2; COMMIT;

使用ROLLBACK进行回滚

BEGIN; UPDATE accounts SET balance = balance - 100 WHERE id = 1; UPDATE accounts SET balance = balance + 100 WHERE id = 2; ROLLBACK;

SQL标准定义了4种隔离级别,分别对应可能出现的数据不一致的情况:

Isolation Level

脏读(Dirty Read)

不可重复读(Non Repeatable Read)

幻读(Phantom Read)

Read Uncommitted

Yes

Yes

Yes

Read Committed

-

Yes

Yes

Repeatable Read

-

-

Yes

Serializable

-

-

-

2 四种隔离

  • 在Read Uncommitted隔离级别下,一个事务可能读取到另一个事务更新但未提交的数据,这个数据有可能是脏数据。
  • 在Read Committed隔离级别下,一个事务可能会遇到不可重复读(Non Repeatable Read)的问题。不可重复读是指,在一个事务内,多次读同一数据,在这个事务还没有结束时,如果另一个事务恰好修改了这个数据,那么,在第一个事务中,两次读取的数据就可能不一致。
  • 在Repeatable Read隔离级别下,一个事务可能会遇到幻读(Phantom Read)的问题。幻读是指,在一个事务中,第一次查询某条记录,发现没有,但是,当试图更新这条不存在的记录时,竟然能成功,并且,再次读取同一条记录,它就神奇地出现了。
  • Serializable是最严格的隔离级别。在Serializable隔离级别下,所有事务按照次序依次执行,因此,脏读、不可重复读、幻读都不会出现。虽然Serializable隔离级别下的事务具有最高的安全性,但是,由于事务是串行执行,所以效率会大大下降,应用程序的性能会急剧降低。如果没有特别重要的情景,一般都不会使用Serializable隔离级别。

默认隔离级别

如果没有指定隔离级别,数据库就会使用默认的隔离级别。在MySQL中,如果使用InnoDB,默认的隔离级别是Repeatable Read。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基础SQL教程 的相关文章

  • 删除表的重复项

    In my activity logs 它包含列 material name user id mod result 这标志着测试是否通过 失败 cert links 不知何故 用户生成了两倍的条目material name与cert lin
  • 如何在 Spring Data 中选择不同的结果

    我在使用简单的 Spring Data 查询或 Query 或 QueryDSL 在 Spring Data 中构建查询时遇到问题 如何选择三列 研究 国家 登录 不同的行 并且查询结果将是用户对象类型的列表 Table User Id S
  • 如何引用下一行的数据?

    我正在 PostgreSQL 9 2 中编写一个函数 对于股票价格和日期的表 我想计算每个条目较前一天的百分比变化 对于最早一天的数据 不会有前一天 因此该条目可以简单地为 Nil 我知道WITH声明可能不应该高于IF陈述 到目前为止 这就
  • ASP SQL Server 连接

  • Spring Data JPA 选择不同

    我有一个情况 我需要建立一个select distinct a address from Person a 其中地址是 Person 内的地址实体 类型的查询 我正在使用规范动态构建我的 where 子句并使用findAll Specifi
  • hive sql查找最新记录

    该表是 create table test id string name string age string modified string 像这样的数据 id name age modifed 1 a 10 2011 11 11 11 1
  • C# using 语句、SQL 和 SqlConnection

    使用 using 语句 C SQL 可以吗 private static void CreateCommand string queryString string connectionString using SqlConnection c
  • 标量子查询包含多行

    我正在使用 H2 数据库并想要移动一些数据 为此 我创建了以下查询 UPDATE CUSTOMER SET EMAIL SELECT service EMAIL FROM CUSTOMER SERVICE AS service INNER
  • 根据由另一列分组的不同列的最大值获取值[重复]

    这个问题在这里已经有答案了 我想根据由另一列分组的不同列的最大值来获取列的值 我有这张表 KEY NUM VAL A 1 AB B 1 CD B 2 EF C 2 GH C 3 HI D 1 JK D 3 LM 并想要这样的结果 KEY V
  • 3 个表的 SQL 查询(或联接)

    第一次在 Stack Overflow 上问问题 很棒的资源 但是只有一件事真正让我作为 SQL 新手感到困惑 我有三个表 我想获取与鲍勃的学生相关的所有导师的姓名 表 1 教师 ID Name 1 Bob 表 2 学生 STUDENT I
  • SQL 使用另一列的键和最大值设置列

    我需要根据同一 ID 的 duration 列的最大值更新 max register 列 将值设置为 1 其他值设置为 0 初始表 Id duration max register 1 0 0 1 7 0 1 3 0 2 10 0 2 5
  • SQL - 需要查找重复记录但排除反向事务

    我有一张交易表 偶尔会有 重复条目 如果 当管理员发现这些重复条目时 他们将撤销交易 从而创建负值 但由于监管要求 原始重复条目仍然保留 我想创建一个 SQL 查询 并使用 Crystal Reports 来制作报告 以便管理员轻松查找重复
  • 时间序列数据的自连接

    我需要一些帮助来完成我认为应该是相当简单的自连接查询 只需要将两条记录中匹配的开始时间和结束时间合并为一条记录 假设我的表中有以下内容 Time Event 08 00 Start 09 00 Stop 10 30 Start 10 45
  • WHERE NOT EXIST 附近的语法错误

    我在堆栈中搜索 但没有一个达到最终答案 我的查询是这样的 INSERT INTO user username frequence autoSend VALUES feri2 3 1 WHERE NOT EXISTS SELECT FROM
  • 从 call_log 中获取最大并发通话数

    我需要帮助在 MySQL 5 0 77 中编写一个查询 根据下面所示的数据 办公室一天的通话量 返回并发电话呼叫的峰值数量 我只是想知道一天中任何特定时间同时打电话的人数最多是多少 首先 这是 MySQL 表 CREATE TABLE ca
  • SQL查询查找具有特定数量关联的行

    使用 Postgres 我有一个架构conversations and conversationUsers Each conversation有很多conversationUsers 我希望能够找到具有确切指定数量的对话conversati
  • meta_query,如何使用关系 OR 和 AND 进行搜索?

    已解决 请参阅下面的答案 我有一个名为的自定义帖子类型BOOKS 它有几个自定义字段 名称为 TITLE AUTHOR GENRE RATING 我该如何修复我的meta query下面的代码以便仅books在自定义字段中包含搜索词 tit
  • 没有提示指令的直连接中表的顺序是否会影响性能?

    所有基于 SQL 的 RDBMS 10 年前的版本 直接连接查询 没有提示指令 中的表顺序是否会对最佳性能和内存管理产生影响 听说最后一个join应该是最大的表 您的数据库的查询优化器如何处理这种情况 回答你的问题 是的 表的顺序在连接中有
  • MySQL“列计数与第 1 行的值计数不匹配”是什么意思

    这是我收到的消息 ER WRONG VALUE COUNT ON ROW 列计数与第 1 行的值计数不匹配 这是我的全部代码 我的错误在哪里 DROP TABLE student CREATE TABLE employee emp id I
  • 总和和不同不会改变结果?

    我是一个新手 试图在这里解决这个问题 到目前为止还没有运气 非常感谢任何帮助 Select Distinct AB agency no ab branch no AS AGENCY BRANCH count AB agency no ab

随机推荐

  • Arduino IDE搭建ESP8266开发环境,开发包下载过慢解决方法

    Arduino IDE搭建ESP8266开发环境 xff0c 开发板管理器中下载过慢解决方法 方法一 xff1a 1 首选项 附加开发板管理器网址 xff1a http arduino esp8266 com stable package
  • CheckBox的使用(一):onCheckedChanged事件

    重写接口 public void onCheckedChanged CompoundButton buttonView boolean isChecked package com example androidtest import and
  • 指针与引用的关系

    c xff0b xff0b 中的引用与指针的区别 相同点 xff1a 1 都是地址的概念 xff1b 指针指向一块内存 xff0c 它的内容是所指内存的地址 xff1b 引用是某块内存的别名 区别 xff1a 1 指针是一个实体 xff0c
  • C&C++图形图像处理开源库

    Google三维APIO3D O3D 是一个开源的 WebAPI 用来在浏览器上创建界面丰富的交互式的 3D 应用程序 这是一种基于网页的可控3D标准 此格式期望真正的基于浏览器 xff0c 独立于操作系统之外 xff0c 并且支持主流的3
  • protobuf的ParseFromArray 解析失败的问题

    前段时间 xff0c 在解析定义的Message时 xff0c 总是提示解析失败 xff0c 刚开始以为是消息号与消息没有对应上 xff0c 检查后发现消息号与消息是对应的 后来发现消息的一个字段定义为required 但是没有赋值 xff
  • Incorrect number of FETCH variables

    在写存储过程 xff0c 运行后提示 Incorrect number of FETCH variables 原来是用游标select的字段数需要与fetch into的变量数一致 修改后的如下 xff1a DROP PROCEDURE I
  • phpStorm 2016.1 最新版激活方法

    新版激活方法 1 在线激活 最新 http 123 206 193 241 1017 http www 0 php com 1017 xff08 可用 xff0c 更新于 20170621 xff09 http idea singee77
  • Android EditText最大字数限制并提示

    public class MaxTextLengthFilter implements InputFilter private int mMaxLength 构造方法中传入最多能输入的字数 public MaxTextLengthFilte
  • Android调用系统, 任意比例裁剪图片

    废话不多说 直接上代码 核心代码 span class hljs javadoc 跳转到系统裁剪图片页面 span class hljs javadoctag 64 param span imagePath 需要裁剪的图片路径 span s
  • Kotlin教程学习-字符串拼接,数组,List

    摘要 Kotlin是一种优雅的语言 是JetBrains公司开发的JVM语言 与Java有着极密切的联系 Kotlin有着怎样的魅力呢 首先看到的就是import语句 这个很好理解 既然Kotlin有包的概念 自然就可以使用import语句
  • Android app启动白屏优化

    可以看到启动的时候会有一个白屏 如果手机较慢的话 这个白屏就会持续一段时间 不太友好 那么还有没有什么办法优化呢 给我们的应用窗口弄一个PlaceHolder Android最新的Material Design有这么个建议的 建议我们使用一
  • 04 点亮LED 汇编

    1 原理图 从原理图看到 xff0c 3个LED分别由GPF4 GPF5和GPF6控制 2 寄存器描述 GPF4 GPF5和GPF6可用作输入输出 xff0c 或中断功能 要点亮LED xff0c 需要将IO设置为输出模式 xff0c 并输
  • CentOS7.5安装CloudStack4.11出现Requires python(abi) = 2.6的解决方案

    错误描述 root 64 manage yum install cloudstack management 已加载插件 xff1a fastestmirror Loading mirror speeds from cached hostfi
  • 一款APP从设计稿到切图过程全方位揭秘(IOS版)

    9月17日凌晨 xff0c IOS9正式推送 xff0c 它使用的字体最终还是变了 xff0c 我下面写的内容你们也要酌情更新 xff0c 因为我写的实在赶不上它更新的速度了 iOS9使用的西文字体由Helvetica Neue变更为 Sa
  • Dagger2找不到DaggerActivityComponent类

    这是因为你要成功编译一次 xff0c DaggerXXXComponent才会自动生成 xff0c 如果是Android Studio的话 快捷键Ctrl 43 F9编译就行了
  • AndroidStudio升级3.0后报错,Annotation processors must be explicitly declared now

    报错信息显示为butterknife的注解导致的 Error Execution failed span class hljs keyword for span task span class hljs string 39 app java
  • Java设计模式透析之 —— 模板方法(Template Method)

    链接 xff1a http blog csdn net guolin blog article details 8744002
  • android 解放双手 自动化生成多语言strings内容

    本文主要基于jxl jar 自动解析Excel xls文件内容 xff0c 生成values 文件夹及strings xml文件 资源文件 xff1a 代码及jxl jar下载 只能支持97 2003的Excel xls xff0c 不适配
  • 解决Ajax发送DELETE请求时无法传参数的问题

    相信大家使用spring 时一般都会用ajax发送delete请求 xff0c 但是delete请求无法传参数怎么办呢 xff1f 请看下面链接 http stackoverflow com questions 10766195 sprin
  • 基础SQL教程

    转载自廖雪峰老师的教程 xff1a SQL教程 廖雪峰的官方网站 一 概述 简单地说 xff0c SQL就是访问和处理关系数据库的计算机标准语言 数据据库作为一种专门管理数据的软件 应用程序不需要自己管理数据 xff0c 而是通过数据库软件