🦏 第1章 数据库简介
📄 一句话概括

连接、建库、建表、跑代码——四步,每一歩都能落成一句 SQL。 看不懂那四句,界面就只是个黑盒。 Demo 按这四步真走了一遍:连接拿到库文件、建表、插两行、查一句 price > 100 命中 2 行; 关掉连接再打开,文件 8192 字节,数据还在。

📝 本章和前面几章的关系

上一篇讲工具是什么,这一篇讲怎么用——用的顺序就是教材的四小节: 连接、创建数据库、创建表、运行代码。 这四步是后面所有章节的操作底座:以后每敲一句 SQL,走的都是这条路。

一、第一步:连接,填四个格子

主机、端口、用户名、密码——四个格子。 本机就填 localhost 或 127.0.0.1,端口 3306,用户 root。 localhost 和 127.0.0.1 在 MySQL 里不是一回事:前者可能走命名管道/socket,后者一定走 TCP。 权限表里 'root'@'localhost' 与 'root'@'127.0.0.1' 是两个账号, 这就是「命令行能进、工具进不去」的经典原因。 「连接名」随便起,只是给你自己看的标签,不影响连到哪台机器。

二、第二步:建库,字符集一次定对

建库的完整写法: CREATE DATABASE shop DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; 字符集必须选 utf8mb4:老版 utf8 只有三字节,存不下 emoji 和部分生僻字, 8.0 已经把它改成 utf8mb4 了,但自己写语句时别写错。 排序规则(collation)决定「怎么比大小」:0900_ai_ci 里 ai 是重音不敏感、 ci 是大小写不敏感。要严格区分大小写就选 _bin。 SQLite 这一步是退化的:一个文件就是一个库,没有「建库」这句, CREATE DATABASE 直接报语法错。Demo 里把它换成了建表。

三、第三步:建表,字段名和类型要想清楚

建表时要定的六件事:字段名、类型、长度、能不能空、默认值、主键。 图形工具那六个格子就是这六件事。 类型别乱选:手机号用 VARCHAR(11) 不用整数(前导 0 会丢、还要算长度)、 钱用 DECIMAL(8,2) 不用 FLOAT(浮点存不准)、 时间用 DATETIME 或 TIMESTAMP(后者带时区)。 字段名别用关键字:order、desc、key、group 都是保留字,非要用就得加反引号: `order`。这一条踩一次记一辈子。

四、第四步:跑代码,一次发一批

查询编辑器里敲完,按运行:选中一句就只发那一句,没选就发全部。 结果在下面开页签,同时告诉你「影响了几行」。 「影响行数」这个数要养成看的习惯:UPDATE 少写了 WHERE, 它会告诉你影响了 1 行还是 10 万行——这一眼能救命。 Demo 里那 2 行不是猜的:price > 100 把 128 和 156 两行捞出来,结果集就是两行。

五、小结

教材小结:用 Navicat 连接 MySQL、创建数据库与表、在查询窗口里运行 SQL,是本书所有操作的起点。 本课补三条:一是 localhost 与 127.0.0.1 在权限表里是两个账号; 二是字符集一次定对 utf8mb4,建完再改要动数据; 三是跑完看「影响行数」,它是误操作的唯一警报。

六、动手 Demo:四步走一遍,关掉再打开

Demo 六段:按「连接→建库→建表→跑代码」走一遍,然后关掉连接重新打开,看数据还在不在。 这一步是本课唯一一次「真写文件」,其余章节都在内存库里跑,因为持久化这件事只看一次就够。

import sqlite3, os
p = os.path.join(os.environ["TEMP"], "demo4604.db")
if os.path.exists(p):
    os.remove(p)

c = sqlite3.connect(p)                      # 1 连接
c.execute("CREATE TABLE IF NOT EXISTS goods "
          "(id INTEGER PRIMARY KEY, name TEXT, price REAL)")   # 2 建库
c.execute("INSERT INTO goods (name, price) VALUES "
          "('篮球', 128.00), ('足球', 156.00)")                 # 3 建表
c.execute("SELECT name, price FROM goods WHERE price > 100")   # 4 跑代码
c.commit()
c.close()

# 关掉再打开,数据还在
c2 = sqlite3.connect(p)
c2.execute("SELECT COUNT(*) FROM goods")
print(os.path.getsize(p))                   # 8192

实跑输出:

--------------------------------------------------------------------
第四课:连接、建库、建表、跑代码,四步走一遍
--------------------------------------------------------------------

  第一步:连接——本质是「拿到一个库文件(或一个服务端地址)」
  sqlite3.connect(r'<Temp>\demo4604.db')
  **MySQL 的写法是**
  `mysql -h 127.0.0.1 -P 3306 -u root -p`**,或者图形工具里填「主机/端口/账号/密码」那四个格子。**

  第二步:建库——SQLite 里「建库」就是「新建一个文件」
  SQL> CREATE TABLE IF NOT EXISTS goods (id INTEGER PRIMARY KEY, name TEXT, price REAL)
  完成
  **MySQL 的写法是** `CREATE DATABASE shop DEFAULT CHARSET utf8mb4;`**,然后用**
  `USE shop;` **切进去。**
  **SQLite 没有「库」这一层,一个文件就是一个库,所以这一步退化成「建表」。**

  第三步:建表——字段、类型、约束
  SQL> INSERT INTO goods (name, price) VALUES ('篮球', 128.00), ('足球', 156.00)
  影响 2 行
  SQL> SELECT * FROM goods
  id     name     price
  -----------------------
  1      篮球     128.00
  2      足球     156.00
  (2 行)

  第四步:跑代码——编辑器里敲完,执行,看结果
  SQL> SELECT name, price FROM goods WHERE price > 100
  name     price
  ----------------
  篮球     128.00
  足球     156.00
  (2 行)
  **命中的是 2 行。图形工具里这一步就是按一下运行键,底下多出一个结果页签。**

  把文件关掉,再打开,数据还在
  文件大小 8192 字节,重新打开后还有 2 行
  **这就是「持久化」:数据在磁盘上,不在内存里。MySQL 也一样,只不过它把文件藏在自己管的目录里,不让你直接看。**

第一段连接。 sqlite3.connect(路径) 就等于拿到一个库,MySQL 那边是四个格子。 第二段建库。 SQLite 没有库这一层, 所以直接建表——这一步在 MySQL 里是 CREATE DATABASE 加 USE。 第三段插两行。 篮球 128、足球 156。 第四段跑查询。 price > 100 命中两行,图形工具里这一步就是按运行键。 第五段关掉再打开。 文件 8192 字节, 重新连上还有 2 行——这就是持久化:数据在磁盘上,不在内存里。 第六段讲差异。 MySQL 把文件藏在自己管的目录里,你看不到,但一样是落盘的。

30 秒实验

  1. 把 price > 100 改成 price >= 128,命中几行?为什么和原来一样?
  2. (先想再跑)建表时不给 id 写 PRIMARY KEY,插两行相同的 id 会怎样?
  3. CREATE DATABASE 在 SQLite 里为什么报错?它对应这里的哪一步?

常见误区

  1. 字符集建库时选成 utf8。 三字节存不下 emoji,等发现时数据已经进去了,改起来要导表。
  2. 字段名用了关键字还不加反引号。 order、desc、key 全是保留字,报错信息很难看懂。
  3. 跑完不看影响行数。 UPDATE 忘了 WHERE,影响 10 万行,界面也一样只弹一句「成功」。
自测三问(点开对答案) 1. 连接 MySQL 要填哪四个信息? —— 主机、端口、用户名、密码;本机一般是 localhost/127.0.0.1、3306、root。 2. 为什么字符集要选 utf8mb4? —— 老版 utf8 最多三字节,放不下四字节的 emoji 与部分生僻字;utf8mb4 才是完整 UTF-8。 3. 「影响行数」有什么用? —— 它是误操作的第一道警报:UPDATE/DELETE 少写 WHERE 时,行数会从个位数变成全表。

四步都走通了, 但本书的例子怎么敲、注释怎么写、分号要不要加? 下一章把这些书写约定一次说清。

相关笔记