Adminer等人如何知道要更新的内容?

时间:2015-06-03 20:47:48

标签: php pdo mariadb adminer

这是我想要了解的内容。我有以下数据库表

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)

这不是期望的结果,也不是Adminer所做的。它似乎知道要更新的行和那样做。我不清楚这是如何完成的。还有许多其他陈述 - 例如CREATE TABLE可以故意使用无效分配(.eg尝试为TEXT字段分配长度,然后在出错时研究SQL。但是,自Adminer主动以来,行编辑中不存在该选项阻止您进行无效编辑(例如,在整数列中输入字符)。

关于我能想到的唯一方法是在声明末尾的LIMIT 1上标记 - 这样可行。但是,在具有大量字段的表中,当该行中只有一个或两个字段发生更改时,将涉及放入一个非常冗长的WHERE子句,以帮助MySQL识别 right 行以进行更改

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

要完成这篇文章 - 请不要告诉我应该是唯一的,我应该使用索引。我很清楚这一点。这只是我想要解决的最糟糕的情况。

我应该提一下,虽然这个问题涉及MySQL,但实际上我使用的是MariaDB 10。

1 个答案:

答案 0 :(得分:0)

您已要求更新一行,但没有可以使用的唯一标识符,因此,软件会获取与更新数据库时一样多的常量数据。该数据,export DISPLAY=:99 Field0的值不是唯一的,因此它更改了所有匹配的行。如果(Field1Field0)是唯一键,或者有(唯一)主键,则它只能更改一行。

如果(Field1Field0)不是唯一的,并且您添加了Field1,它仍然可以选择更改其他匹配的行。

如果没有一种独特的方式来引用每个单独的行(并且使用没有NULL的主键),则实际上会破坏Codd's 12 rules,尤其是规则#2。由于“完美”的关系型数据库在日常使用中大多是理论上的和不切实际的,因此DB可以在没有严格遵守的情况下幸福地存在,但在这种情况下没有唯一的密钥,您只是为自己的生活而努力。