这是我想要了解的内容。我有以下数据库表
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。
答案 0 :(得分:0)
您已要求更新一行,但没有可以使用的唯一标识符,因此,软件会获取与更新数据库时一样多的常量数据。该数据,export DISPLAY=:99
和Field0
的值不是唯一的,因此它更改了所有匹配的行。如果(Field1
,Field0
)是唯一键,或者有(唯一)主键,则它只能更改一行。
如果(Field1
,Field0
)不是唯一的,并且您添加了Field1
,它仍然可以选择更改其他匹配的行。
如果没有一种独特的方式来引用每个单独的行(并且使用没有NULL的主键),则实际上会破坏Codd's 12 rules,尤其是规则#2。由于“完美”的关系型数据库在日常使用中大多是理论上的和不切实际的,因此DB可以在没有严格遵守的情况下幸福地存在,但在这种情况下没有唯一的密钥,您只是为自己的生活而努力。