MariaDB/MySQL, PostgreSQL 和 SQLite3 - 命令行界面比较

不要害怕使用您选择的数据库的命令行客户端。

我最好先说明这一点:我不喜欢将 GUI(又名非命令行或图形)工具与我的数据库一起使用。这可能是因为我最初学习数据库时使用的是命令行工具,但即便如此,我认为命令行数据库工具通常是手动与数据库交互的最佳方式。

在 Linux 上使用的最流行的两个数据库是 MySQL 和 PostgreSQL。它们都具有非常有用但略有不同的命令行客户端。如果您需要在这两个数据库之间迁移,或者如果您是数据库新手,那么对两者进行比较会很有帮助。

但是,由于两匹马的比赛不如三匹马的比赛那么激动人心,我想在我的比较中包含第三个数据库命令行客户端。我选择了 SQLite,因为它可以说是世界上最流行的数据库。您可能现在本地计算机上就有多个 SQLite 数据库。它的命令行客户端也很不错。

此外,我在示例中使用 MariaDB 而不是 MySQL,因为这就是我安装的,并且因为我喜欢 MariaDB 在命令行客户端和数据库服务器中所包含的改进。MariaDB 和 MySQL 非常兼容,而且我的示例很简单,因此每当我提到 MariaDB 时,您都可以认为它也适用于 MySQL。

服务...或不服务

PostgreSQL 和 MariaDB 具有所谓的客户端/服务器架构。客户端连接到服务器,尽管客户端和服务器通常一起安装,您可能会将它们视为一个单一实体,但实际上它们不是。客户端不需要与服务器在同一台机器上运行。MariaDB 服务器称为 mysqld,它始终在服务器启动时运行。同样,PostgreSQL 服务器称为 postgres。

SQLite 没有客户端/服务器架构。只有您正在使用的数据库(它是一个本地文件)和可以与之交互的客户端程序。

安装

我不会在这里介绍如何安装 MariaDB、MySQL、PostgreSQL 或 SQLite3。大多数发行版都有它们的软件包,对于 MariaDB,Debian、Ubuntu、Red Hat 和通用 Linux 二进制文件都可以从其下载页面获得。有关说明,请参阅每个发行版的文档和您的发行版文档。

在 Ubuntu 上,您可以使用以下命令安装所有三个


sudo apt-get install mariadb-server postgresql sqlite3

在大多数情况下,其他 Linux 发行版也同样容易。(您需要添加相应的 MariaDB Ubuntu 存储库才能使上述操作生效。说明位于 MariaDB 下载页面上。)

图 1. MariaDB、PostgreSQL 和 SQLite3 客户端的运行情况

基本客户端命令

MariaDB、PostgreSQL 和 SQLite3 的客户端程序分别是 mysql、psql 和 sqlite3。我在表 1 中列出了每个客户端的几个有用的命令。第一个条目显示了用于连接到数据库的基本命令;但是,每个客户端都有多个选项。这些选项包括(在 MariaDB 和 PostgreSQL 的情况下)用于指定用户、密码和数据库主机服务器的选项。您经常需要这些选项,因此请参阅客户端的 man 手册以了解它们是什么以及如何使用它们。表 1 中列出的一些命令具有扩展选项;有关详细信息,请参阅文档。

表 1. MariaDB/MySQL、PostgreSQL 和 SQLite 客户端速查表
任务 MariaDB/MySQL PostgreSQL SQLite
连接到数据库 mysql <dbname> psql <dbname> sqlite3 <filename>
客户端帮助 help contents \? .help
SQL 帮助 help contents \h 不适用
列出数据库 SHOW DATABASES; \l .databases
更改数据库 USE <dbname> \c <dbname> 不适用
列出表 SHOW TABLES; \dt .tables
显示表信息 DESCRIBE <tablename>; \d <tablename> .schema <tablename>
加载数据 LOAD DATA INFILE '<file>' \i <file> .import <file> <table>
导出数据 SELECT ... INTO OUTFILE '<file>' \o <file> .dump <table>
退出客户端 quit (或 exit) \q .exit

首次连接到新安装的 MariaDB 或 PostgreSQL 数据库时,您需要以数据库超级用户身份连接,因为您可能尚未设置任何其他用户。

要启动新安装的 MariaDB mysql 客户端,请执行以下操作


mysql -u root -p

系统将提示您输入在软件包安装过程中输入的密码。

要启动新安装的 PostgreSQL psql 客户端,请执行以下操作


sudo su - postgres
psql

创建和删除数据库

仅安装数据库客户端和/或服务器不会自动为您提供要使用的数据库。对于 MariaDB 和 PostgreSQL,可以使用客户端或外部实用程序创建数据库。

在 MariaDB 和 PostgreSQL 中,要创建一个名为 library 的数据库,命令是


CREATE DATABASE library;

要在 MariaDB 中连接到这个新创建的数据库,请执行


USE library

在 PostgreSQL 中,执行


\c library

要删除新创建的 library 数据库,请使用以下命令删除它


DROP DATABASE library;

我不应该说这个,但使用上述命令时要小心。如果您刚刚删除了 library 数据库,请重新创建它。您稍后需要它来继续阅读本文中的示例。

在 SQLite3 中,没有数据库服务器,数据库只是常规文件,通常带有 .db 扩展名。要创建数据库,请在启动客户端时在命令行中命名它,如果它不存在,客户端将创建它,如下所示


sqlite3 library.db

要删除 SQLite3 数据库,只需像删除任何其他文件一样删除它(使用 rm 或通过文件管理器)。

管理用户和权限

这里没有空间详细介绍如何创建和管理数据库用户的权限。有关详细信息,请参阅 MariaDB 和 PostgreSQL 文档。在本文的示例中,我将继续使用默认的超级用户帐户。

SQLite3 没有内部数据库用户或用户权限管理。如果本地用户具有对数据库文件的写入权限,他们可以执行他们想要的任何操作。

常用 SQL 操作

本文是关于 MariaDB、PostgreSQL 和 SQLite 的命令行客户端,但使用此类客户端时,您主要做的事情之一是编写 SQL 语句。因此,让我们看一下这三者之间一些基本的 SQL 相关相似之处和差异。

最常见的 SQL 语句是 selects、inserts、updates 和 deletes。作为一种计算机语言,SQL 是比较流行的一种,并且有一个官方标准 ANSI SQL,它经历了多年的各种修订。大多数关系数据库管理系统 (RDBMS) 使用 SQL 作为其查询语言,但它们在多大程度上遵守 ANSI SQL 方面有所不同。在我这里探讨的这三个数据库中,PostgreSQL 最接近标准。MariaDB 在某些地方偏离标准,使其更易于使用。SQLite3 并没有声称支持 ANSI SQL 的所有功能。相反,它只支持一个子集。毕竟,它应该是“Lite”。

有些人希望看到 SQL 消亡,永远不再被使用。我不是这些人之一。SQL 有问题,但大多数计算机语言也是如此。我发现 SQL 易于阅读、灵活,并且值得花时间学习它。下面的示例很简单,我忽略了 SQL 的许多复杂性。我也不会解释每个语句的每个部分。我的目标是让您了解 SQL 在实践中的样子,并指出这三个数据库之间的一些相似之处和差异。这些数据库中的每一个的在线文档(以及 MariaDB 和 PostgreSQL 的客户端内帮助)都包含有关 SQL 语法的广泛信息。我发现 SQLite 语法图对于该数据库特别有帮助。

SQL 语句可以写在一行上,也可以分成多行以使其更易于阅读。在下面的示例中,我采用了后一种方法。SQL 语句通常以分号 (;) 结尾。

CREATE TABLE 语句

如果没有一些表,您在数据库冒险中走不了多远。如果您不熟悉数据库,请将数据库表视为电子表格工作表,只是没有所有字体和边框样式。

回到我们的 library 示例,library 中最常见的东西是书籍,所以让我们创建一个 books 表


CREATE TABLE books (
  bookid serial PRIMARY KEY,
  title varchar(100) NOT NULL,
  seriesid integer,
  authorid integer
);

上述代码适用于 MariaDB 和 PostgreSQL,但不适用于 SQLite3,因为使用了 SERIAL 数据类型,该数据类型通常用作 PRIMARY KEY 的数据类型。请参阅“SERIAL 数据类型”侧边栏以获取更多信息。

SERIAL 数据类型

数据类型是您告诉数据库列中数据类型的方式。常见的数据类型包括 integer、text、varchar 和 date。SERIAL 数据类型是一种特殊的数据类型。在 MariaDB 中,SERIAL 数据类型是以下内容的别名Garrick,下一行。


BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE

这很拗口,但它确实完成了创建适合用作 PRIMARY KEY 的列的工作。BIGINT 是一个大整数;UNSIGNED 表示没有负值;NOT NULL 表示它不能为空;AUTO_INCREMENT 表示如果在插入行时未指定特定值,则该值应为“当前最大值 + 1”;UNIQUE 表示该表中不允许其他行在该列中具有相同的值。

在 PostgreSQL 中,SERIAL 数据类型是以下内容的别名


INTEGER NOT NULL DEFAULT nextval('tablename_colname_seq')

奇怪的 nextval('tablename_colname_seq') 位引用的是“ALTER SEQUENCE”,具体来说是


ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;

这只是 PostgreSQL 创建自增列的方式。值得庆幸的是,当您创建类型为 SERIAL 的列时,PostgreSQL 会为您创建 ALTER SEQUENCE。此列也适合用作 PRIMARY KEY。

许多数据库表的常见功能是 PRIMARY KEY。此键唯一地引用表中的一行。PRIMARY KEY 可以是行中两个或多个列的组合(只要该组合保证在该数据库表中是唯一的),但最常见的是,有一个特定的自增列用作 PRIMARY KEY。

当您创建 SQLite3 表时,SQLite3 表中的每一行都会自动创建一个 PRIMARY KEY 列(SQLite 称其为 RowID)。但是,它是隐藏的,除非您指定类型为 integer PRIMARY KEY 的列。因此,对于 SQLite,请将上面 CREATE TABLE 语句中的 bookid 行更改为以下内容


bookid integer PRIMARY KEY,

并且,SQLite3 将创建一个具有与 MariaDB 和 PostgreSQL 等效设置的表。

INSERT 语句

现在您有了一个表,是时候输入(或 INSERT)一些信息了。在三个数据库之间插入数据非常相似,但有一个重要的区别。MariaDB 和 PostgreSQL 都允许您在一个语句中插入多行信息。另一方面,SQLite3 每次只允许您插入一行。

例如,要将一些数据插入到您之前创建的 books 表中,请对 MariaDB 和 PostgreSQL 使用以下 SQL 语句


INSERT INTO books (title, seriesid, authorid) VALUES
  ('The Fellowship of the Ring', 1, 1),
  ('The Two Towers', 1, 1),
  ('The Return of the King', 1, 1),
  ('The Sum of All Men', 2, 2),
  ('Brotherhood of the Wolf', 2, 2),
  ('Wizardborn', 2, 2),
  ('The Hobbbit', NULL, 1);

您可能已经注意到最后一行中的拼写错误。我故意这样做是为了让您稍后可以修复它。

对于 SQLite3,您要插入的每一行都需要单独完成,如下所示


INSERT INTO books (title, seriesid, authorid) VALUES
  ('The Fellowship of the Ring', 1, 1);
INSERT INTO books (title, seriesid, authorid) VALUES
  ('The Two Towers', 1, 1);

...等等。

在上面的 SQL 语句中,我没有在列名部分指定 bookid。我这样做是因为该列设置为 PRIMARY KEY,并且它由数据库自动填充正确的值。

SELECT 语句

SELECT 是最常见的数据库操作。我没有首先谈论它的唯一原因是,在 CREATE 表并在其中 INSERT 数据之前(如您在前面的部分中所做的那样),没有任何东西可以 SELECT。

在这三个数据库中,SELECT 语句的工作方式几乎相同。基本的 SELECT 语句(例如以下语句)在这三个数据库上都适用


SELECT * FROM books;
SELECT title, authorid FROM books WHERE authorid = 1;
SELECT * FROM books ORDER BY authorid;

Joins 在这三个数据库中也运行良好。Joins 是将来自两个或多个表的信息组合在一起的地方。例如,这是一个 join,它根据 authorid 编号将作者姓名与其书籍匹配


SELECT title AS "Book Title", givenname, surname
  FROM books INNER JOIN authors USING (authorid)
ORDER BY surname;

上面的 SELECT 语句预先假定创建了 authors 表,并向其中插入了至少几行数据,如下所示

在 MariaDB 和 PostgreSQL 上


CREATE TABLE authors (
  authorid serial PRIMARY KEY,
  surname varchar(100),
  givenname varchar(100),
  birthdate date
);

在 SQLite3 上,将 authorid 行更改为以下内容,CREATE TABLE 语句将正常工作


  authorid integer PRIMARY KEY,

以下是表的一些数据,格式化为在这三个数据库上工作


INSERT INTO authors (surname, givenname) VALUES
  ('Tolkien', 'J.R.R.');
INSERT INTO authors (surname, givenname) VALUES
  ('Farland', 'David');

现在,您可以运行 SELECT ... JOIN 语句。

UPDATE 语句

还记得那个拼写错误吗?现在是时候修复它了。此 UPDATE 行适用于所有三个数据库


UPDATE books SET title = 'The Hobbit' WHERE title = 'The Hobbbit';

DELETE 语句

删除行在这三个数据库中也相同


DELETE FROM books WHERE bookid = 7;

上面将删除 books 表中 bookid 为 8 的行。如果您一直在关注,则不应有 bookid 为 8 的条目,因此不会发生任何事情。

ALTER 语句

假设我决定从 books 表中删除 seriesid 列。在 MariaDB 和 PostgreSQL 中,以下语句将执行此操作


ALTER TABLE books DROP seriesid;

另一方面,SQLite3 不支持从表中删除列。您可以向表中添加列或修改列,但删除列的唯一方法是创建一个没有 seriesid 列的新表,将数据从旧表传输到新表,删除旧表,然后将新表重命名为原始名称。这并不像您想象的那么烦人,这要归功于一些 SQL INSERT 技巧(好吧,当我第一次看到它运行时,我认为它很巧妙)。基本思想是将 SELECT 语句的输出用作 INSERT 语句的输入,如下所示


CREATE TABLE books2 (
  bookid integer PRIMARY KEY NOT NULL,
  title varchar(100) NOT NULL,
  authorid integer
);
INSERT INTO books2 (bookid, title, authorid)
  SELECT bookid, title, authorid FROM books;
DROP TABLE books;
ALTER TABLE books2 RENAME TO books;

只要您将 CREATE TABLE 语句的 bookid 行更改为以下内容,上面的技巧在 MariaDB 和 PostgreSQL 中也可以按编写的方式工作


bookid serial PRIMARY KEY,

但是,如果您只想从表中删除一列,那将是非常繁琐的工作。

这些示例应该足以让您了解这三者之间的比较情况。

SQLite 输出

在尝试 SQL 示例时,您会注意到 SQLite 输出远不如 MariaDB/MySQL 或 PostgreSQL 的输出漂亮。默认情况下,SQLite 不打印列名或尝试填充列,使其像其他数据库一样排列整齐漂亮。要使 SQLite 对 SELECT ... JOIN 语句执行此操作,请在语句之前输入以下命令


.explain ON
.mode column
.width 30 10 10

.explain 命令指示 SQLite 显示列标题;.mode 将输出设置为以列显示,.width 命令设置列的宽度。这样做的唯一问题是,它会搞乱未来查询的输出(除非它们碰巧使用您指定的 .width 值看起来不错)。要将所有内容重置为默认值,请使用 .mode list 将输出模式设置回默认值“list”。这样做也会关闭 explain 并将列宽度重置为默认值。

单引号与双引号

在 SQL 示例中,我主要使用单引号 ('),而很少使用双引号 (")。MariaDB 和 SQLite 允许您在查询中互换使用单引号或双引号来表示大多数带引号的文本。PostgreSQL 更挑剔,因为它试图更接近 ANSI SQL 标准,该标准规定单引号应用于值(例如:title = 'The Hobbbit'),双引号应用于系统标识符(字段名称、表名称等 - 例如:SELECT title AS "Book Title"...)。您可以使用命令 SET sql_mode='ANSI_QUOTES' 强制 MariaDB 遵守标准 - 并拒绝双引号值。

结论

在命令行上与数据库交互并不难。在我看来,在命令行上执行上述任务比通过图形数据库程序容易得多。

当然,在许多情况下,应该避免手动操作数据库,无论是在命令行还是使用图形程序,而应使用自动化前端 - 例如,用于包含公司网站内容的数据库的 PHP 内容管理前端。但是,对于那些您确实需要深入研究并手动调整某些内容的时候,或者对于那些不需要自定义前端的时间或费用的小型项目,无需害怕使用您选择的数据库的命令行客户端。

资源

MariaDB 网站:https://mariadb.org.cn

MariaDB 文档:http://kb.askmonty.org

MariaDB 下载:http://downloads.askmonty.org

PostgreSQL 网站:https://postgresql.ac.cn

PostgreSQL 文档:https://postgresql.ac.cn/docs

PostgreSQL 下载:https://postgresql.ac.cn/download

SQLite 网站:http://www.sqlite.org

SQLite 文档:http://www.sqlite.org/docs.html

SQLite 下载:http://www.sqlite.org/download.html

SQLite SQL 语法图:http://www.sqlite.org/syntaxdiagrams.html

关于 SQL 的维基百科文章:http://en.wikipedia.org/wiki/SQL

关于在 MySQL 和 PostgreSQL 之间迁移的 Wikibooks 文章:https://wikibooks.cn/wiki/Converting_MySQL_to_PostgreSQL

加载 Disqus 评论