[TOC]
什么是 SQL语言?
答:SQL指结构化查询语言,全称是 Structured Query Language
,是一种 ANSI(American National Standards Institute 美国国家标准化组织)标准的计算机语言。它是用于访问和处理数据库的标准的计算机语言。
SQL 能做什么?
创建存储过程
创建视图
设置表、存储过程和视图的权限
MySQL是属于关系型数据库 RDBMS
中的数据存储在被称为表的数据库对象中,表是相关的数据项的集合,它由列cols和行rows
组成。
什么是 RDBMS ?
答:指关系型数据库管理系统,全称 Relational Database Management System;RDBMS 是 SQL 的基础同样也是所有现代数据库系统的基础,比如 MSSQL Server、IBM DB2、Oracle、MySQL 以及 Microsoft Access
。
如何学习SQL和查看命令帮助? 答:linux中采用man,help与info命令,在mysql中是help建议在学习的时候多采用帮助文档;
mysql> help contents
Account Management
Administration
...
mysql> help Account Management
CREATE USER
DROP USER
GRANT
RENAME USER
REVOKE
SET PASSWORD
注释:除了 SQL 标准之外,大部分 SQL 数据库程序都拥有它们自己的专有扩展,比如MySQL 与 Oracle 之间扩展模块是有所不同的!
学习SQL环境快速安装:
#安装Docker-ce (注意安装前删除老版本)
yum install -y docker-ce python3
pip3 install pip --upgrade
#安装Docker-compose
pip install docker-compose
#验证运行docker-compose.yml配置文件
docker-compose config
docker-compose up -d #后台运行
docker-compose.yml
# Use root/example as user/password credentials 默认MySQL版本是8.x
version: '3.1'
services:
db:
image: mysql
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
MYSQL_ROOT_PASSWORD: example
ports:
- 3308:3306
db5:
image: mysql:5.7.28
container_name: mysql5
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
MYSQL_ROOT_PASSWORD: example
ports:
- 3305:3306
adminer:
image: adminer
restart: always
ports:
- 8080:8080
WeiyiGeek.
运行和查询
#手动运行容器
$ docker run --name mysql-test -e MYSQL_ROOT_PASSWORD=my-secret-pw --default-authentication-plugin=mysql_native_password -d mysql:tag
$ docker run -it --network some-network --rm mysql mysql -hsome-mysql -uexample-user -p #对Docker网络中的MySQL进行连接
$ docker run -it --rm mysql mysql -hsome.mysql.host -usome-mysql-user -p #连接其他MySQL
#使用自定义MySQL配置文件
$ docker run --name some-mysql -v /my/custom:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
#在主机系统的适当卷上创建一个数据目录,例如/my/own/datadir。
$ docker run --name some-mysql -v /my/own/datadir:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
#测试查询
docker ps
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# 4ba28666e63f adminer "entrypoint.sh doc..." 45 hours ago Up 44 hours 0.0.0.0:9080->8080/tcp data_adminer_1
# 2172955ddedc mysql "docker-entrypoint..." 45 hours ago Up 44 hours 33060/tcp, 0.0.0.0:9001->3306/tcp data_db_1
...
SQL标准语句
在数据库系统中分隔每条 SQL 语句的标准方法,这样在对服务器的相同请求中执行一条以上的 SQL 语句
),因为某些数据库系统要求在每条 SQL 语句的末端使用分号。SELECT 与 select 是相同的
;/* 注释案例 */ 和 --注释案例
;常见的SQL语句:
//0.CRUD (创建/查询/更新/删除)
//1.数据定义语言 - DDL
CREATE DATABASE|TABLE|INDEX|USER|VIEW - 创建新数据库 / 创建新表 / 创建索引(搜索键)/ 创建用户 / 创建视图
ALTER DATABASE|TABLE|INDEX|USER - 修改数据库 / 变更(改变)数据库表 / 修改索引 / 更改用户
DROP DATABASE|TABLE|INDEX|USER - 删除数据库 / 删除表 / 删除索引 / 删除用户
RENAME DATABASE|TABLE|USER - 重命名数据库和数据表 / 重命名用户
TRUNCATE TABLE - 清空表数据
//2. 数据查询语言- DQL(查询)
SELECT - 从数据库中提取数据
FROM 字句
WHERE 字句
//3.数据操作语言 - DML(增删改)
UPDATE - 更新数据库中的数据
DELETE - 从数据库中删除数据
INSERT INTO - 向数据库中插入新数据
//4.数据控制语言 - DCL(权限)
GRANT - 设置数据库表rw权限设置(访问、安全权限)
REVOKE - 取消数据库表rw权限设置
IF...ELSE
WHILE
BEGIN
TRANSACTION
//5.事务处理语言 - TPL
COMMIT - 事务提交
ROLLBACK - 事务回滚
SQL分类 SQL语言大致分为以下几类:
create drop alter(修改) rename
);
WHERE (条件) ,ORDER BY (排序) ,having , Group By (分组), limit(限制显示)
插入(INSERT)、更新(UPDATE)和删除(DELETE)
;
CURSOR Control Language
语句DECLARE CURSOR
, FETCH INITO
和 update where current
用于对一个或多个表单独行操作;
BEGIN ,TRANSACTION ,COMMIT(提交) ,ROLLBACK(回滚)
等等;
补充学习:
Move-To-First-Record、Get-Record-Content、Move-To-Next-Record
等等。描述:SELECT 语句用于从数据库中选取数据,可以加上条件或者语句参数进行过滤显示数据; SQL 查询的五种子句where(条件查询)、having(筛选)、group by(分组)、order by(排序 ASC | DESC)、limit(限制结果数)
;
/* SQL SELECT 语法 */
SELECT [DISTINCT] column_name,column_name
FROM table_name
WHERE column_name operator value;
/* DISTINCT 语句用于返回唯一不同的值,在表中一个列可能会包含多个重复值仅仅列出不同的值 */
/* WHERE 子句用于提取那些满足指定标准的记录。*/
SELECT DISTINCT 字段名 FROM 表名 WHERE 查询条件;
/* LIKE 操作符用于在 WHERE 子句中搜索列中的指定模式 */
SELECT column_name(s)
FROM table_name
WHERE column_name [LIKE|REGEXP] pattern;
/* BETWEEN AND (在之间的值) 字句在此之间的值*/
SELECT 字段名 FROM 表名 WHERE 字段名 BETWEEN 初始值 AND 终止值;
/* ORDER BY 关键字用于对结果集按照一个列或者多个列进行排序。(注意这里无WHERE)*/
/* DESC 降序 , ASC 升序(默认),即 desc 或者 asc 只对它紧跟着的第一个列名有效其他不受影响,仍然是默认的升序*/
SELECT column_name,column_name
FROM table_name
ORDER BY column_name1 ASC|DESC,column_name2 ASC|DESC;
/* SQL limit 子句,查询前n条/后n条记录(分页常用) */
SELECT 字段 FROM 表名 WHERE 查询条件 LIMIT 起始,结束
/* SQL 多表查询 */
SELECT 数据库.表,mysql.user FROM 数据库,mysql WHERE 1
/* GROUP BY 语法 */
SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name;
/* HAVING 语法筛选分组后的各组数据*/
SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name
HAVING aggregate_function(column_name) operator value;
WHERE 子句中的运算符:
<> 表示(不等于)
, BETWEEN(在某个范围内), LIKE(搜索某种模式), IN(指定针对某个列的多个可能值),IS(是否赛某列的值)(优先级排列), not (满足不包含该条件的值) , and, or
NOT与谓词进行组合条件的查询:
NULL 值判断
基础示例:
set names utf8; /*命令用于设置使用的字符集(如果在配置文件中设置了Server或者Client端的字符集则不需要指定)*/
-- 查询用户数据库.表
mysql> select user,host from mysql.user;
mysql> select id,name,country from websites;
-- 重复去掉 distinct: 从 "Websites" 表的 "country" 列中选取唯一不同的值,也就是去掉 "country" 列重复值
mysql> select distinct country from websites;
-- 比较运算符
mysql> SELECT * FROM websites WHERE country="CN";
mysql> SELECT * FROM websites WHERE id=1; /* SQL 可以直接输入 数字 表示数值**/
mysql> SELECT * FROM websites WHERE id <> 1; /*显示不包括id=1的数据;*/
mysql> SELECT * FROM websites WHERE id>=2 and country != "CN"; /**采用逻辑运算符和比较运算符连用*/
-- 不带比较运算符的 WHERE 子句
mysql> SELECT host FROM mysql.user WHERE 0; /*则会返回一个空集,因为每一行记录 WHERE 都返回 false。*/
mysql> SELECT host FROM mysql.user WHERE 1; /*返回MySQL表中host字段,因为每一行记录 WHERE 都返回 true。*/
-- 空值判断is null:打印编写满足列某值的某行是,如果不满足则返回该标字段及其字段的值为NULL;)
mysql> SELECT * FROM information_schema.FILES WHERE CHECKSUM IS NULL
mysql> SELECT * FROM information_schema.FILES WHERE CHECKSUM IS NOT NULL
-- 条件语句between.and. :查询 emp 表中 SAL 列中大于等于 1500 的小于 3000 的值
mysql> SELECT * FROM emp WHERE sal between 1500 and 3000;
-- 运算符 In (包含运算). 查询 EMP 表 SAL 列中等于 5000,3000,1500 的值。
mysql> SELECT * FROM emp WHERE sal in (5000,3000,1500);
-- 模糊查询Like:查询 EMP 表中 Ename 列中有 M 的值,M 为要查询内容中的模糊信息。
mysql> SELECT * FROM emp WHERE ename like 'Java%';
mysql> SELECT * FROM tb_stu WHERE name like'%程序_';
mysql> SELECT * FROM tb_stu WHERE name like'%PHP%';
-- 模糊查询REGEXP:使用 REGEXP 或 NOT REGEXP 运算符 (或 RLIKE 和 NOT RLIKE) 来操作正则表达式查询匹配的模糊信息。
mysql> SELECT host,user FROM user WHERE user REGEXP '[^root]'
mysql> SELECT host,user FROM user WHERE user REGEXP '^root'
-- 联合使用() 比较 条件 逻辑 运算符
SELECT * FROM websites WHERE alexa > 15 AND (country='CN' OR country='USA');
SELECT * FROM websites WHERE (alexa > 15 and alexa % 2 != 0) AND (country='CN' OR country='USA');
-- 排序语句 ORDER BY:多列排序的时候,先按照第一个column name排序,在按照第二个column name排序;
SELECT * FROM tb_name WHERE address <> '' order by addtime desc, id asc; /**查询不为空的数据*/
-- 显示行数 limit语句:查询前n条/后n条记录
SELECT Host,User,password_last_changed FROM mysql.user WHERE 1 limit 0,3; --前三条
SELECT Host,User,password_last_changed FROM mysql.user WHERE 1 ORDER BY HOST DESC limit 0,3; --后三条
-- 子查询也叫内部查询如select avg(score) from studentscore就是子查询
-- 查询学生成绩表里分数低于平均成绩的学生姓名和成绩,并根据分数降序排列
select name,score form studentscore where score < (select avg(score) from studentscore) order by score DESC
WeiyiGeek.
多表查询
CREATE DATABASE student;
USE student;
CREATE TABLE `user`(
xh int(8) NOT NULL auto_increment COMMENT '主键学号',
xm VARCHAR(62) NOT NULL COMMENT '姓名',
nj VARCHAR(10) NOT NULL COMMENT '班级',
age INT(3) NOT NULL DEFAULT 0 COMMENT '年龄',
zy VARCHAR(256) NOT NULL COMMENT '专业',
PRIMARY KEY(xh)
)ENGINE = InnoDB DEFAULT CHARSET = utf8;
CREATE TABLE `user_kc`(
`xh` int(8) NOT NULL DEFAULT 0 COMMENT '主键学号',
`kcm` VARCHAR(256) NOT NULL COMMENT '课程名',
`grade` float(8) NOT NULL COMMENT '成绩' -- 注意最后一个字段没有','
)ENGINE = InnoDB DEFAULT CHARSET = utf8;
INSERT INTO user VALUES (1001,'张晓华','2014级',19,'计算机技术'), (1002,'则新华','2015级',39,'计算机技术'), (1003,'线程华','2015级',19,'网络工程技术'),(1004,'台时华','2016级',19,'网络工程技术'),(1005,'爱是','2013级',19,'物联网工程');
INSERT INTO user_kc VALUES (1002,"Python编程",79.1),(1001,"JAVA编程",89.5),(1003,"LINUX编程",69.5),(1002,"Mysql数据库编程",69.9),(1005,"网络编程",79.5),(1004,"前端HTML5",79.5),(1002,"Python编程",79.5),(1004,"C语言之精华",59.5);
基础示例:
-- 联表查询
SELECT user.xh,user.xm,user.nj,user_kc.kcm,user_kc.grade
FROM user,user_kc
WHERE user.xh=user_kc.xh;
WeiyiGeek.联表查询
函数使用
基础示例:
select user();
select now();
root@212.17.8.29 2020-01-06 03:28:45
注意事项:
描述:INSERT INTO 语句用于向表中插入新记录。
-- INSERT INTO 语句可以有两种编写形式。
-- 1.无需指定要插入数据的列名,只需提供被插入的值即可(需要注意他是按照字段顺序进行插入的):
INSERT INTO table_name
VALUES (value1,value2,value3,...);
-- 2.需要指定列名及被插入的值:
INSERT INTO table_name
VALUES (value1,value2,value3,...);
-- 3. 将旧表中的数据灌入新表
CREATE table 新表名 LIKE book; -- 复制表结构,含有主键等信息的完整表结构;
INSERT INTO 新表 SELECT * FROM 旧表;
基础示例:
-- 向 "Websites" 表中插入一个新行。
INSERT INTO Websites (name, url, alexa, country)
VALUES ('百度','https://www.baidu.com/','4','CN');
-- 为了数据库优化更好我们建议将添加的字符进行拼接然后再一起写入数据库中:
mysql> INSERT INTO sb_user(name,pass) VALUES ('test','test'),('admin','admin');
-- 旧表数据灌入新表之中(但是此种方法新表必须存在)
mysql> create table newUser like user;
mysql> desc newUser;
+-------------+--------------+------+-----+----------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+----------+-------+
| id | int(5) | NO | | 10086 | |
| name | char(128) | NO | | undefine | |
| sex | int(1) | YES | | 0 | |
| qq_id | int(10) | YES | | NULL | |
| addr | varchar(256) | YES | | NULL | |
| description | varchar(512) | YES | | NULL | |
+-------------+--------------+------+-----+----------+-------+
mysql> INSERT INTO newUser SELECT * FROM user;
mysql> SELECT * FROM newUser;
WeiyiGeek.
注意事项:
描述:UPDATE 语句用于更新表中已存在的记录。
语法:
UPDATE table_name
SET column1=value1,column2=value2,...
WHERE some_column=some_value;
基础示例:
-- 假设我们要把 "菜鸟教程" 的 alexa 排名更新为 5000,country 改为 USA。
UPDATE websites SET alexa = '5000', country = 'CN' WHERE name = "菜鸟教程"; /* WHERE 语句很重要 */
补充说明:
1.在 MySQL 中可以通过设置 sql_safe_updates 这个自带的参数来解决,当该参数开启的情况下,你必须在update 语句后携带 where 条件,否则就会报错。
mysql> SHOW VARIABLES LIKE 'sql_safe_updates'; -- 值得(注意)
Variable_name Value
sql_safe_updates OFF
-- 表示开启该参数
set sql_safe_updates=ON;
set sql_safe_updates=1;
-- 开启后必须在更新语句后加入Where条件,否则在进行删除时候会产生错误;
ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
注意事项:
描述:DELETE 语句用于删除表中的行。
DELETE FROM table_name
WHERE some_column=some_value;
基础数据:
-- 假设我们要从 "Websites" 表中删除网站名为 "ORACLE" 且国家为 USA 的网站 。
DELETE FROM websites WHERE name='oracle' and country='USA';
-- 删除所有数据但是表结构、属性、索引将保持不变:
DELETE FROM table_name;
DELETE * FROM table_name;
WeiyiGeek.
补充说明:
1.SQL关于删除的三个语句:DROP、TRUNCATE、 DELETE
的区别:
删除表: drop table 表名;
清空表数据: delete from 表名;
清空表数据: truncate table 表名;
#1.删除表test并释放空间,将test删除的一干二净。
DROP table test;
#2.删除表test里的内容并释放空间,但不删除表的定义,表的结构还在。
TRUNCATE test;
#3.删除整个表:仅删除表test内的所有内容,保留表的定义,不释放空间。
DELETE FROM test 或者 DELETE * FROM test ; @
#删除指定数据:删除表test中年龄等于30的且国家为US的数据
DELETE FROM test WHERE age=30 AND country='US';
WeiyiGeek.
2.什么时候使用DROP?什么时候使用DELETE?
答:对于结构删除,如数据库删除、表删除、索引删除等当使用DROP,而对于数据的删除,和事务有关, 或者想触发 trigger则用DELETE,想保留表而将所有数据删除和事务无关用 truncate 即可,如果是整理表内部的碎片,可以用 truncate 跟上 reuse stroage
再重新导入/插入数据;;
3.总结
drop > truncate > delete
,安全性: 小心使用 drop 和 truncate, 尤其没有备份的时候否则哭都来不及。
注意事项:
描述:SQL语句联合使用的其他子语句,是相当的重要的;
描述:SELECT TOP 子句用于规定要返回的记录的数目,它对于拥有数千条记录的大型表来说,是非常有用的。
-- #SQL Server / MS Access 语法
SELECT TOP number|percent column_name(s)
FROM table_name;
-- #MySQL 语法
SELECT column_name(s)
FROM table_name
LIMIT number;
-- #Oracle 语法
SELECT column_name(s)
FROM table_name
WHERE ROWNUM <= number;
基础示例:
-- 从 websites 表中选取前面百分之 50 的记录(MSSQL):
SELECT TOP 50 PERCENT * FROM Websites;
select top 5 * from table --前5行
select top 5 * from table order by id desc --后5行 desc 表示降序排列 asc 表示升序
注意事项:
基础语法:
/* LIKE 操作符用于在 WHERE 子句中搜索列中的指定模式 */
SELECT column_name(s)
FROM table_name
WHERE column_name [LIKE|REGEXP] pattern;
LIKE 模糊查询通配符说明: % 表示多个字值,_ 下划线表示一个字符
;
REGEXP 模糊查询通配符说明:'[abc]'字符列中的任何单一字符,[!abc]或者[^abc]不在字符列中的任何单一字符
;
'^[a-zA-Z0-9]'
:表示查询以a-z或者A-Z以及0-9开头的内容;基础示例:
-- LIKE子句的模糊查询
SELECT host,user FROM user WHERE user LIKE '%ro%'
-- REGEXP子句显示user字段以root开头的行(注意引号包含表达式)
SELECT host,user FROM user WHERE user REGEXP '^root'
WeiyiGeek.
描述:IN 操作符允许您在 WHERE 子句中规定多个值。
-- SQL IN 语法(以 , 号分割)
SELECT column_name(s)
FROM table_name
WHERE column_name IN (value1,value2,...);
IN 与 = 的异同说明?
基础示例:
-- in 与 = 的转换
select * from Websites where name in ('Google','Baidu');
select * from Websites where name='Google' or name='Baidu';
-- 注意数值和字符串对查询的结果没有影响
select * from user where xh in (1001,'1003');
WeiyiGeek.
描述:BETWEEN 操作符用于选取介于两个值之间的数据范围内的值(值可以是数值,文本或者日期
)。
-- SQL BETWEEN 语法
SELECT column_name(s)
FROM table_name
WHERE column_name BETWEEN value1 AND value2;
基础演示:
-- SQL 语句选取 alexa 介于 1 和 20 之间的所有网站:
SELECT * FROM Websites
WHERE alexa BETWEEN 1 AND 20;
-- 如需显示不在上面实例范围内的网站,请使用 NOT BETWEEN:
SELECT * FROM Websites
WHERE alexa NOT BETWEEN 1 AND 20;
-- 选取 alexa 介于 1 和 20 之间但 country 不为 USA 和 IND 的所有网站(注意ADD子句)
SELECT * FROM Websites
WHERE (alexa BETWEEN 1 AND 20)
AND country NOT IN ('USA', 'IND');
-- 选取 name 以介于 'A' 和 'H' 之间字母开始的所有网站(带有文本值的 BETWEEN 操作符)
SELECT * FROM Websites
WHERE name BETWEEN 'A' AND 'H';
-- SQL 语句选取 date 介于 '2016-05-10' 和 '2016-05-14' 之间的所有访问记录:
SELECT * FROM access_log
WHERE date BETWEEN '2016-05-10' AND '2016-05-14';
-- MySQL用户的修改时间范围
SELECT User,password_last_changed FROM user
WHERE password_last_changed
BETWEEN ' 2020-01-03 09:22:32' AND ' 2020-01-03 09:22:38';
WeiyiGeek.
注意事项:
但不包括两个测试值的字段 ,且包括两个测试值的字段,且包括第一个测试值但不包括最后一个测试值的字段
)描述:通过使用 SQL,可以为表名称或列名称指定别名(创建别名是为了让列名称的可读性更强)。 在下面的情况下使用别名很有用:
基础语法:
-- 列的 SQL 别名语法
SELECT column_name AS alias_name
FROM table_name;
-- 表的 SQL 别名语法
SELECT column_name(s)
FROM table_name AS alias_name;
基础演示:
-- 字段别名的示例
SELECT xh AS '学号',kcm AS '课程', grade AS '成绩'
FROM user_kc
WHERE grade > 70;
WeiyiGeek.AS别名字段
-- 表的别名实例
SELECT u.xh,u.xm,kc.kcm,kc.grade
FROM user AS u,user_kc AS kc
WHERE kc.xh = u.xh
ORDER BY kc.xh;
WeiyiGeek.
-- 字段拼接(这里采用CONCAT函数后面会深入讲解)
SELECT CONCAT( '学号:', u.xh , '姓名:', u.xm) AS '基础信息',CONCAT( '课程:', kc.kcm , '成绩:', kc.grade) AS '成绩信息',
FROM user AS u,user_kc AS kc
WHERE kc.xh = u.xh AND kc.kcm = 'Python编程'
ORDER BY xh
WeiyiGeek.
描述:SQL join 用于把来自两个或多个表的行结合起来,基于这些表之间的共同字段。。 下图展示了 LEFT JOIN、RIGHT JOIN、INNER JOIN、OUTER JOIN 相关的 7 种用法。
A∩B={x|x∈A,且x∈B}
A∪B={x|x∈A,或x∈B}
。
WeiyiGeek.
不同的 SQL JOIN 分类:
INNER JOIN(内连接-笛卡尔积) 描述:SQL INNER JOIN 从多个表中返回满足 JOIN 条件的所有行,在表中存在至少一个匹配时返回行。
-- 在表中存在至少一个匹配时返回行。
SELECT column_name(s)
FROM table1
INNER JOIN table2
ON table1.column_name=table2.column_name;
-- 或:(INNER JOIN 与 JOIN 是相同的)
SELECT column_name(s)
FROM table1
JOIN table2
ON table1.column_name=table2.column_name;
基础示例:
-- 显示满足ON条件的行,否则以左边基准表 + user_kc 每一条
SELECT u.xh,u.xm,kc.kcm,kc.grade
FROM user AS u
INNER JOIN user_kc AS kc ON u.xh = kc.xh
ORDER BY u.xh
WeiyiGeek.
LEFT JOIN 关键字 描述:LEFT JOIN 关键字从左表(table1)返回所有的行,即使右表(table2)中没有匹配。如果右表中没有匹配,则结果为 NULL。
SQL LEFT JOIN 语法
SELECT column_name(s)
FROM table1
LEFT JOIN table2
ON table1.column_name=table2.column_name;
或:
SELECT column_name(s)
FROM table1
LEFT OUTER JOIN table2
ON table1.column_name=table2.column_name;
基础实例:
-- LEFT JOIN 关键字演示
INSERT INTO user VALUES (1006,'WeiyiGeek','2019',21,'网络安全工程');
SELECT u.xh,u.xm,kc.kcm,kc.grade
FROM user AS u
LEFT JOIN user_kc AS kc ON u.xh = kc.xh
ORDER BY u.xh
WeiyiGeek.
RIGHT JOIN 关键字 描述:RIGHT JOIN 关键字从右表(table2)返回所有的行,即使左表(table1)中没有匹配。如果左表中没有匹配,则结果为 NULL。实际就是与LEFT相似只不过是左边关联不上的为NULL
SQL RIGHT JOIN 语法:
SELECT column_name(s)
FROM table1
RIGHT JOIN table2
ON table1.column_name=table2.column_name;
-- 或
SELECT column_name(s)
FROM table1
RIGHT OUTER JOIN table2
ON table1.column_name=table2.column_name;
基础实例:
-- 这次将user_kc作为左表,而user作为右表
SELECT u.xh,u.xm,kc.kcm,kc.grade
FROM user_kc AS kc -- 注意此处与上面是不同的
RIGHT JOIN user AS u ON u.xh = kc.xh
ORDER BY u.xh
WeiyiGeek.
FULL OUTER JOIN 关键字
描述:FULL OUTER JOIN 关键字只要左表(table1)和右表(table2)其中一个表中存在匹配,则返回行 它结合了 LEFT JOIN 和 RIGHT JOIN 的结果即 A 并 B
。
FULL OUTER JOIN 语法:
SELECT column_name(s)
FROM table1
FULL OUTER JOIN table2
ON table1.column_name=table2.column_name;
基础实例:
#MySQL中不支持 FULL OUTER JOIN,你可以在 SQL Server 测试以下实例。
SELECT Websites.name, access_log.count, access_log.date
FROM Websites
FULL OUTER JOIN access_log
ON Websites.id=access_log.site_id
ORDER BY access_log.count DESC;
总结:
1.首先连接的结果可以在逻辑上看作是由SELECT语句指定的列组成的新表。左连接与右连接的左右指的是以两张表中的哪一张为基准它们都是外连接。
2.外连接就好像是为非基准表添加了一行全为空值的万能行,用来与基准表中找不到匹配的行进行匹配,两个没有空值的表进行左连接,左表是基准表
,左表的所有行都出现在结果中,右表则可能因为无法与基准表匹配而出现是空值的字段
。
3.JOIN 分类得到的结果数:
inner join <= min(left join, right join)
full join >= max(left join, right join)
当 inner join < min(left join, right join) 时 full join > max(left join, right join)
4.在使用 join 时,on 和 where 条件的区别如下:
- on 条件是在生成临时表时使用的条件,它不管 on 中的条件是否为真都会返回左边表中的记录。
- where 条件是在临时表生成好后,再对临时表进行过滤的条件。这时已经没有 left join 的含义(必须返回左边表的记录)了,条件不为真的就全部过滤掉。
5.MySQL中不支持 FULL OUTER JOIN,你可以在 SQL Server 测试以下实例。
描述:SQL UNION 操作符合并两个或多个 SELECT 语句的结果。
-- SQL UNION 语法
SELECT column_name(s) FROM table1
UNION
SELECT column_name(s) FROM table2;
---SQL UNION ALL 语法
SELECT column_name(s) FROM table1
UNION ALL -- 默认地UNION 操作符选取不同的值。如果允许重复的值请使用 UNION ALL。
SELECT column_name(s) FROM table2;
基础实例:
-- 从 "Websites" 和 "apps" 表中选取所有不同的country(只有不同的值):
SELECT country FROM Websites
UNION
SELECT country FROM apps
ORDER BY country;
-- 使用 UNION ALL 从 "Websites" 和 "apps" 表中选取所有的中国(CN)的数据(也有重复的值):
SELECT country, name FROM Websites
WHERE country='CN'
UNION ALL
SELECT country, app_name FROM apps
WHERE country='CN'
ORDER BY country;
-- union 与 union all 在于前者可以剔除重复的字段的行,后者则是显示所有不管是否重复
SELECT xh,'#',xm FROM user
UNION ALL
SELECT xh,kcm,'-' FROM user_kc
ORDER BY xh
WeiyiGeek.
注意事项:
描述:GROUP BY 语句用于结合聚合函数,根据一个或多个列对结果集进行分组。
基础语法:
-- SQL GROUP BY 语法
SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name;
基础应用:
-- 统计 access_log 各个 site_id 的访问量
SELECT site_id, SUM(counts) AS nums FROM access_log GROUP BY site_id;
-- SQL GROUP BY 多表连接统计有记录的网站的记录数量:
SELECT Websites.name,COUNT(access_log.aid) AS nums FROM access_log
LEFT JOIN Websites -- 关键点-表字段结合
ON access_log.site_id=Websites.id
GROUP BY Websites.name; -- 关键点
-- 基础实例
SELECT Aggregate.NAME,COUNT(Persons.ID) AS 'NUMS'
FROM Persons
LEFT JOIN Aggregate
ON Aggregate.ID = Persons.ID
GROUP BY Aggregate.NAME;
SELECT Aggregate.NAME,COUNT(Persons.ID) AS 'NUMS'
FROM Persons
LEFT JOIN Aggregate
ON Aggregate.NAME = Persons.LastName
GROUP BY Aggregate.NAME;
WeiyiGeek.
描述:HAVING 子句可以让我们筛选分组后的各组数据; 在 SQL 中增加 HAVING 子句原因是 WHERE 关键字无法与聚合函数一起使用
。
-- SQL HAVING 语法
SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name
HAVING aggregate_function(column_name) operator value;
基础示例:
-- 查找总访问量大于 200 的网站,并且 alexa 排名小于 200。
SELECT Websites.name, SUM(access_log.count) AS nums FROM Websites
INNER JOIN access_log
ON Websites.id=access_log.site_id
WHERE Websites.alexa < 200
GROUP BY Websites.name
HAVING SUM(access_log.count) > 200;
-- 过滤掉分组结果为NULL的rows
SELECT Aggregate.NAME,COUNT(Persons.ID) AS 'NUMS'
FROM Persons
LEFT JOIN Aggregate
ON Aggregate.NAME = Persons.LastName
GROUP BY Aggregate.NAME
HAVING Aggregate.NAME IS NOT NULL;
WeiyiGeek.HAVING
描述:SELECT INTO 语句从一个表复制数据,然后把数据插入到另一个新表中,但是需要注意 MySQL 数据库不支持 SELECT ... INTO 语句,但支持 INSERT INTO ... SELECT
, 当然你可以使用以下语句来拷贝表结构及数据(后面讲解CREATE会讲):
CREATE TABLE 新表
AS
SELECT * FROM 旧表
SELECT INTO 语法:
-- 复制所有的列插入到新表中:
SELECT *
INTO newtable [IN externaldb]
FROM table1;
-- 只复制希望的列插入到新表中:
SELECT column_name(s)
INTO newtable [IN externaldb]
FROM table1;
基础实例:
-- 创建 Websites 的备份复件,只复制中国的网站插入到新表中:
SELECT *
INTO WebsitesBackup2016
FROM Websites;
WHERE country='CN';
-- 复制多个表中的数据插入到新表中:
SELECT Websites.name, access_log.count, access_log.date
INTO WebsitesBackup2016
FROM Websites
LEFT JOIN access_log
ON Websites.id=access_log.site_id;
-- SELECT INTO 语句可用于通过另一种模式创建一个新的空表。
SELECT *
INTO newtable
FROM table1
WHERE 1=0; -- 只需要添加促使查询没有数据返回的 WHERE 子句即可
注意事项:
描述:INSERT INTO SELECT 语句从一个表复制数据,目标表中任何已存在的行都不会受影响。然后把数据插入到一个已存在的表中
(非常注意不同于SELECT INTO语句转存的表必须存在,而且字段类型一致)。
SQL INSERT INTO SELECT 语法:
-- 从一个表中复制所有的列插入到另一个已存在的表中:
INSERT INTO table2
SELECT * FROM table1;
-- 只复制希望的列插入到另一个已存在的表中:
INSERT INTO table2 (column_name(s))
SELECT column_name(s)
FROM table1;
基础实例:
-- 复制 "apps" 中的数据插入到 "Websites" 中:
INSERT INTO Websites (name, country)
SELECT app_name, country FROM apps;
select into from 和 insert into select 两则的区别?
注意事项:
select into [newTable] from
:要求目标表不存在,因为在插入时会自动创建;将查询出来的数据整理到一张新表中保存,表结构与查询结构一致。insert into [newTable] select from
:要求目标表存在,为已经存在的表批量添加新数据。-- 即,查询出来结果--->复制一张同结构的空表--->将数据拷贝进去。
select *(查询出来的结果) into newtable(新的表名)form where (后续条件)
-- 即,指定一张想要插入数据的表格(注意建立的表的字段结构)--->对数据进行加工筛选--->填入一张准备好的表格。
insert into (已准备好的表) select *(或者取用自己想要的结构)frome 表名 where 各种条件