Вот что я пытаюсь понять. У меня есть следующая таблица базы данных
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
можно намеренно использовать недопустимые назначения (например, попытаться назначить длину TEXT
поле, а затем изучить SQL на ошибки. Однако, эта опция не существует при редактировании строк, так как Adminer активно запрещает вам делать недопустимые изменения (например, вводить символ в столбце целых чисел).
О единственном способе, которым я могу думать, является пометка на LIMIT 1
в конце заявления — что будет работать, вроде. Тем не менее, в таблице с большим числом полей это будет включать в себя очень длинное предложение WHERE, когда только одно или два поля в этой строке изменились, чтобы помочь MySQL идентифицировать право строка для изменения.
Возможно, есть другие методы для достижения этой цели, которые не настолько грубы, о которых я не знаю? Я был бы очень благодарен любому, кто мог бы помочь.
Чтобы закончить этот пост — пожалуйста, не говорите мне, что строки должен быть уникальным, и я должен использовать индексы. Я хорошо это знаю. Это просто худший сценарий, который я пытаюсь решить.
Я должен упомянуть, что хотя этот вопрос говорит о MySQL, на самом деле я использую MariaDB 10.
Вы попросили обновить строку, но нет уникального идентификатора, который можно было бы использовать, поэтому программное обеспечение получало столько же постоянных данных, сколько и для обновления базы данных. Эти данные, значения Field0
а также Field1
не был уникальным, и поэтому он изменил все подходящие строки. Если (Field0
, Field1
) был уникальным ключом, или существовал (уникальный) первичный ключ, он мог изменить только одну строку.
Если (Field0
, Field1
) не был уникальным, и вы добавили LIMIT 1
, он все еще мог иметь возможность изменить один Другой строка, которая соответствует.
Без уникального способа ссылаться на каждую отдельную строку (и это было бы с первичным ключом без NULL), вы фактически нарушаете 12 правил Кодда, особенно правило № 2. Поскольку «идеальная» реляционная база данных в основном теоретическая и непрактичная для повседневного использования, БД могут счастливо существовать без строгого соответствия, но без уникального ключа в этом случае вы просто усложняете себе жизнь.
Других решений пока нет …