MySQL必知必会:使用SELECT进行数据的简单检索

以“MySQL必知必会”开头的文章大部分是学习**《MySQL必知必会》**这本之前没看完的经典书籍的学习记录。
主要内容:会按照书中目录step by step进行,使用navicat可视化软件,根据目录的需求驱动,记录SQL语句、分析与结果。当然,这部分知识并不是孤立的,有时会结合python进行实现,会参考《高性能MySQL》、《数据库系统概论》等资料关联重要原理,还会对一些可用的ORM API的实例化操作进行记录。

一,连接数据库

使用python连接MySQL数据库:

先创建数据库:
CREATE TABLE `users` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `email` varchar(255) COLLATE utf8_bin NOT NULL,
    `password` varchar(255) COLLATE utf8_bin NOT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
AUTO_INCREMENT=1 ;

连接并操作:
import pymysql.cursors
# Connect to the database
connection = pymysql.connect(host='localhost',
                             user='root',
                             password='root',
                             db='test',
                             port=3306,
                             charset="utf8",
                             cursorclass=pymysql.cursors.DictCursor)

try:
    with connection.cursor() as cursor:
        # Create a new record
        sql = "INSERT INTO `users` (`email`, `password`) VALUES (%s, %s)"
        cursor.execute(sql, ('[email protected]', 'very-secret'))

    # connection is not autocommit by default. So you must commit to save your changes.
    connection.commit()

    with connection.cursor() as cursor:
        # Read a single record
        sql = "SELECT `id`, `password` FROM `users` WHERE `email`=%s"
        cursor.execute(sql, ('[email protected]',))
        result = cursor.fetchone()
        print(result)
finally:
    connection.close()

打印:
{
    
    'id': 1, 'password': 'very-secret'}
  • 使用pymysql提供的参数化语句避免注入。

二,创建及使用数据库

1,创建数据库:

mysql> CREATE DATABASE crashcourse;
Query OK, 1 row affected (0.10 sec)
mysql> show create database crashcourse; 
+-------------+---------------------------------------------------------------------------------------------------------------------------------------+
| Database    | Create Database                                                                                                                       |
+-------------+---------------------------------------------------------------------------------------------------------------------------------------+
| crashcourse | CREATE DATABASE `crashcourse` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */ |
+-------------+---------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.02 sec)

mysql> show databases;  # 了解数据库,返回数据库列表
+--------------------+
| Database           |
+--------------------+
| crashcourse        |
| information_schema |
| messageboard       |
| mysql              |
| mysqlite3          |
| performance_schema |
| spyders            |
| sys                |
+--------------------+
8 rows in set (0.01 sec)

2,使用数据库:

mysql> use crashcourse; #指定使用的数据库
Database changed

三,创建及使用数据表

1,创建数据表:

CREATE TABLE customers
(
  cust_id      int       NOT NULL AUTO_INCREMENT,
  cust_name    char(50)  NOT NULL ,
  cust_address char(50)  NULL ,
  cust_city    char(50)  NULL ,
  cust_state   char(5)   NULL ,
  cust_zip     char(10)  NULL ,
  cust_country char(50)  NULL ,
  cust_contact char(50)  NULL ,
  cust_email   char(255) NULL ,
  PRIMARY KEY (cust_id)
) ENGINE=InnoDB;


mysql> sshow create table productnotes;  #查看创建表productnotes表的mysql代码语句
+--------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table        | Create Table                                                                                                                                                                                                                                                                               |
+--------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| productnotes | CREATE TABLE `productnotes` (
  `note_id` int NOT NULL AUTO_INCREMENT,
  `prod_id` char(10) NOT NULL,
  `note_date` datetime NOT NULL,
  `note_text` text,
  PRIMARY KEY (`note_id`),
  FULLTEXT KEY `note_text` (`note_text`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+--------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.03 sec)

mysql> show tables;  
+-----------------------+
| Tables_in_crashcourse |
+-----------------------+
| customers             |
| orderitems            |
| orders                |
| productnotes          |
| products              |
| vendors               |
+-----------------------+
6 rows in set (0.01 sec)

2,使用数据表:

插入数据:
INSERT INTO customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email)
VALUES(10001, 'Coyote Inc.', '200 Maple Lane', 'Detroit', 'MI', '44444', 'USA', 'Y Lee', '[email protected]');
INSERT INTO customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact)
VALUES(10002, 'Mouse House', '333 Fromage Lane', 'Columbus', 'OH', '43333', 'USA', 'Jerry Mouse');
INSERT INTO customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email)
VALUES(10003, 'Wascals', '1 Sunny Place', 'Muncie', 'IN', '42222', 'USA', 'Jim Jones', '[email protected]');
INSERT INTO customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email)
VALUES(10004, 'Yosemite Place', '829 Riverside Drive', 'Phoenix', 'AZ', '88888', 'USA', 'Y Sam', '[email protected]');
INSERT INTO customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact)
VALUES(10005, 'E Fudd', '4545 53rd Street', 'Chicago', 'IL', '54545', 'USA', 'E Fudd');


显示表列:
mysql> show columns from customers; 
+--------------+-----------+------+-----+---------+----------------+
| Field        | Type      | Null | Key | Default | Extra          |
+--------------+-----------+------+-----+---------+----------------+
| cust_id      | int       | NO   | PRI | NULL    | auto_increment |
| cust_name    | char(50)  | NO   |     | NULL    |                |
| cust_address | char(50)  | YES  |     | NULL    |                |
| cust_city    | char(50)  | YES  |     | NULL    |                |
| cust_state   | char(5)   | YES  |     | NULL    |                |
| cust_zip     | char(10)  | YES  |     | NULL    |                |
| cust_country | char(50)  | YES  |     | NULL    |                |
| cust_contact | char(50)  | YES  |     | NULL    |                |
| cust_email   | char(255) | YES  |     | NULL    |                |
+--------------+-----------+------+-----+---------+----------------+
9 rows in set (0.02 sec)

3,使用SHOW查看一些内部信息:

show status; # 用于显示广泛的服务器状态信息
show grants; #显示授予用户(所有用户或特定用户)的安全权限
show errors; # 显示服务器错误内容
show warnings#显示服务器警告内容

四,使用SELECT检索数据

SELECT的用途是从一个或多个表中检索信息。
在这里插入图片描述

1,检索单个列

使用SELECT,必须至少给出——想选择什么,以及从什么地方选择。

mysql> select prod_name from products;  # 从products表中检索prod_name 单列
+----------------+
| prod_name      |
+----------------+
| .5 ton anvil   |
| 1 ton anvil    |
| 2 ton anvil    |
| Detonator      |
| Bird seed      |
| Carrots        |
| Fuses          |
| JetPack 1000   |
| JetPack 2000   |
| Oil can        |
| Safe           |
| Sling          |
| TNT (1 stick)  |
| TNT (5 sticks) |
+----------------+
14 rows in set (0.03 sec)
  • 如果没有明确排序查询结果(下一章介绍),则返回的数据的顺序没有特殊意义。

2,检索多个列

在SELECT关键字后给出多个列名,列名之间必须以逗号分隔。

mysql> select prod_id,prod_name,prod_price from products;   # 从products表中检索prod_name,prod_name,prod_price 多列  
+---------+----------------+------------+
| prod_id | prod_name      | prod_price |
+---------+----------------+------------+
| ANV01   | .5 ton anvil   | 5.99       |
| ANV02   | 1 ton anvil    | 9.99       |
| ANV03   | 2 ton anvil    | 14.99      |
| DTNTR   | Detonator      | 13.00      |
| FB      | Bird seed      | 10.00      |
| FC      | Carrots        | 2.50       |
| FU1     | Fuses          | 3.42       |
| JP1000  | JetPack 1000   | 35.00      |
| JP2000  | JetPack 2000   | 55.00      |
| OL1     | Oil can        | 8.99       |
| SAFE    | Safe           | 50.00      |
| SLING   | Sling          | 4.49       |
| TNT1    | TNT (1 stick)  | 2.50       |
| TNT2    | TNT (5 sticks) | 10.00      |
+---------+----------------+------------+
14 rows in set (0.03 sec)
  • 从上述输出可以看到, SQL语句一般返回原始的、无格式的数据。数据的格式化是一个表示问题,而不是一个检索问题。

3,检索所有列

在实际列名的位置使用星号(*)通配符。

mysql> select * from products;  # 从products表中检索所有列,通常情况下,检索不需要的列会降低检索和应用程序的效率
+---------+---------+----------------+------------+----------------------------------------------------------------+
| prod_id | vend_id | prod_name      | prod_price | prod_desc                                                      |
+---------+---------+----------------+------------+----------------------------------------------------------------+
| ANV01   |    1001 | .5 ton anvil   | 5.99       | .5 ton anvil, black, complete with handy hook                  |
| ANV02   |    1001 | 1 ton anvil    | 9.99       | 1 ton anvil, black, complete with handy hook and carrying case |
| ANV03   |    1001 | 2 ton anvil    | 14.99      | 2 ton anvil, black, complete with handy hook and carrying case |
| DTNTR   |    1003 | Detonator      | 13.00      | Detonator (plunger powered), fuses not included                |
| FB      |    1003 | Bird seed      | 10.00      | Large bag (suitable for road runners)                          |
| FC      |    1003 | Carrots        | 2.50       | Carrots (rabbit hunting season only)                           |
| FU1     |    1002 | Fuses          | 3.42       | 1 dozen, extra long                                            |
| JP1000  |    1005 | JetPack 1000   | 35.00      | JetPack 1000, intended for single use                          |
| JP2000  |    1005 | JetPack 2000   | 55.00      | JetPack 2000, multi-use                                        |
| OL1     |    1002 | Oil can        | 8.99       | Oil can, red                                                   |
| SAFE    |    1003 | Safe           | 50.00      | Safe with combination lock                                     |
| SLING   |    1003 | Sling          | 4.49       | Sling, one size fits all                                       |
| TNT1    |    1003 | TNT (1 stick)  | 2.50       | TNT, red, single stick                                         |
| TNT2    |    1003 | TNT (5 sticks) | 10.00      | TNT, red, pack of 10 sticks                                    |
+---------+---------+----------------+------------+----------------------------------------------------------------+
14 rows in set (0.03 sec)

4,检索不同的行

使用DISTINCT关键字,此关键字指示MySQL只返回不同的值。

mysql> select prod_id,vend_id from products; 
+---------+---------+
| prod_id | vend_id |
+---------+---------+
| ANV01   |    1001 |
| ANV02   |    1001 |
| ANV03   |    1001 |
| FU1     |    1002 |
| OL1     |    1002 |
| DTNTR   |    1003 |
| FB      |    1003 |
| FC      |    1003 |
| SAFE    |    1003 |
| SLING   |    1003 |
| TNT1    |    1003 |
| TNT2    |    1003 |
| JP1000  |    1005 |
| JP2000  |    1005 |
+---------+---------+
14 rows in set (0.03 sec)

mysql> select distinct vend_id from products; 
+---------+
| vend_id |
+---------+
|    1001 |
|    1002 |
|    1003 |
|    1005 |
+---------+
4 rows in set (0.03 sec)
  • DISTINCT关键字应用于所有列而不仅是前置它的列。如果给出SELECT DISTINCT vend_id,prod_price,除非指定的两个列都不同,否则所有行都将被检索出来.

5,结果限制

1,返回第一行或前几行,可使用LIMIT子句:

mysql> select prod_name from products limit 5; #从第 0 行开始,返回前 5 行
+--------------+
| prod_name    |
+--------------+
| .5 ton anvil |
| 1 ton anvil  |
| 2 ton anvil  |
| Detonator    |
| Bird seed    |
+--------------+
5 rows in set (0.03 sec)
  • 带一个值的LIMIT总是从第一行开始,给出的数为返回的行数。

2,返回从行5开始的5行:

mysql> select prod_name from products limit 5,5;#从第 5 行开始,检索 5 行
+--------------+
| prod_name    |
+--------------+
| Carrots      |
| Fuses        |
| JetPack 1000 |
| JetPack 2000 |
| Oil can      |
+--------------+
5 rows in set (0.03 sec)
  • 带两个值的LIMIT可以指定从行号为第一个值的位置开始。
mysql> select prod_name from products limit 4 OFFSET 3; #从第 3 行开始,检索 4 行
+-----------+
| prod_name |
+-----------+
| Detonator |
| Bird seed |
| Carrots   |
| Fuses     |
+-----------+
4 rows in set (0.03 sec)
  • 这是MySQL 5支持LIMIT的另一种替代语法

6,使用完全限定的表名

使用完全限定的名字来引用列(同时使用表名和列字)。

select products.prod_name from products;
等价于
select prod_name from products;
等价于
select products.prod_name from crashcourse.products;

五,排序数据

使用SELECT语句的ORDER BY子句,ORDER BY子句取一个或多个列的名字,根据需要排序检索出的数据。

  • SQL语句由子句构成,有些子句是必需的,而有的是可选的。一个子句通常由一个关键字和所提供的数据组成。
mysql> select prod_name from products order by prod_name;  
+----------------+
| prod_name      |
+----------------+
| .5 ton anvil   |
| 1 ton anvil    |
| 2 ton anvil    |
| Bird seed      |
| Carrots        |
| Detonator      |
| Fuses          |
| JetPack 1000   |
| JetPack 2000   |
| Oil can        |
| Safe           |
| Sling          |
| TNT (1 stick)  |
| TNT (5 sticks) |
+----------------+
14 rows in set (0.03 sec)
  • 通常, ORDER BY子句中使用的列将是为显示所选择的列。但是,实际上并不一定要这样,用非检索的列排序数据是完全合法的。

六,按多个列排序

只要指定列名,列名之间用逗号分开即可。

mysql> select prod_id, prod_price,prod_name from products order by prod_price, prod_name; #先按价格,再按产品名排序
+---------+------------+----------------+
| prod_id | prod_price | prod_name      |
+---------+------------+----------------+
| FC      | 2.50       | Carrots        |
| TNT1    | 2.50       | TNT (1 stick)  |
| FU1     | 3.42       | Fuses          |
| SLING   | 4.49       | Sling          |
| ANV01   | 5.99       | .5 ton anvil   |
| OL1     | 8.99       | Oil can        |
| ANV02   | 9.99       | 1 ton anvil    |
| FB      | 10.00      | Bird seed      |
| TNT2    | 10.00      | TNT (5 sticks) |
| DTNTR   | 13.00      | Detonator      |
| ANV03   | 14.99      | 2 ton anvil    |
| JP1000  | 35.00      | JetPack 1000   |
| SAFE    | 50.00      | Safe           |
| JP2000  | 55.00      | JetPack 2000   |
+---------+------------+----------------+
14 rows in set (0.03 sec)

七,指定排序方向

1,降序排列desc:

mysql> select prod_id, prod_price,prod_name from products order by prod_price desc, prod_name; #先按价格降序排列,再按产品名升序排列 
+---------+------------+----------------+
| prod_id | prod_price | prod_name      |
+---------+------------+----------------+
| JP2000  | 55.00      | JetPack 2000   |
| SAFE    | 50.00      | Safe           |
| JP1000  | 35.00      | JetPack 1000   |
| ANV03   | 14.99      | 2 ton anvil    |
| DTNTR   | 13.00      | Detonator      |
| FB      | 10.00      | Bird seed      |
| TNT2    | 10.00      | TNT (5 sticks) |
| ANV02   | 9.99       | 1 ton anvil    |
| OL1     | 8.99       | Oil can        |
| ANV01   | 5.99       | .5 ton anvil   |
| SLING   | 4.49       | Sling          |
| FU1     | 3.42       | Fuses          |
| FC      | 2.50       | Carrots        |
| TNT1    | 2.50       | TNT (1 stick)  |
+---------+------------+----------------+
14 rows in set (0.03 sec)
  • 若包含desc,则使用的降序,未用的默认为升序ASC

指定具体列的升降序

mysql> select prod_id, prod_price,prod_name from products order by prod_price desc, prod_name desc; #先按价格降序排列,再按产品名降序排列
+---------+------------+----------------+
| prod_id | prod_price | prod_name      |
+---------+------------+----------------+
| JP2000  | 55.00      | JetPack 2000   |
| SAFE    | 50.00      | Safe           |
| JP1000  | 35.00      | JetPack 1000   |
| ANV03   | 14.99      | 2 ton anvil    |
| DTNTR   | 13.00      | Detonator      |
| TNT2    | 10.00      | TNT (5 sticks) |
| FB      | 10.00      | Bird seed      |
| ANV02   | 9.99       | 1 ton anvil    |
| OL1     | 8.99       | Oil can        |
| ANV01   | 5.99       | .5 ton anvil   |
| SLING   | 4.49       | Sling          |
| FU1     | 3.42       | Fuses          |
| TNT1    | 2.50       | TNT (1 stick)  |
| FC      | 2.50       | Carrots        |
+---------+------------+----------------+
14 rows in set (0.03 sec)
  • 在字典( dictionary)排序顺序中,A被视为与a相同,这是MySQL(和大多数数据库管理系统)的默认行为。但是,许多数据库管理员能够在需要时改变这种行为(如果你的数据库包含大量外语字符,可能必须这样做)。

八,简单应用

使用ORDER BY和LIMIT的组合,能够找出一个列中最高或最低的值。

mysql> select prod_price from products order by prod_price desc limit 1; # 最高值 
+------------+
| prod_price |
+------------+
| 55.00      |
+------------+
1 row in set (0.13 sec)


mysql> select prod_price from products order by prod_price asc limit 1; # 最低值 
+------------+
| prod_price |
+------------+
| 2.50       |
+------------+
1 row in set (0.03 sec)
  • 先排序,在限制取值。

猜你喜欢

转载自blog.csdn.net/dangfulin/article/details/108265415