当前位置: 首页 > 知识库问答 >
问题:

Adminer等人如何知道要更新什么?

严修诚
2023-03-14

这就是我想要理解的。我有下面的数据库表

DROP TABLE IF EXISTS `test`;
CREATE TABLE `test` (
  `Field0` int(11) NOT NULL,
  `Field1` int(11) NOT NULL,
  `Field2` enum('a','b','c') COLLATE latin2_czech_cs NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin2 COLLATE=latin2_czech_cs;

INSERT INTO `test` (`Field0`, `Field1`, `Field2`) VALUES
(10,    11, 'a'),
(10,    13, 'b'),
(10,    13, 'a');

请注意,没有任何索引,唯一的键...。在有人告诉我“这不是个好主意”之前,我把这个例子串起来是有充分理由的。

现在假设我使用Adminer(你可以很容易地阅读phpMyAdmin等)来编辑第2行

(10,13,b)

现在在编辑之后,如果发出的SQL是

UPDATE `test` SET Field2 = 'c' WHERE Field0 = '10' AND Field1 = '13';

MySQL将更新两行,表将为

(10,11,a)
(10,13,c)
(10,13,c)

这不是期望的结果,也不是管理员所做的。它似乎知道要更新什么行,并做到这一点。我不清楚这是如何做到的。对于许多其他语句,例如,CREATE TABLE,可以故意使用无效的赋值(例如,尝试给文本字段赋值一个长度,然后研究错误SQL。但是,行编辑中不存在该选项,因为Adminer会主动阻止您进行无效编辑(例如,在整数列中键入char)。

我能想到的唯一办法是在语句末尾加上一个LIMIT 1,这会起作用的。然而,在一个字段数量较多的表中,当该行中只有一个或两个字段发生了更改时,需要放入一个非常长的WHERE子句,以帮助MySQL确定要更改的正确行。

也许还有其他一些技术可以做到这一点,这些技术并不是我所不知道的那么粗糙?我将非常感谢任何能够帮助我的人。

为了完成这篇文章-请不要告诉我行应该是唯一的,我应该使用索引。我很清楚这一点。这只是我试图解决的最坏情况。

我应该提到,虽然这个问题谈到MySQL,但我实际上使用的是MariaDB 10。

共有1个答案

吴驰
2023-03-14

您已要求更新一行,但没有可使用的唯一标识符,因此,软件获取的常量数据与更新数据库所需的常量数据一样多。在这些数据中,Field0Field1的值不是唯一的,因此它更改了它匹配的所有行。如果(Field0Field1)是唯一的键,或者存在(唯一的)主键,则只能更改一行。

如果(Field0Field1)不是唯一的,并且您添加了一个LIMIT 1,则它仍然可以选择更改另一个匹配的行。

如果没有唯一的方法来引用每一行(这将是一个没有NULL的主键),您实际上违反了Codd的12条规则,特别是规则#2。由于完美的关系数据库大多是理论上的,对日常使用来说是不切实际的,因此数据库可以在没有严格遵从的情况下愉快地存在,但是在这种情况下,如果没有唯一的密钥,您只会让自己的生活变得困难。

 类似资料:
  • 我在laravel 5中工作,我有一个模块,用户可以在其中更新学生的信息,因为用户有一个带有当前数据的预加载表单,并且可以修改他想要的字段。然后,在控制器中,我执行以下操作: 那工作得很好。所以我的问题是:有一种方法可以获得已经更新的字段的名称?

  • 我想知道记录是否更新了熊猫数据框中的日期。数据框由几列组成,其中对于A的每个值,我们有几个B的值,包括开始日期和结束日期。由于时间戳,我们可以知道是否有新的记录或以前的记录已被修改。 我想知道的是如何能够检查如果一个新记录有一个日期范围接近其他记录在其组中例如B1组如果他们有一个类似的日期范围删除前一个只留下新记录已更新,但如果它没有公共范围来解释为新记录。 例如 输入数据帧: 预期输出: 谢谢你

  • 情况: 在我的网站上。com/game,我在 在我的服务器上,的最大值为。 问题: 。 问题是,每当用户访问,它显示空页面,不再执行任何操作。我无法让客户端获取新的。 如何让客户端获取新的?

  • 问题内容: 打电话时我得到一个。这是什么意思?我怎么知道这个意思? 问题答案: 您可以用来获取易于理解的错误号字符串。这是由相同的字符串打印出来的,但是如果您要格式化错误消息而不是标准错误输出,这将很有用。 例如: Linux还支持显式线程安全变体。

  • 我想模拟Gmail关于通知栏通知的应用程序行为,它符合推荐的Android模式:http://developer.Android.com/design/patterns/notifications.html 即特定于单个邮件的通知,点击该通知将显示该特定电子邮件的屏幕。如果我通过刷清或使用“清除所有”清除通知,那么当我得到一个新消息时,我将得到另一个消息特定的通知。但如果我没有清除它,而我又收到另

  • 问题内容: 我们有一个数据库,每天cronjob在午夜更新,我们从外部XML获取新数据。 我们要做的是插入所有新内容,并在键重复的情况下更新该字段。 我们想知道的是实际插入了哪些行,这意味着我们想要一个新项目的列表。是否有可能返回新插入的查询?基本上,我们将需要获取所有新的ID,而不是新插入的数量。 谢谢 问题答案: 添加一列并更改您的查询: 您也可以在触发器中增加它,使您可以保持查询不变。