结构化查询语言/处理数据
如上一页所示,我们现在有一个名为 person 的空表。我们能用这样的表格做什么?就像使用一个袋子一样!将东西存放在里面,查看里面的东西是否存在,修改里面的东西,或者将东西从里面拿出来。这些是与表格中的数据相关的四个基本操作。
- INSERT:将一些数据放入表中
- SELECT:从表中检索数据
- UPDATE:修改表中存在的数据
- DELETE:从表中删除数据。
对于这四个操作中的每一个,都有一个 SQL 命令。它以一个关键字开头,并以一个分号结束。此规则适用于所有 SQL 命令:它们以一个关键字开头,并以一个分号结束。在中间,可能还有更多关键字,以及对象名称和值。
当将新数据存储在表的行中时,我们必须命名所有受影响的对象和值:表名(数据库中可能有很多表)、列名和值。所有这些都嵌入在一些关键字中,以便 SQL 编译器可以识别标记及其含义。通常,简单 INSERT 的语法如下:
INSERT INTO <tablename> (<list_of_columnnames>)
VALUES (<list_of_values>);
以下是一个示例
-- put one row
INSERT INTO person (id, firstname, lastname, date_of_birth, place_of_birth, ssn, weight)
VALUES (1, 'Larry', 'Goldstein', date'1970-11-20', 'Dallas', '078-05-1120', 95);
-- confirm the INSERT command
COMMIT;
当 DBMS 识别 INSERT INTO 和 VALUES 关键字时,它就知道该做什么:它在表中创建一行,并将给定的值放入命名的列中。在上面的示例中,命令后跟第二个命令:COMMIT 确认 INSERT 操作以及其他写入操作 UPDATE 和 DELETE。(我们将在后面的章节中详细了解 COMMIT 及其对应命令 ROLLBACK。)
- 关于 date_of_birth 值格式的简短说明:世界各地没有通用的日期格式。人们根据自己的文化习惯使用不同的格式。为了我们的目的,我们决定使用 ISO 8601 中定义的分层格式来表示日期。可能您的本地数据库安装使用不同的格式,因此您被迫修改我们的示例或修改数据库安装的默认日期格式。
现在我们将更多行放入我们的表格中。为此,我们使用上述语法的变体。如果值列表与原始 CREATE TABLE 语句中使用的列数、顺序和数据类型完全匹配,则可以省略列名列表。
- 提示:不建议在实际应用程序中省略列名列表!表结构会随着时间的推移而发生变化,例如有人可能会向表中添加新列。在这种情况下,应用程序可能会出现意外的副作用。
-- put four rows
INSERT INTO person VALUES (2, 'Tom', 'Burton', date'1980-01-22', 'Birmingham', '078-05-1121', 75);
INSERT INTO person VALUES (3, 'Lisa', 'Hamilton', date'1975-12-30', 'Mumbai', '078-05-1122', 56);
INSERT INTO person VALUES (4, 'Debora', 'Patterson', date'2011-06-01', 'Shanghai', '078-05-1123', 11);
INSERT INTO person VALUES (5, 'James', 'de Winter', date'1975-12-23', 'San Francisco', '078-05-1124', 75);
COMMIT;
现在我们的表格应该包含五行。我们能确定吗?如何检查所有操作是否都正常进行,并且行和值确实存在?为此,我们需要一个命令来显示表格的实际内容。它是 SELECT 命令,其通用语法如下
SELECT <list_of_columnnames>
FROM <tablename>
WHERE <search_condition>
ORDER BY <order_by_clause>;
与 INSERT 命令一样,您可以省略某些部分。最简单的示例是
SELECT *
FROM person;
星号 '*' 表示“所有列”。在结果中,DBMS 应该提供所有五行,每行包含之前使用 INSERT 命令的七个值。
在以下示例中,我们将逐一添加通用语法中当前缺失的子句。
添加一些或所有列名的列表
SELECT firstname, lastname
FROM person;
DBMS 应该提供所有五行的 firstname 和 lastname 两列。
添加搜索条件
SELECT id, firstname, lastname
FROM person
WHERE id > 2;
DBMS 应该提供三行的 id、firstname 和 lastname 三列。
添加排序说明
SELECT id, firstname, lastname, date_of_birth
FROM person
WHERE id > 2
ORDER BY date_of_birth;
DBMS 应该按 date_of_birth 升序提供三行的 id、firstname、lastname 和 date_of_birth 四列。
如果我们想更改某些行中某些列的值,可以使用 UPDATE 命令。简单 UPDATE 的通用语法如下
UPDATE <tablename>
SET <columnname> = <value>,
<columnname> = <value>,
...
WHERE <search_condition>;
值为命名的列赋值。未提及的列保持不变。search_condition 的作用与 SELECT 命令相同。它将命令的覆盖范围限制为满足条件的行。如果省略 WHERE 关键字和 search_condition,则会影响表的所有行。可以指定不匹配任何行的 search_condition。在这种情况下,不会更新任何行,并且不会出现任何错误或异常。
更改一行的一列
UPDATE person
SET firstname = 'James Walker'
WHERE id = 5;
COMMIT;
Mr. de Winter 的名字更改为 James Walker,而他的所有其他值保持不变。此外,所有其他行保持不变。请使用 SELECT 命令验证这一点。
更改多行的一列
UPDATE person
SET firstname = 'Unknown'
WHERE date_of_birth < date'2000-01-01';
COMMIT;
<search_condition> 不限于主键列。我们可以指定任何其他列。比较运算符也不限于等于号。我们可以使用不同的运算符,它们只需要与列的数据类型匹配。
在此示例中,我们使用单个命令更改了四行的 firstname。如果一个表有数百万行,我们可以使用一个命令更改所有行。
更改一行两列
-- Please note the additional comma
UPDATE person
SET firstname = 'Jimmy Walker',
lastname = 'de la Crux'
WHERE id = 5;
COMMIT;
两个值使用一个命令更改。
DELETE 命令从表中删除完整行。由于行是整体删除的,因此无需指定任何列名。<search_condition> 的语义与 SELECT 和 UPDATE 相同。
DELETE
FROM <tablename>
WHERE <search_condition>;
删除一行
DELETE
FROM person
WHERE id = 5;
COMMIT;
James de Winter 的行从表中删除。
删除多行
DELETE
FROM person;
COMMIT;
由于我们省略了 <search_condition>,因此所有剩余的行都被删除。该表为空,但仍然存在。
没有受影响的行
DELETE
FROM person
WHERE id = 99;
COMMIT;
此命令将不会删除任何行,因为没有 id 等于 99 的行。但是,语法和 DBMS 中的执行仍然是完美的。不会抛出异常。命令在没有任何错误消息或错误代码的情况下终止。
INSERT 和 DELETE 命令会影响整个行。INSERT 将一个完整的新行放入表中(未提及的列保持为空),DELETE 删除整个行。相反,SELECT 和 UPDATE 只影响命令中提到的列;未提及的列不受影响。
INSERT 命令(在此页面的简单版本中)没有 <search_condition>,因此仅处理一行。其他三个命令可能会影响零行、一行或多行,具体取决于其 <search_condition> 的评估结果。