0

Here is what I am trying to understand. I have the following database table

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');

Note the absence of any indexes, unique keys... . Before someone tells me "that is not a good idea" I have strung together this example for a good reason.

Now suppose I use Adminer (you could just as easily read phpMyAdmin etc) to edit Row 2

(10,13,b)

Now after the edit if the SQL that were issued were

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

MySQL would update two rows and the table would read

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

which is not the desired result and not what Adminer does. It appears to know what row to update and does just that. It is not clear to me how this is done. With many other statements - e.g. CREATE TABLE it is possible to deliberately use invalid assignments (.e.g attempt to assign a length to a TEXT field and then study the SQL on error. However, that option does not exist on row edits since Adminer actively stops you from doing invalid edits (e.g. typing in a char in an integer column).

About the only way I can think of is to tag on a LIMIT 1 at the end of the statement - which would work, kind of. However, in a table with a larger number of fields it would involve putting in a very lengthy WHERE clause when only one or two fields in that row have changed in order to help MySQL identify the right row to alter.

Perhaps there are other techniques to accomplish this that are not quite so crude that I am not aware of? I'd be most grateful to anyone who might be able to help.

To finish this post - please don't tell me that rows should be unique and I should be using indices. I am well aware of that. This is simply the worst case scenario that I am trying to resolve.


I should mention that although this question talks of MySQL I am in fact using MariaDB 10.

4

1 回答 1

0

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

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

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

于 2015-06-05T10:18:39.847 回答