数据库长什么样

刚开始学 SQL 的话,可以从这里读起。用例子看看表怎样存放数据,以及怎样读懂查询结果。

先打开它

点击第一个例子下方的按钮。浏览器会在新标签页中打开 Planche,并载入商城数据库。数据库文件只在页面中处理,你的修改不会影响其他机器。需要恢复初始状态时,可在欢迎页重新载入示例。

表就是一张网格

跑一下这条。它要的是名为 categories 的表里的全部内容。

1

SELECT * FROM categories;
在 Planche 中运行

结果 — 共 33 行,这里是前 5 行

idnamedescriptionparent_idsort_orderis_active
1ElectronicsElectronics and related productsNULL01
2LaptopsLaptops in Electronics111
3PhonesPhones in Electronics121
4TabletsTablets in Electronics131
5AudioAudio in Electronics141

浏览器会另开一个标签页打开 Planche,示例数据库已经载入,这条查询也已经放好。本页其他示例都会复用同一个标签页;在你按下 F9 之前,什么都不会执行。

返回的网格就是一张表。先认识三个术语:

  • 列是顶部的一个标题——id、name、description。表里每一条记录都有这同样的六个,而这些名字就是你在查询里要敲的。
  • 行是网格里横着的一条,它代表一个东西。这里一行就是一个分类。一共 33 行,说明这家商城有 33 个分类。
  • 单元格是行与列相交的地方——一个值,比如某个分类的名字。

这个数据库里的每张表都是同一个形状。products 一行一个商品,orders 一行一个订单,customers 一行一个客户。变的只是各自有哪些列。

有些格子是空的,这有个名字

2

SELECT id, name, parent_id
FROM categories
LIMIT 8;
在 Planche 中运行

结果 — 共 8 行,这里是前 5 行

idnameparent_id
1ElectronicsNULL
2Laptops1
3Phones1
4Tablets1
5Audio1

看 parent_id。有些行是个数字,有些标着 NULL。这个列表示当前分类挂在哪个分类下面——笔记本挂在电子产品下面——而顶层分类不挂在任何分类下面,所以没有东西可填。

NULL 的意思是"这里没有值"。值得把它当成一个独立的概念来学,而不是当成某种零,因为它确实不是:

  • NULL 不是 0。零是你量出来的一个数;NULL 是你根本没有的那次测量。
  • NULL 也不是空字符串。名字被记成空白的客户,和名字从来没被记录过的客户,是两回事。

NULL 的比较规则与普通值不同,第三课会详细说明。现在只需记住:它表示未知或缺失的值,而不只是空格子。

每一行都有自己的编号

这里的第一列是 id,它是一个只属于某一行、而且永不重用的数字。这就是该行的主键——别的东西靠它来指向这一行,而不必依赖随时可能被人改掉的名字。

你遇到的表几乎都有一个主键,通常就叫 id。

为什么是 23 张表而不是一张

理论上一个商城可以只用一张巨大的网格:一行一个订单,客户姓名、地址、每个商品和价格全都重复写在那一行上。数据库不这么设计,理由很直白——一个客户搬了家,你就得去改他历史上每一笔订单,而任何一行漏改,都会变成一份和其他行互相矛盾的"事实"。

所以每一类东西各占一张表,行与行之间靠主键互指。products.category_id 存的是 categories.id,orders.customer_id 存的是 customers.id。指向另一张表某一行的列叫外键,顺着它走就是第四课要讲的连接。

这也是为什么你需要一个地方查"某张表有哪些列"。示例数据库那一页列出了每张表、每个列,以及哪个列指向哪张表。把它开在另一个标签页里——每天写 SQL 的人也是把表结构摆在手边写的。

查询是一个问题,答案也是一张表

3

SELECT COUNT(*) AS how_many FROM products;
在 Planche 中运行

结果 — 1 行

how_many
400

一行、一列、一个数字。它仍然是一张表,只是非常小——而这正是 SQL 的整套想法:你发出一个问题,回来的东西永远是同一种长方形形状,无论是 400 行还是 1 行。

还要注意,这个答案在数据库里哪儿都找不到。没有任何地方存着 400 这个数字;是你问的时候数据库数出来的。大多数有用的查询都是这样——它们算出答案,而不是把答案找出来。

自己跑一条

在工作区上方的编辑器里写或改一条查询,按 F9 运行;想只跑光标所在的那条语句,就按 Ctrl / ⌘ + Enter。结果出现在下面的网格里,行数显示在底部。

左边那一栏是同一个数据库的树形视图:展开 main,再展开 Tables,双击任意一张表就能看到它的行,一个字都不用写。在查询之前想知道表里有什么,这通常是最快的办法。

本页每个例子都在自己的标签页里打开,所以你可以改一条、跑一次、再改回去,而不会弄丢正在做的事。

出错的时候

一定会出错,而错误信息都很短、很直白。列名写错会得到:

no such column: naem

先读信息的结尾——那里通常写着数据库到底没找到什么。新手的错误绝大多数是三种:列名拼错、列其实在另一张表里、以及文本外面少了引号(SQL 要的是 'paid',单引号;双引号是另一个意思)。

出错就意味着什么都没执行。语句是整条被拒绝的,所以一条失败的查询不会改变任何东西。

接下来

你已经知道表、行、列和 NULL 是什么,会跑查询,也看得懂结果。下一课讲的是几乎每条查询都由之搭成的那四个子句。

自己动手写

  1. 这家商城有多少客户?这条查询的形状你在本页最后一个例子里见过。

    查看答案

    查看答案

    SELECT COUNT(*) AS how_many FROM customers;
    在 Planche 中运行

    结果 — 1 行

    how_many
    1500

    COUNT(*) 数的是行,AS how_many 只是给结果列起个好读的名字。把 customers 换成别的表名,数的就是那张表。