分类 数据库 下的文章

一、SELECT介绍

1.1 SELECT

SELECT是数据库四大基本操作的一种,用于查询表中的数据信息。

基本的查询语法为:SELECT 列1, 列2, ... FROM 表,表示从表中取出对应的列。

SELECT语句的用法多种多样,并且还有很多高级的操作(如排序、分组以及联合等等),是增删改查四种基本操作中用法最多也运用最广的命令。

1.2 测试数据

创建测试表stu_info,所有的测试将会在这张表上进行:

CREATE TABLE `stu_info` (
  `stu_id` int(12) unsigned zerofill NOT NULL AUTO_INCREMENT,
  `stu_name` varchar(255) NOT NULL DEFAULT '',
  `age` tinyint(4) NOT NULL,
  `classno` tinyint(4) NOT NULL,
  `city` varchar(255) NOT NULL,
  PRIMARY KEY (`stu_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

表中数据:

+--------------+-----------+-----+---------+----------+
| stu_id       | stu_name  | age | classno | city     |
+--------------+-----------+-----+---------+----------+
| 000000000001 | maqian    |  24 |       1 | changsha |
| 000000000002 | xiaoming  |  19 |       2 | shanghai |
| 000000000003 | xiaohua   |  23 |       2 | shenzhen |
| 000000000004 | xiaobai   |  22 |       3 | shenzhen |
| 000000000005 | xiaowang  |  19 |       4 | hunan    |
| 000000000006 | xiaozhou  |  20 |       3 | wuhan    |
| 000000000007 | xiaoli    |  20 |       1 | changsha |
| 000000000008 | xiaopeng  |  23 |       1 | changsha |
| 000000000009 | xiaozheng |  22 |       1 | fujian   |
+--------------+-----------+-----+---------+----------+

二、使用SELECT查询数据

2.1 查询单列数据

查询所有的学生名字:

SELECT stu_name FROM stu_info;

结果:

+-----------+
| stu_name  |
+-----------+
| maqian    |
| xiaoming  |
| xiaohua   |
| xiaobai   |
| xiaowang  |
| xiaozhou  |
| xiaoli    |
| xiaopeng  |
| xiaozheng |
+-----------+
注意事项:查询时,如果没有明确指定排序对象,返回的数据中顺序没有特殊意义,每次返回的顺序可能都不同。只要保证每次返回的行数是一样的就是正常。

2.2 查询多个列

查询所有学生的名字及年龄信息,查询多列时,不同列之间使用,隔开:

SELECT stu_name, age FROM stu_info;

结果:

+-----------+-----+
| stu_name  | age |
+-----------+-----+
| maqian    |  24 |
| xiaoming  |  19 |
| xiaohua   |  23 |
| xiaobai   |  22 |
| xiaowang  |  19 |
| xiaozhou  |  20 |
| xiaoli    |  20 |
| xiaopeng  |  23 |
| xiaozheng |  22 |
+-----------+-----+

2.3 查询所有列

使用通配符*表示查询所有列:

SELECT * FROM stu_info;

结果:

+--------------+-----------+-----+---------+----------+
| stu_id       | stu_name  | age | classno | city     |
+--------------+-----------+-----+---------+----------+
| 000000000001 | maqian    |  24 |       1 | changsha |
| 000000000002 | xiaoming  |  19 |       2 | shanghai |
| 000000000003 | xiaohua   |  23 |       2 | shenzhen |
| 000000000004 | xiaobai   |  22 |       3 | shenzhen |
| 000000000005 | xiaowang  |  19 |       4 | hunan    |
| 000000000006 | xiaozhou  |  20 |       3 | wuhan    |
| 000000000007 | xiaoli    |  20 |       1 | changsha |
| 000000000008 | xiaopeng  |  23 |       1 | changsha |
| 000000000009 | xiaozheng |  22 |       1 | fujian   |
+--------------+-----------+-----+---------+----------+
使用*来输出所有列时,会严重降低检索和应用程序的性能。大部分时候,尽量少使用用通配符,明确自己所需要的列。

2.4 去除重复数据

在查询时,可以通过DISTINCT关键字来剔除重复的行。如查询所有的班级(不重复):

SELECT DISTINCT classno FROM stu_info;

结果:

+---------+
| classno |
+---------+
|       1 |
|       2 |
|       3 |
|       4 |
+---------+

当对多个关键字使用DISTINCT时,只有所有列都相同才会被认为是重复的,其中某个字段相同并不会认为是同一个行:

SELECT DISTINCT classno, city FROM stu_info;

上面的数据中,有多个classno=1并且city=changsha的结果,使用DISTINCT之后,这些重复的行被剔除了,而同样classno=但是city=fujian的记录却依然存在:

+---------+----------+
| classno | city     |
+---------+----------+
|       1 | changsha |
|       2 | shanghai |
|       2 | shenzhen |
|       3 | shenzhen |
|       4 | hunan    |
|       3 | wuhan    |
|       1 | fujian   |
+---------+----------+

2.5 限制结果

使用LIMIT关键字可以限制输出的结果数量,语法格式为:

  1. LIMIT N:只输出前面N条记录。
  2. LIMIT M,N:从第M条记录开始,输出N条记录。
  3. LIMIT N OFFSET M:MYSQL从5.0开始支持的语法,作用和第二条一样,从M开始输出N条记录。
第三种用法实际上是为了解决用户会混淆M,N究竟是从M开始的N条记录还是N开始的M条记录的问题。

2.5.1 显示前面5条记录

SELECT classno, city FROM stu_info LIMIT 5;

结果:

+---------+----------+
| classno | city     |
+---------+----------+
|       1 | changsha |
|       2 | shanghai |
|       2 | shenzhen |
|       3 | shenzhen |
|       4 | hunan    |
+---------+----------+

2.5.2 从第5条之后显示5条记录

SELECT classno, city FROM stu_info LIMIT 5, 5;

结果:

+---------+----------+
| classno | city     |
+---------+----------+
|       3 | wuhan    |
|       1 | changsha |
|       1 | changsha |
|       1 | fujian   |
+---------+----------+

当实际的记录数量小于剩余记录时,输出的结果并不会达到我们想要的行数。

使用SELECT classno, city from stu_info LIMIT 4 OFFSET 5的结果也和上面一样!

三、对结果排序

排序是查询是最常用的的功能之一,语法格式为ORDER BY col1, col2,表示根据col1col2排序。

MYSQL支持对单行和多行数据排序,也支持正序和倒序排序。默认情况是正序排序,逆序排序需要手动添加关键字DESC

3.1 对单列数据排序

输出学生的年龄、班级和名字,并针对年龄排序:

SELECT age, stu_name FROM stu_info ORDER BY age;

结果:

+-----+---------+-----------+
| age | classno | stu_name  |
+-----+---------+-----------+
|  19 |       2 | xiaoming  |
|  19 |       4 | xiaowang  |
|  20 |       3 | xiaozhou  |
|  20 |       1 | xiaoli    |
|  22 |       3 | xiaobai   |
|  22 |       1 | xiaozheng |
|  23 |       2 | xiaohua   |
|  23 |       1 | xiaopeng  |
|  24 |       1 | maqian    |
+-----+---------+-----------+

可以看到,age列都是从小到大排列,而classno还是处于无序的状态。

3.2 对多列数据排序

在上面的基础上,添加对班级排序逻辑。即当学生年龄一致的时候,根据所在的班级排序:

SELECT age, classno, stu_name FROM stu_info ORDER BY age, classno;

结果:

+-----+---------+-----------+
| age | classno | stu_name  |
+-----+---------+-----------+
|  19 |       2 | xiaoming  |
|  19 |       4 | xiaowang  |
|  20 |       1 | xiaoli    |
|  20 |       3 | xiaozhou  |
|  22 |       1 | xiaozheng |
|  22 |       3 | xiaobai   |
|  23 |       1 | xiaopeng  |
|  23 |       2 | xiaohua   |
|  24 |       1 | maqian    |
+-----+---------+-----------+

结果中,所有年龄相同的行,班级序号也是有序的。

3.3 逆序排序

逆序输出所有的学生名字:

SELECT stu_name FROM stu_info ORDER BY stu_name DESC;

结果:

+-----------+
| stu_name  |
+-----------+
| xiaozhou  |
| xiaozheng |
| xiaowang  |
| xiaopeng  |
| xiaoming  |
| xiaoli    |
| xiaohua   |
| xiaobai   |
| maqian    |
+-----------+

四、其他

4.1 使用完全限定的表名

查询时,可以明确查询的表名和列名,如:

SELECT stu_info.stu_name from stu_info;
注意:不可省略最后的表信息,不要认为列中限定了表名最后就不用再添加表名了。

效果等同于:

SELECT stu_name FROM stu_info;

这种用法一般适用于多表之间的联合查询,当两个表中的字段有重合时,需要明确指定表名来限定查询的是哪个表中的字段。

一、主从复制原理

MySQL主从复制依赖binlog,binlog中记录了数据库中的执行过的语句,主从复制时,复制的并不是整个数据库中的所有数据,而是从上次同步到现在所执行过的SQL语句。

执行主从同步时,主库会有一个Log-Dump线程和从库同步,把binlog发送给从库。从库则有一个I/O线程和SQL-Thread线程分别用于和主库同步和重放。同步过程是:

  1. 从库的I/O线程向主库请求同步,主库把数据发送过来。
  2. 收到主库的binlog后,从库会把日志放到relay-log。
  3. SQL线程重放SQL语句,数据达到同步。

二、复制方式

2.1 异步复制

默认情况下MySQL是异步复制,即SQL语句执行完成后写入binlog就可以了,不用等待主从数据同步完成。

2.2 半同步复制

同步复制的意思是每次执行SQL语句要等待从库写入到relay log后才能继续往下执行,这样就避免了主库以外宕机后从库数据不一致的情况。

+
8 rows in set (0.00 sec)


## 二、授权

grant [privileges] on db.table to ''user''@''host''

// 授予用户所有权限
grant all privileges on . to ''maqian''@''%''


## 三、修改用户密码

-- 当前用户
set password = password(''123456'')
-- 非当前用户
set password for ''user''@''host'' = password(''123456'')


## 四、取消授权

revoke [privilege] on db.table from ''user''@''host''


## 五、删除用户

drop user ''user''@''localhost''

primary key 用于标识主键,字段被设置为主键后该字段所有值不可重复且不能为null ,每个表仅可有一个主键。unique 设置字段不可重复,但不包括null 值,每张表可以有多个unique 字段,null 并不包括空值

简单来说primary key = unique + not null

- 阅读剩余部分 -

一、发布和订阅

除了任务队列以外,redis还有一种基于“发布/订阅”模式的消息传递,使得客户端可以订阅某个频道,当频道有消息产生时,会把消息传递到所有的订阅者。和列表不一样的是,发布和订阅可以是一对多的关系,即同一个消息可以同时传递到多个客户端(订阅者)。而列表只能允许一个客户端接收一个消息。

订阅和退订的命令是PUBLISH/SUBSCRIBEPUBLISH是向频道发送消息,SUBSCRIBE是订阅频道。

1.1 发布

往指定频道发布消息的操作:

PUBLISH channel message

消息发送成功后,将会返回一个整数,表示收到这条消息的订阅者数量,如果没有任何客户端订阅频道,返回0。

一个要注意的问题是消息发布后不会被持久化,如果当前没有订阅者订阅频道,后续再订阅也不会收到订阅前的消息。

- 阅读剩余部分 -

一、任务队列概述

消息队列,顾名思义就是一个用来传递任务的队列。消息队列在开发中十分常见,经常用在页面后台处理需要很长时间的操作时,例如发送邮件、短信以及进行复杂数据运算操作等,这些操作通常会阻塞页面相当长的时间,为了避免用户等待太久,一般会先给用户页面进行相应,然后在后台使用独立的线程或者进程来处理这些复杂的操作。

消息队列分为两个部分,生产者和消费者。生产者负责把任务放进队列,消费者则负责从队列中取出任务执行。最常见的一个场景是:当我们在某个站点注册账号时,一般都会给我们的邮箱发送邮件验证,由于发送邮件比较耗时,并且邮件的实时性要求也不是很高,所以这里就可以使用消息队列来完成。先把发送邮件放到队列中,然后开启另外的一个线程专门读取任务,读取邮件并发送出去。

- 阅读剩余部分 -

网站中经常需要用到网站限流,例如限制用户恶意爬虫获取网页信息以及在网站访问流量大时限制访问频率等等,这里使用redis做一个简单的网站登录限制案例。

一、使用EXPIRE进行访问频率限制

逻辑:用户登入网页,判断是否为第一次登入,如果是,创建一个新键记录访问次数为1,并设置超时时间。后面再登入时先判断键是否存在且大于访问次数限制,如果是的话,返回错误页面,否则访问次数+1,正常访问。

- 阅读剩余部分 -

一、安装

redis中操作redis的模块为redis-py,使用pip install redis或者easy_install redis安装即可,也可以进去https://pypi.python.org/pypi/redis下载源码安装。

二、使用

安装好模块后,使用import redis即可导入模块。

2.1 创建连接

r = redis.StrictRedis()  # 默认连接127.0.0.1:6379
r = redis.StrictRedis(host="127.0.0.1", port=6379, db=0)  #显示指定主机、端口号和数据库

- 阅读剩余部分 -

一、expire和ttl命令

1.1 基本用法

Redis中的EXPIER 命令可以给键值设置过期时间,相关的命令及其格式为:

EXPIRE key seconds
PEXPIRE key milliseconds

两个命令分别表示设置秒级和毫秒级别的过期时间,到期之后系统会自动删除该键。

EXPIRE 命令返回1 表示设置过期时间成功,返回0 表示键不存在或者设置失败。

127.0.0.1:6379> set k 1
OK
127.0.0.1:6379> expire k 60
(integer) 1
127.0.0.1:6379> expire x 1
(integer) 0

- 阅读剩余部分 -