每次开工的前三十秒都是同一套动作: 连上去、选库、看表。 Demo 在样例库上把这三步走了一遍——库里有六张表, 行数分别是 6/13/5/5/11/4;看表结构拿到五个字段的类型和约束。 顺带撞出一个真差异:SQLite 的 TEXT 主键允许 NULL,MySQL 的主键一律非空。
前两章是背景,这一章开始动手。 教材 3.1~3.3 三节加起来只有四页,但它给的三个命令(连接、USE、 SHOW)是后面 27 章每次都要用的。 这一章还顺手把全书的舞台搭好——vendors、products、customers、orders、orderitems、 productnotes 六张表,后面每条 SQL 都在这上面转。
一、连接:一行命令,四个参数
教材给的连接命令是:mysql -h 主机名 -u 用户名 -p。
四个参数记住就行:
-h(host)主机、-u(user)用户、-p(password)密码、还有可选的 -P(大写,端口)。
-p 后面不跟密码,回车后它会单独问你要——这是故意的:密码写在命令行里会留在 shell 历史记录中,
别人翻一下就有了。
连不上时按三站排查,顺序别乱:先 ping 主机(网络通不通),再试 3306 端口(服务在不在听),
最后看账号密码(权限对不对)。谁先失败,问题就在哪一站。
退出用 exit 或 quit,后面要加分号也行。
命令行里还有一个 \q,效果一样——这是 mysql 客户端自己的命令,不是 SQL。
这里有个容易搞混的点:SQL 语句要分号结尾,而客户端命令(exit、quit、\s、\u)不需要。
分号是给 SQL 的,不是给客户端的。
二、选择数据库:库是表的上一级
连上去之后还没有选中任何库。
这时候敲 SELECT 会报 No database selected——这个报错新手一天能撞三次。
选库用 USE 库名;。选了之后,你写的表名都默认在这个库里找。
想换就再 USE 一次,没有「退出当前库」这种命令,直接换就行。
层级关系是三层:服务器 → 数据库 → 表 → 行。 一台服务器上可以有几十个库,一个库里有几十张表。
权限也是按层给的:可以只让你看某一个库(第 28 章)。
SQLite 没有这个层级:一个文件就是一个库,打开文件就等于选中了它。
所以本课的 Demo 里你找不到 USE,只有 connect。
这不是 SQLite 偷懒,是它的设计前提就是「单文件、单用户」。
三、了解数据库和表:三条命令摸清地形
到了一个新库,先摸地形。
MySQL 里三条命令:SHOW DATABASES;(有哪些库)、SHOW TABLES;(这个库有哪些表)、
DESCRIBE 表名;(这张表什么结构)。
DESCRIBE 的输出有五列:Field(字段名)、Type(类型)、Null(能不能空)、
Key(是不是主键/索引)、Default(默认值)、Extra(自增之类的附加信息)。
这五列就是一张表的身份证。
DESCRIBE 可以简写成 DESC,也可以写成 SHOW COLUMNS FROM 表名;,三个写法等价。
另外 SHOW CREATE TABLE 表名; 会把建表语句原样打出来——
这个更有用,因为它连字符集、引擎、索引一起给你。
SQLite 里这三件事要绕一下:SHOW TABLES 换成查系统表 sqlite_master,
DESCRIBE 换成 PRAGMA table_info(表名)。信息一样,问法不同。
摸地形这件事值得养成习惯。 拿到一个陌生库,先看有哪些表、每张表几个字段、
哪几个是主键——这三眼下去,数据模型就八九不离十了。
四、动手 Demo:连上样例库,摸一遍地形
样例库就是教材附录 B 的六张表,表结构和字段名照抄,数据按同样的量级自造。 Demo 做四件事:列出所有表、看清 products 的结构、数出每张表的行数、试一次完全限定的表名。 行数那一段是全课的坐标——后面讲一条 SQL 有没有筛对,靠的就是这些数。
import sqlite3
con = sqlite3.connect(":memory:")
# 库里有哪些表(MySQL 里是 SHOW TABLES;)
rows = con.execute("SELECT name FROM sqlite_master WHERE type='table'").fetchall()
print([r[0] for r in rows])
# 这张表长什么样(MySQL 里是 DESCRIBE 表名;)
for r in con.execute("PRAGMA table_info(products)"):
print(r)
实跑输出:
--------------------------------------------------------------------
第三课:连上去,看看库里有什么
--------------------------------------------------------------------
连库之后第一件事:这个库里有哪些表
SQL> SELECT name, type FROM sqlite_master WHERE type = 'table' ORDER BY name
name type
-----------------------
customers table
orderitems table
orders table
productnotes table
products table
vendors table
(6 行)
MySQL 里这一句是 **SHOW TABLES;**,SQLite 没有这个命令,
改查系统表 sqlite_master——**同样的信息,两种问法。**
第二件事:这张表长什么样(字段、类型、能不能空、是不是主键)
字段名 类型 能否为空 默认值 主键
------------------------------------------------------------
prod_id TEXT 是 无 是
vend_id INTEGER 否 无
prod_name TEXT 否 无
prod_price REAL 否 无
prod_desc TEXT 是 无
MySQL 里这一句是 **DESCRIBE products;** 或 **SHOW COLUMNS FROM products;**。
注意 prod_id 那一格:「能否为空」写的是「是」。
**这是 SQLite 的历史包袱——它的主键允许 NULL(只拦重复值,不拦空)。**
MySQL 的主键一律「非空且唯一」,所以这一格在 MySQL 里会是「否」。
第三件事:每张表有几行
表 行数
------------------------------
vendors 6
products 13
customers 5
orders 5
orderitems 11
productnotes 4
**这六张表就是全书的舞台**:供货商、产品、顾客、订单、订单明细、产品备注。
后面 27 章的每一条 SQL,都是在这六张表上转。
换个说法看同一份数据:完全限定的表名
SQL> SELECT products.prod_name FROM products LIMIT 3
prod_name
-------------
.5 ton anvil
1 ton anvil
2 ton anvil
(3 行)
**表名.字段名** 的写法,在只查一张表时是多余的;
但一牵扯到多张表(第 15 章联结),它就是必需品——不然两个表都有 prod_name 时,
数据库不知道你说的是谁的。
第一张表是「这个库里有什么」。 六张表一次列清:供货商、产品、顾客、订单、订单明细、产品备注。
MySQL 里这一句是 SHOW TABLES,SQLite 查 sqlite_master——同一个问题,两种问法。
第二张表是「这张表长什么样」。 五个字段:prod_id 文本主键、vend_id 整数、prod_name 文本、
prod_price 实数、prod_desc 文本。
prod_desc 那两格都写着「是」——它既允许空、也不是主键,所以插数据时可以不给它值。
prod_id 那一格值得停一下:「能否为空」写的是「是」。 这是 SQLite 的历史包袱——
它的主键只拦重复值、不拦空值。
MySQL 的主键一律「非空且唯一」,这一格会是「否」。 这种差异书上一个字都没提,
因为它写的是 MySQL。
第三张表是全课的坐标。 6 个供货商、13 个产品、5 个顾客、5 张订单、11 条订单明细、
4 条产品备注。后面凡是问「筛出来的行数对不对」,都拿这张表当基准。
最后一段讲完全限定的表名。 只查一张表时 products.prod_name 是啰嗦,但第 15 章一联结,
两张表都有 prod_name 这种字段时,不写表名数据库就不知道你说的是谁——那时候它不是啰嗦,是必须。
30 秒实验
- 把六张表的字段名都 DESCRIBE 一遍,找出哪些字段允许空、哪些是主键。
- 故意在没选库的时候敲一句 SELECT——本课怎么复现这个报错? (提示:SQLite 里没有「没选库」这个状态,想想为什么。)
- 用 SHOW CREATE TABLE(MySQL)或查 sqlite_master 的 sql 列,把 products 的建表语句原样打出来, 和你自己写的那句比一比。
常见误区
- 连上去就敲 SELECT。没选库会报 No database selected。先 USE,再查表——这是固定的前两步。
- 把 -p 和密码贴在一起写。
-p密码能用,但密码会进 shell 历史、进 ps 输出。 只写 -p,让它问。 - 以为 DESCRIBE 能看索引。它只给字段和主键,索引要看
SHOW INDEX FROM 表名;。 两件事,两条命令。
自测三问(点开对答案)
1. 连接命令里 -h、-u、-p 各是什么?为什么 -p 后面常常不写密码? —— 主机、用户、密码。 不写密码是为了不让它进 shell 历史记录和进程列表,回车后单独提示输入更安全。 2. 为什么连上之后直接 SELECT 会报 No database selected? —— 因为服务器上有很多库,你还没说清在哪一个库里找表。USE 库名 之后才有默认库。 SQLite 一个文件一个库,就不存在这个状态。 3. 到一个陌生库,最先该敲哪三句? —— SHOW DATABASES(或看有哪些库)、SHOW TABLES(有哪些表)、DESCRIBE 表名(表结构)。 SQLite 对应 sqlite_master 与 PRAGMA table_info。地形摸清了,下一章开始真正的检索:SELECT 怎么挑列——单列、多列、所有列、不重复的值、 只取前几行,还有完全限定的表名什么时候必须写。
- ☐ (本章完,下一章 第4章 检索数据)