1
0
mirror of https://github.com/apachecn/lmpythw-zh.git synced 2025-05-28 12:02:19 +00:00
lmpythw-zh/ex42.md
wizardforcel 27d6aa5ef4 ex42
2017-08-15 11:55:09 +08:00

82 lines
3.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 练习 42SQL 删除
> 原文:[Exercise 42: Deleting with SQL](https://learncodethehardway.org/more-python-book/ex42.html)
> 译者:[飞龙](https://github.com/wizardforcel)
> 协议:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/)
> 自豪地采用[谷歌翻译](https://translate.google.cn/)
这是最简单的练习,但我希望你键入代码之前思考一秒钟。如果你将`SELECT`写成`"SELECT * FROM"`,将`INSERT`写成`"INSERT INTO"`,那么你会怎么编写`DELETE`格式?你可以看下面,但是试着猜测它会是什么,然后看一看。
```sql
/* make sure there's dead pets */
SELECT name, age FROM pet WHERE dead = 1;
/* aww poor robot */
DELETE FROM pet WHERE dead = 1;
/* make sure the robot is gone */
SELECT * FROM pet;
/* let's resurrect the robot */
INSERT INTO pet VALUES (1, "Gigantor", "Robot", 1, 0);
/* the robot LIVES! */
SELECT * FROM pet;
```
我只是简单地通过删除它,然后使用`dead=0`将记录放回去,来为机器人实现非常复杂的更新。在以后的练习中,我将向你展示,如何使用`UPDATE`来实现它,所以不要以为这是更新的真正方法。
你已经熟悉了这个脚本中的大多数行,除了第五行。这里你拥有`DELETE`,它与其他命令格式几乎相同。你提供了`DELETE FROM table WHERE tests`,以及一种方式,将其看做移除行的`SELECT`。任何在`WHERE`子句中有效的内容在这里都有效。
## 使用其它表来删除
记得我说过:“`DELETE`就像`SELECT`,但它从表中删除行。” 限制是一次只能从一个表中删除。这意味着为了删除所有宠物,你需要执行一些额外的查询,然后基于它们删除。
一种方法是使用一个子查询,根据你已经编写的查询来选择要所需的 ID。还有其他的方法可以实现它但是现在你可以根据你所知道的方法来实现它
```sql
DELETE FROM pet WHERE id IN (
SELECT pet.id
FROM pet, person_pet, person
WHERE
person.id = person_pet.person_id AND
pet.id = person_pet.pet_id AND
person.first_name = "Zed"
);
SELECT * FROM pet;
SELECT * FROM person_pet;
DELETE FROM person_pet
WHERE pet_id NOT IN (
SELECT id FROM pet
);
SELECT * FROM person_pet;
```
第 1~8 行是正常起步的`DELETE`命令,但是`WHERE`子句使用`IN`,匹配`pet`中的`id`列与子查询中返回的表。子查询(也称为子选择)是正常的`SELECT`,在尝试寻找人们拥有的宠物时,它应该看起来和以前你做的那个相似。
第 13~16 行中,然后我使用子查询,将任何不存在的宠物从`person_pet`表中给删除,使用`NOT IN`而不是`IN`
SQL 处理它的方式是以下过程:
+ 运行末尾处括号中的子查询,并创建一个表,带有所有列,就像普通`SELECT`一样。
+ 将此表视为一种临时表,来匹配`pet.id`列。
+ 浏览`pet`表,并删除拥有此临时表中(`IN`)的 ID 的任何行。
## 挑战练习
+ 将所有`ex2.sql``ex7.sql`合并到一个文件中,并重执行上述脚本,以便你只需运行一个新文件即可重新创建数据库。
+ 添加一些东西到脚本中,来删除其他宠物,然后再次使用新值插入它们。记住,这不是你通常更新记录的方式,只是为了练习。
+ 练习编写`SELECT`命令,然后将它们放在`DELETE WHERE IN`中,来删除找到的记录。尝试删除你拥有的任何死亡宠物。
+ 反着操作,删除有死亡宠物的人。
+ 你真的需要删除死的宠物吗?为什么不在`person_pet`中移除他们的关系,并标记它们死了?写一个查询,从`person_pet`中去除死亡宠物。
## 深入学习
出于完整性,你需要阅读[`DELETE`文档](https://sqlite.org/lang_delete.html)。