2010-11-05 1 views
46

Я беру курс под названием «системы баз данных», и для нашего проекта класса мне нужно создать веб-сайт.Зачем использовать первичный ключ с автоматическим приращением, когда существуют другие уникальные поля?

Вот пример таблицы, я создал:

CREATE TABLE users 
(
    uid INT NOT NULL AUTO_INCREMENT, 
    username VARCHAR(60), 
    passhash VARCHAR(255), 
    email VARCHAR(60), 
    rdate DATE, 
    PRIMARY KEY(uid) 
); 

Профессор сказал мне «UID» (идентификатор пользователя) был совершенно бесполезным и ненужным, и я должен был использовать имя пользователя в качестве первичного ключа, так как нет два пользователя могут иметь одинаковое имя пользователя.

Я сказал ему, что мне удобно использовать идентификатор пользователя, потому что, когда я вызываю что-то вроде domain.com/viewuser?id=5, я просто проверяю параметр с помощью: is_numeric($_GET['id']) ... само собой разумеется, что он не был убежден.

Поскольку я видел user_id и другие аналогичные атрибуты (thread_id, comment_id, среди других) на множестве учебных пособий и рассматривает схему базы данных популярного программного обеспечения (например, vbulletin), должно быть много других (более сильных) причин ,

Итак, мой вопрос: как бы вы оправдали необходимость непустого автоматического инкрементного id в качестве первичного ключа или другого атрибута, такого как имя пользователя?

+1

Joe Celko всегда исторгал то же самое: «Вы должны использовать значащие ПК, когда это возможно». – Brettski

+1

Ваш профессор слишком много читает книгу комиксов, чем читает PHP/MySQL? – klox

+0

Ваш профессор звучит как пурист. Реально, да - если имена пользователей будут уникальными, идентификаторы пользователей являются повторяющимися данными сортировки, так как имя пользователя и идентификатор пользователя имеют одинаковое значение. Но в реальном мире они полезны для большинства, если не всех причин, упомянутых ниже. – cHao

ответ

79

автоинкрементные первичные ключи полезны по нескольким причинам:

  • Они позволяют дублирующиеся имена пользователей, как на переполнение стека
  • Они позволяют имя пользователя (или адрес электронной почты, если это используется для входа в систему), чтобы быть изменен (легко)
  • Выбирается, соединения и вставки быстрее, чем VARCHAR первичных ключей, как его гораздо быстрее, чтобы поддерживать числовой индекс
  • Как уже упоминалось, проверка становится очень просто: if ((int)$id > 0) { ... }
  • санитария ввода тривиальна: $id = (int)$_GET['id']
  • Существует гораздо меньше накладных расходов, как внешние ключи не должны дублировать потенциально большие строковые значения

Я бы сказал, пытаясь использовать любой информации строки, как уникальный Идентификатор для записи - плохая идея, когда автоматически увеличивающий числовой ключ так легко доступен.

Системы с уникальными именами пользователей прекрасно подходят для очень небольшого числа пользователей, но Интернет оказал им принципиально нарушенную работу. Когда вы рассматриваете огромное количество людей с именем «john», которые могут взаимодействовать с веб-сайтом, смешно требовать от каждого из них использования уникального отображаемого имени. Это приводит к ужасной системе, которую мы так часто видим со случайными цифрами и буквами, украшающими имя пользователя.

Однако даже в системе, где вы применяете уникальные имена пользователей, это все еще плохой выбор для первичного ключа. Представьте себе пользователя с 500 сообщениями: внешний ключ в таблице posts будет содержать имя пользователя, дублируемое 500 раз. Накладные расходы являются запретительными даже до того, как вы считаете, что кому-то может понадобиться изменить свое имя пользователя.

+24

Скажите «профессор», чтобы прочитать этот ответ;) – subosito

+8

Другой момент - ОРМ ненавидят нецелые ключи. Хотя я чувствую, что это общий провал со стороны большинства ORM, вы научитесь работать * с помощью * инструментов – Phil

+1

@meagar Я ненавижу посещать сайты, которые требуют, чтобы я придумал уникальное имя пользователя для входа в систему. полностью отказаться от «имени пользователя» для аутентификации и перейти только на адрес электронной почты. – Phil

15

Если имя пользователя является первичным ключом, а пользователь меняет свое имя пользователя, вам необходимо обновить все таблицы, содержащие ссылки на внешние ключи для таблицы users.

+8

Если пользователь может изменить свое имя пользователя, то имя пользователя по определению не является первичным ключом кандидата. –

+6

Референтное действие 'ON UPDATE CASCADE' является обычным ответом на этот аргумент« соломенный человек ». – onedaywhen

+4

@Bob Jarvis: свойство хорошего ключа, что значения стабильны. Неизменяется идеальный, но редкие изменения тоже хороши. – onedaywhen

4

Поскольку кто-то может захотеть изменить свое имя пользователя (или любое другое имя в этом отношении).

0

Например, целочисленный поиск (? Id = 5) намного быстрее и имеет более высокую мощность, чем строковый поиск (? Username = bob). Другой пример: uid is auto_increment, поэтому вам не нужно вставлять его явно, но он будет автоматически увеличиваться в каждом запросе на вставку.

PS: Ваш проф тааак неправильно об этом: D

+1

Если они уникальны, то карнальность строки или номера будет одинаковой. Если в каждом случае используется хэш-индекс, то производительность поиска будет примерно одинаковой в каждом случае. Таким образом, на приведенной информации нет оснований говорить, что один быстрее, чем другой. В любом случае, точка вопроса - это правильность, а не производительность. Профессор прав! – sqlvogel

+0

@dportas, так вы о профессоре? Профессор настолько ошибается, что я уволяю его, если он попытается сделать что-то такое глупое в моих базах данных. – HLGEM

+1

@HLGEM: Я не он, но я мог бы уволить кого-то, кто был настолько глуп, чтобы позволить дублировать пользователей в пользовательской таблице - или, по крайней мере, я бы перевоспитал их, заставив их определить естественные ключи перед суррогатами. Я ожидаю, что профессор почувствует то же самое. – sqlvogel

1

мне нужно кого-то с большим знанием базы данных, чтобы поддержать меня на этом, но я верю, что вы получите быстрый ответ на внешний ключ времени поиска.

Кроме того, вы можете позже решить, хотите ли вы, чтобы имена пользователей изменились или что требования к именам пользователей могут измениться (возможно, более длинная строка?). Использование идентификатора запрещает изменять все внешние ключи.

Lets face it, большинство проектов не собираются расширять , что много, но вы действительно хотите рискнуть головной болью 12 месяцев в будущем, когда вы сможете соответствовать хорошим стандартам программирования сейчас?

+1

VARCHAR (4) занимает столько же байтов, сколько INT; меньше, чем это меньше, чем INT, но это не делает его выполнимым в зависимости от правил. –

+0

Конечно, это varchar (60), поэтому почти наверняка будет медленнее. – HLGEM

0

Мы используем идентификатор для предотвращения дублирования данных, и это может сделать некоторые проакции не сложными (если мы хотим обновить или удалить данные), это проще, если мы используем ID.

Если вы не хотите использовать ID, вы можете использовать другие поля. но не забудьте сделать их УНИКАЛЬНЫМИ. он может сделать ваши данные превентивными из данных дублирования.

другой способ за пределами ОСНОВАНИЯ UNIQUE.

0

Я иду со всеми ответами выше. Я бы сказал, что идентификатор легко реализовать, и когда дело доходит до индексации, Int всегда предпочтительнее по сравнению с varchar. Ваш профессор должен знать лучше, почему он сказал бы, что нет, чтобы Int id был выше меня!

7

Обычно это называется surrogate key, и у него много преимуществ. Один из них изолирует ваши отношения с базой данных из данных приложения. Более подробную информацию и соответствующие недостатки можно найти по ссылке wiki, приведенной выше.

0

Поскольку идентификатор пользователя должен быть уникальным (не может быть дублирован) & иногда является индексом.

4

Ваш профессор поступает правильно, указав, что вы должны были сделать имя пользователя уникальным и не иметь значения NULL, если это требование, чтобы имена пользователей были уникальными. Uid также может быть ключом, но если вы на самом деле его не используете, то он не нужен. Более важным аспектом дизайна должно быть внедрение естественного ключа. Поэтому я согласен с комментарием вашего профессора.

+3

Я согласен с ним в том, что он должен иметь уникальное ограничение, но почти всегда ошибочно использовать somethign настолько изменчивым, как имя пользователя, как PK. Известно, что целые числа быстрее объединяются, чем varchars этого размера, и обновляют потенциально миллионы записей FK, когда изменения имени пользователя могут привести к критической остановке вашей системы. Кто-то преподавательский дизайн должен знать лучше, чем хотеть естественный ключ для чего-то такого изменчивого. – HLGEM

+0

@HLGM: Я был в сетях и таких почти три десятилетия. Я не могу вспомнить свое имя пользователя, когда-либо меняющееся. –

+0

@HLGEM, который говорит, что имена пользователей меняются? – alternative

10

Если вы продемонстрировали своему профессору, что присвоение уникального произвольного целого каждому пользователю имеет значение для вашего приложения, то, конечно, он ошибается, заявив, что он «абсолютно бесполезен и ненужен».

Однако, возможно, вы пропустили его точку. Если он сказал вам, что требование состоит в том, что «ни один из двух пользователей не может иметь одинаковое имя пользователя», то вы не выполнили это требование.

Искреннее спасибо за отправку вашего SQL DDL, это очень полезно, но большинство из них не беспокоятся о SO.

Используя таблицу, я могу это сделать:

INSERT INTO users (username) VALUES (NULL); 
INSERT INTO users (username) VALUES (NULL); 
INSERT INTO users (username) VALUES (NULL); 
INSERT INTO users (username) VALUES (NULL); 
INSERT INTO users (username) VALUES (NULL); 

Каких результаты в этом:

SELECT uid, username, passhash, email, rdate 
FROM users; 

uid username passhash email rdate 
1  <NULL>  <NULL>  <NULL> <NULL> 
2  <NULL>  <NULL>  <NULL> <NULL> 
3  <NULL>  <NULL>  <NULL> <NULL> 
4  <NULL>  <NULL>  <NULL> <NULL> 

Я думаю, это точка ваш профессор пытается сделать: без соблюдения естественного ключа на username у вас действительно нет целостности данных.

Если бы я был профессором, я бы также настоятельно рекомендовал удалить столбцы с нулевым значением из вашего дизайна.

+0

Спасибо, я забыл об ограничении NOT NULL и UNIQUE.Вот обновленная версия: пользователи CREATE TABLE (uid INT NOT NULL AUTO_INCREMENT, имя пользователя VARCHAR (30) NOT NULL, passhash VARCHAR (255) NOT NULL, email VARCHAR (60) NOT NULL, rdate DATE NOT NULL, PRIMARY KEY (uid), UNIQUE (имя пользователя, адрес электронной почты); – cnandreu

+0

'UNIQUE (имя пользователя, адрес электронной почты)' не делает то, что вы думаете. Вы можете попробовать проверить свой собственный код. –

+0

@Catcall: этот последний комментарий был для @CarlosMarx, правильно? – onedaywhen

0

И вы хотите сохранить свои имена пользователей в ясном тексте для любого, кто украл? Я бы никогда не подумал об использовании естественного ключа, который, возможно, захочу зашифровать когда-нибудь (или вы хотите зашифровать сейчас).

+0

Если безопасность была проблемой, вы бы не хэш-имя пользователя, а не шифрование? Хэш должен сделать хороший хороший ключ. Если вы не согласны с тем, какой естественный ключ вы использовали бы для уникальной идентификации пользователей? Я думаю, мы согласны с тем, что оригинальный дизайн неправильный, но какие предложения у вас есть для OP? – sqlvogel