首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用于删除行的数据库中的主键还是常规字段?

用于删除行的数据库中的主键还是常规字段?
EN

Stack Overflow用户
提问于 2013-07-14 05:21:30
回答 4查看 11.8K关注 0票数 3

我想要擦除数据库中的一行,我有两个选择;第一,使用普通列来删除行;第二,使用主键?

我知道主键更好,但为什么呢?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-07-14 05:30:21

主键更好,因为您可以确定要删除的行:虽然从技术上讲,您可以更新主键列,但这样做并不是正常的做法。但是,其他列是可变的,这可能会导致如下情况:

您有一个表,该表具有一个PK和另一个唯一标识符,例如,email

  • You使用email

  • 读取一行,然后决定删除它,并在电子邮件更新为DELETE USER WHERE email='sample_email@gmail.com'

DELETE USER WHERE email='sample_email@gmail.com'的同时对行进行修改

DELETE命令不会删除任何内容,因为在您设法运行命令之前,电子邮件已经更改。因为PK不应该改变,所以这种情况在正常情况下是不可能的。当然,您的代码可以检测到没有发生删除,重做读取,然后重新发出命令,但与使用主键相比,这是大量的工作。

票数 2
EN

Stack Overflow用户

发布于 2013-07-14 06:52:35

在MySql上,当使用非主键列删除/更新行时,您可能会在多用户环境中遇到奇怪的锁定行为。

下面是一个示例--两个会话试图删除行(自动提交被禁用)。

代码语言:javascript
复制
C:\mysql\bin>mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.5.29-log MySQL Community Server (GPL)

Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.

mysql> create table test(
    ->   id int primary key,
    ->   val int
    -> );
Query OK, 0 rows affected (0.02 sec)

......

mysql> select * from test;
+----+------+
| id | val  |
+----+------+
|  1 |    1 |
|  2 |    2 |
|  3 |    3 |
|  4 |    4 |
|  5 |    5 |
|  6 |    6 |
+----+------+
6 rows in set (0.00 sec)

现在在会话1中,我们将使用主键删除第5行

代码语言:javascript
复制
mysql> delete from test where id = 5;
Query OK, 1 row affected (0.00 sec)

然后在会话2中,我们也使用PK删除第2行

代码语言:javascript
复制
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)

mysql> delete from test where id = 2;
Query OK, 1 row affected (0.00 sec)

一切正常-会话1删除了第5行,会话2删除了第2行

现在看看当我们尝试删除使用非主键的行时会发生什么:

会话1

代码语言:javascript
复制
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)

mysql> delete from test where val = 5;
Query OK, 1 row affected (0.00 sec)

和会话2

代码语言:javascript
复制
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)

mysql> delete from test where val = 2;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql>

会话2中的Delete命令“挂起”,大约一分钟后,它抛出一个错误: Lock wait timeout

让我们尝试删除其他行:

代码语言:javascript
复制
mysql> delete from test where val = 4;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> delete from test where val = 6;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql>

会话1只删除第5行,并且从逻辑上讲,锁应该只放在要删除的记录#5上,但正如您在这些示例中看到的那样,当不使用主键时,MySql在整个表的所有行上放置了锁。因此,只使用主键删除行更安全(至少在MySql上是这样)。

票数 5
EN

Stack Overflow用户

发布于 2013-07-14 05:28:27

我假设你的意思是这样的陈述:

代码语言:javascript
复制
delete from table
    where column = value

当列是主键时,它会自动有一个惟一的索引(至少在我所知道的数据库中是这样)。这样可以更快地找到要删除的记录。

具有索引的另一列将几乎同样快,因为它可以使用索引查找。

没有索引的列将会慢得多,因为查询必须执行全表扫描。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17634335

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档