Почему присвоение имени столбцу первичного ключа таблицы «Id» считается плохой практикой? [закрыто]


210

Мой учитель t-sql сказал нам, что именование нашей колонки PK "Id" считается плохой практикой без каких-либо дополнительных объяснений.

Почему именование столбца PK таблицы "Id" считается плохой практикой?


27
Ну, на самом деле это не описание, и Id означает «идентичность», что самоочевидно. Это моё мнение.
Жан-Филипп Леклерк

49
Я уверен, что есть много магазинов, которые используют Id в качестве имени ПК. Я лично использую TableId в качестве соглашения о присвоении имен, но я бы никому не сказал, что это ОДИН ИСТИННЫЙ ПУТЬ. Похоже, ваша учительница просто пытается представить свое мнение как широко распространенную лучшую практику.

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

57
У вас есть таблица ... она называется People, у нее есть столбец, который называется Id. Как вы думаете, что это за Id? Автомобиль? Лодка? ... нет, это People Id, вот и все. Я не думаю, что это не плохая практика, и нет необходимости называть колонку PK чем-либо, кроме Id.
Джим

38
Итак, учитель встает перед классом и говорит вам, что это плохая практика без единой причины? Это худшая практика для учителя.
Джефф

Ответы:


247

Я собираюсь выйти и сказать: Это на самом деле не плохая практика (и даже если он есть, его не что плохо).

Вы можете сделать аргумент (как указал Чад ), что он может маскировать ошибки, как в следующем запросе:

SELECT * 
    FROM cars car
    JOIN manufacturer mfg
        ON mfg.Id = car.ManufacturerId
    JOIN models mod
        ON mod.Id = car.ModelId
    JOIN colors col
        ON mfg.Id = car.ColorId

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

SELECT * 
    FROM cars
    JOIN manufacturer
        ON manufacturer.Id = cars.ManufacturerId
    JOIN models
        ON models.Id = cars.ModelId
    JOIN colors
        ON manufacturer.Id = cars.ColorId

Практика ВСЕГДА использовать трехбуквенные сокращения кажется мне намного хуже, чем использование названия столбца id. (Показательный пример: кто на самом деле будет сокращать имя таблицы carsс помощью аббревиатуры car? Какой цели это служит?)

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

Сосредоточьтесь на изучении вещей, которые на самом деле являются плохими методами (такими как множественные вложенные коррелированные подзапросы), а не на размышлениях над такими проблемами. Проблема именования ваших столбцов "ID" ближе к тому, чтобы быть делом вкуса, чем к плохой практике.


ПРИМЕЧАНИЕ ДЛЯ РЕДАКТОРОВ: ошибка в этом запросе является преднамеренной и используется, чтобы сделать точку. Пожалуйста, прочитайте полный ответ перед редактированием.


1
@ Чад, это была ссылка на тот факт, что в этом конкретном запросе вы использовали 3 буквы для псевдонимов к именам таблиц, даже когда это не имело смысла ( cars-> car. Слава Богу - вы спасли мои пальцы). Не читайте слишком глубоко в это.
riwalk

3
хуже, чем мои псевдонимы, было мое смешивание множественности carsи manufacturer. Один во множественном числе, другой нет. Если люди хотят выбирать в БД, это плохая практика, на которую следует обратить внимание.
CaffGeek

3
Я думаю, что это плохая практика. Очевидно, что с точки зрения плохой практики это не страшно ... но так легко избежать, почему бы не сделать это? Теперь, я согласен, для вступительного класса это то, на чем стоит сосредоточиться? Вероятно, нет ....
user606723

2
@ user606723, на самом деле, я думаю, что для вступительного класса это важная вещь. Обучение передовой практике должно быть основополагающим. Только тогда, когда вы почувствуете, что понимаете последствия, компромиссы и когда вам следует отклоняться от лучших практик.
CaffGeek

5
@ Чед, согласен не соглашаться. Попытка научить студентов «лучшим практикам», не позволяя им понять, почему это лучшие практики, - тщетное усилие. И так как вы не можете охватить все, подчеркнув этот пункт словами «вы просто не должны этого делать, вы поймете, почему позже», с точки зрения профессора, это довольно разумный выбор. Любопытные студенты могут написать здесь или, надеюсь, найти ответ на этот вопрос. (Или спросите после урока)
user606723

123

Потому что, когда у вас есть таблица с внешним ключом, вы не можете назвать этот внешний ключ "Id". У вас есть имя таблицы, TableId

И тогда ваше соединение выглядит

SELECT * FROM cars c JOIN manufacturer m ON m.Id = c.ManufacturerId

И в идеале, ваше условие должно иметь одинаковое имя поля с каждой стороны

SELECT * FROM cars c JOIN manufacturer m ON m.ManufacturerId = c.ManufacturerId

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

Это кажется простым, но когда вы объединяете несколько таблиц, с большей вероятностью вы допустите ошибку, найдите таблицу ниже ...

SELECT * 
    FROM cars car 
    JOIN manufacturer mfg
        ON mfg.Id = car.ManufacturerId
    JOIN models mod
        ON mod.Id = car.ModelId
    JOIN colors col
        ON mfg.Id = car.ColorId

В то время как при правильном присвоении имени ошибка выскакивает ...

SELECT * 
    FROM cars car 
    JOIN manufacturer mfg
        ON mfg.ManufacturerId = car.ManufacturerId
    JOIN models mod
        ON mod.ModelId = car.ModelId
    JOIN colors col
        ON mfg.ManufacturerId = car.ColorId

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

SELECT   manufacturer.Id as 'ManufacturerId'
        ,cars.Id as 'CarId'
        --etc
    FROM cars 
    JOIN manufacturer
        ON manufacturer.Id = cars.Id

С точными именами это не проблема


174
Не уверен, что это достаточно хорошее объяснение для меня. Там нет ничего плохого в высказывании SELECT * FROM cars c JOIN manufacturer m ON manufacturer.Id = c.ManufacturerId. Я использовал в idтечение многих лет и никогда не находил то, что вы описали, как настоящую проблему.
riwalk

61
Я бы сказал, что плохой практикой является использование псевдонимов таблиц с такими именами, как mfg или mod. Производители.ид = cars.manufacturer_id очень читабельны, и ошибка тоже будет видна.
Deadalnix

5
@Chad> У меня уже есть проблемы с тупыми именами переменных. Много раз. Для справки, вот что я бы сказал разработчику, который делает это в моей команде: «mfg не означает« производитель », это означает, что вам лень набирать производителя».
Deadalnix

9
@ Stargazer712: выполнение SELECT * из 2 таблиц дает 2 столбца ID ID. Идентификатор теперь неоднозначен: вы ссылаетесь по порядковому номеру или имени? SELECT * также не является хорошей практикой. Бедные аргументы. Хрупкий код. Чад правильно: оборонительное кодирование в основном
ГБНО

6
@gbn, опять же, вся неопределенность исчезнет, ​​если вы просто сделаете это SELECT manufacturer.id FROM .... Любая возникающая в результате трудность idможет быть преодолена очень легко, что делает ее просто делом вкуса.
Rwalk

67

Библиотека Ruby ActiveRecord и Groovy GORM используют «id» для суррогатного ключа по умолчанию. Мне нравится эта практика. Дублирование имени таблицы в каждом имени столбца является излишним, утомительным для записи и более утомительным для чтения.


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

12
ID гораздо
труднее

5
@HLGEM: имя столбца всегда можно сопоставить с именем таблицы.
Кевин Клайн

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

2
+1, Ненавижу видеть таблицы с такими столбцами, как Posts.postID, Posts.postName, где простое использование post.id и post.name намного красивее.
Даг

40

Общие или ключевые имена столбцов, такие как «Имя» или «Id», должны иметь префикс TableName.

Это устраняет неоднозначность, ее легче искать, и это означает, что псевдонимы столбцов будут намного меньше, когда необходимы оба значения «Id».

Меньше используемый или аудит столбца или не ключ (скажем, LastUpdatedDateTime) не имеет значения


57
Если ты сделаешь это, я ненавижу тебя за то, что ты заставляешь меня делать лишний набор текста !!!! Таблица называется Person, как вы думаете, каким будет Id? Автомобиль? нет, это личность
Джим

16
@ Джим, я не знаю, как ты, но ввод 6 дополнительных символов занимает у меня примерно полсекунды. И учитывая, что я редко когда-либо выбираю из одной таблицы, и, таким образом, получаю два столбца с именем «Id», и в любом случае мне нужно будет включить имя таблицы / псевдонима, количество введенных символов не будет сокращено.
CaffGeek

21
@ Может, я нахожу это лишним. если я делаю соединение, c.id = m.manufacturerid, со мной все в порядке. Эти столбцы обычно как-то «сопоставляются» с классом, и наличие класса с Person.PersonId вызывает у меня рвоту ... Да, я полностью осознаю, что у меня есть проблемы.
Джим

20
Я тоже не согласен с этим. Зачем останавливаться на nameи id? Почему у каждого столбца нет префикса с именем таблицы? Кажется произвольным выбрать эти два имени для указания префикса. Концептуально у вас должна быть таблица, чтобы в любом случае иметь контекст столбца. Почему бы просто не использовать это имя таблицы для уточнения запроса: Person.Name, Animal.Name, Part.Name, ...
Томас

11
@ Билл Липер, DRY не всегда подходит для разработки баз данных. В базах данных важно повысить производительность и заставить базу данных выполнять дополнительную работу для выполнения принципов DRY (таких как использование скалярных функций или представлений, которые вызывают представления или запросы, которые возвращают слишком много столбцов, или использование курсора для добавления 1000000 записей для использования существующего процесса) часто противопоказан. Не думайте, что только потому, что в объектно-ориентированном мире есть что-то хорошее, оно подходит для проектирования баз данных. Ваш отрицательный голос был неуместен. Использование ID является известным антипаттерном SQL.
HLGEM

31

Этот поток мертв, но я хотел бы добавить , что ИМО не используя Idэто плохая практика. IdКолонна является особенным; это первичный ключ. Любая таблица может иметь любое количество внешних ключей, но она может иметь только один первичный ключ. В базе данных, где вызываются все первичные ключи , как только вы смотрите на таблицу, вы точно знаете, какой столбец является первичным ключом.Id

Поверьте, вот уже несколько месяцев я каждый день провожу целый день, работая во многих больших базах данных (Salesforce), и самое лучшее, что я могу сказать о схемах, это то, что у каждой таблицы есть первичный ключ с именем Id. Уверяю вас, я абсолютно не путаюсь с присоединением первичного ключа к внешнему ключу, потому что вызывается PK Id. Еще одна вещь, о которой люди не упоминали, это то, что таблицы могут иметь длинные глупые имена, например Table_ThatDoesGood_stuff__c; это имя достаточно плохое, потому что у архитектора было похмелье в то утро, когда он придумывал эту таблицу, но теперь вы говорите мне, что нехорошо не вызывать первичный ключ Table_ThatDoesGood_stuff__cId (помня, что имена столбцов SQL обычно не чувствительны к регистру).

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


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

6
Используя Id, вы попадаете в ситуацию, когда разработчики, не задумываясь, добавляют идентификатор первичного ключа к каждой создаваемой ими таблице. Одной из основ реляционных баз данных является использование значимых и агрегированных первичных ключей, а использование идентификатора не помогает.
Питер Б

Этот ответ кажется, будто вы говорите «Я предпочитаю Id» с аргументированными аргументами. Ваш аргумент в том, что вы можете сразу увидеть, какой ключ является первичным ключом, найдя тот, который называется Id. Ну, то же самое с tableId . Я могу гарантировать, что никогда не запутаюсь, какой ключ является первичным ключом. Я просто ищу тот, который имеет имя таблицы перед идентификатором. Кроме того, с какими языческими таблицами вы работаете, когда первый столбец не является первичным ключом? Я чувствую, что все ваши аргументы в этом ответе основаны исключительно на преференциях и похожи на «tableId для меня неправильно».
Даллин

@dallin все ответы являются самоуверенными, в противном случае кто-то просто ссылается на официальный стандарт, а его нет!
Джеймс

@James Я чувствую, что цель сайтов StackExchange - сократить количество мнений. Вот почему вопросы закрываются как слишком самоуверенные. Конечно, я думаю, что именно поэтому этот вопрос был закрыт - потому что он вызывает сомнительные ответы, но я чувствую, что этот конкретный ответ был чрезмерно самоуверенным без каких-либо реальных подтверждающих фактов или аргументов, основанных на фактах. Весь ответ можно обобщить, сказав: «В мое мнение, вы должны использовать Id, просто потому, что это то, что мне нравится ". Это не ценный ответ.
Даллин

24

Я не считаю это плохой практикой. Последовательность - это король, как обычно.

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

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

Точно так же Java-класс с именем 'Foo' не имеет своих свойств с префиксом 'Foo', не чувствуйте себя обязанным ставить префикс ID вашей таблицы с именами таблицы. В контексте обычно ясно, что это за идентификатор.


5
Таблицы реляционной базы данных не являются классами .
Адам Робинсон

1
Однако они являются структурами данных и аналогичны классам PODO. Применяются те же проблемы с именами.
ocodo

4
@Slomojo: Нет, они не аналогичны простым объектам. Объектно-ориентированный дизайн и дизайн базы данных не одно и то же, и даже не связаны между собой. Хотя в некоторых случаях они могут давать схожий (или даже одинаковый) дизайн, это не означает, что они связаны между собой. Например, отношения m: m тривиальны в классах, но невозможны между двумя таблицами без третьей таблицы ассоциации.
Адам Робинсон

1
Как это относится к стратегии именования, я не знаю. Моя аналогия (ясно?) Ограничена только до такой степени.
ocodo

2
Я сожалею, что мое подразумеваемое значение не было очень ясным, я должен был сказать " в этом смысле они аналогичны классам". В любом случае, я не думаю, что чрезмерно педантичный по этому поводу особенно конструктивен. С точки зрения именования таблицы и классы имеют много общего. Лучшие практики, которые развиваются в тупике, являются честной игрой для пересмотра или, по крайней мере, открыты для обсуждения. В этом Q & A есть много примеров, которые иллюстрируют это эффективно, и мне больше нечего добавить.
ocodo 18.10.11

24

От data.stackexchange.com

Идентификатор в сообщениях

БУМ, вопрос ответил.
Теперь иди и скажи своему учителю, что ТАК практикует плохой дизайн базы данных


8
Моя догадка в ФКС, на основе имен: PostTypeId -> PostTypes.Id; AcceptedAnswerId -> Answers.Id; OwnerUserId -> Users.Id, Почему такую ​​легкую практику следует считать «плохой»?
Sjoerd

3
Как именно это доказывает что-либо о лучших практиках?
GBa

5
Используется ли что-то в стеке или нет, не доказывает, хорошо это или плохо.
Питер Б

2
Это доказывает, что эта практика никоим образом не запрещает масштабируемость и полезность приложения.
Cypher

1
На самом деле ТАК практика не идеальна. Я бы использовал это название: PostType -> PostType.Id; AcceptedAnswer -> Answer.Id; OwnerUser -> User.Id
alpav

17

Это затрудняет (и сбивает с толку) естественное соединение на столе, поэтому да, это плохо, если не очень плохо.

Natural Join - это древний артефакт знания SQL (т. Е. Реляционная алгебра), который вы, возможно, видели в следующих случаях: perhaps в книге базы данных, возможно. Я имею в виду, что Natrual Join не является новой выдуманной идеей SQL, хотя СУБД, казалось, для ее реализации потребовалось целую вечность, поэтому это не новая запутанная идея для ее реализации, для вас может быть даже неразумно игнорировать его существование в наше время.

Что ж, если вы назовете все идентификаторы вашего первичного ключа, то вы потеряете легкость и простоту естественного соединения. select * from dudes natural join carsнужно будет написать select * from dudes inner join cars where cars.dudeid = dudes.idили select * from dudes inner join cars where dudes.carid = cars.id. Если вы можете сделать естественное объединение, вы можете игнорировать, каково это отношение на самом деле, что, на мой взгляд, довольно круто.


Если вы не пишете хранимую процедуру, когда в последний раз, когда вы разрабатываете приложение, вы действительно написали полностью отформатированный SQL-селектор? Современные языки включают в себя какую-то функцию ORM, которая управляет этими отношениями для вас. Имя столбца гораздо важнее, чем возможность писать чистый SQL вручную.
Билл Липер

4
@ Билл, я делаю все время, много-много раз в день, больше зависит от вашей кодовой базы, чем от языка, который вы разрабатываете. А для диагностики, если вы хотите установить хорошие и глубокие отношения, вы можете связать воедино эти естественные объединения и полностью избежать просмотра идентификаторов полей. И, как сказал знаменитый св. Иероним, «незнание SQL - это незнание баз данных».
Питер Тернер

Помимо того факта, что естественные объединения не поддерживаются повсеместно, IMO, естественные объединения труднее читать. Есть два столбца в отношениях или только один? Намного лучше быть явным и избегать естественных объединений.
Томас

1
@ Томас, я бы не включил естественные объединения в код, но для диагностики я нашел их довольно полезными, когда база данных смоделирована так, что они действительно работают.
Питер Тернер

16

Существует ситуация, когда наклейка «ID» на каждой таблице - не лучшая идея: USINGключевое слово, если оно поддерживается. Мы часто используем его в MySQL.

Например, если у вас есть fooTableстолбец fooTableIdи barTableвнешний ключ fooTableId, ваши запросы могут быть построены так:

SELECT fooTableId, fooField1, barField2 FROM fooTable INNER JOIN barTable USING (fooTableId)

Это не только экономит набор текста, но и намного более читабельно по сравнению с альтернативой:

SELECT fooTable.Id, fooField1, barField2 FROM fooTable INNER JOIN barTable ON (fooTable.Id = barTable.foTableId)

Это ответ, который больше всего для меня. USINGКлючевое слово поддерживается базой данных Postgres / MySQL / SQLite, означает меньше печатать , которые некоторые из списка других ответов в качестве причины для использования id, и , наконец , по моему субъективному мнению , является более удобным для чтения.
Майкл Бартон

11

Почему бы просто не спросить своего учителя?

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

Имена столбцов должны быть семантически значимыми. IDявляется универсальным.


8
слишком общий для чего? идентификатор таблицы?
Джим

3
@ Джим какой таблицы? idсамо по себе ничего не значит, особенно в контексте внешнего ключа к другой таблице. Это не имеет ничего classesобщего с хорошим базовым фундаментальным проектированием реляционных баз данных.

10
Чтобы быть немного глупым, стол, к которому он принадлежит. table.idэто вполне приемлемый способ обращения к idполю. Префикс имени поля с именем таблицы является избыточным.
ocodo

2
@Slomoj, это не более печатание, чем включение имени в столбце, и более подробное объяснение при совмещении имен таблиц с одно- или двухбуквенными сокращениями в соединениях монстров.

6
О каком кошмаре ты говоришь? Предположим, у вас есть структура ссылок сотрудников, в которой есть столбец, представляющий их руководителя. Что вы называете внешним ключом? Вы не можете назвать это EmployeeId, поскольку это, вероятно, ваш ПК. Имя FK не обязательно должно совпадать с PK. Он должен быть назван для того, что он представляет для объекта, в котором он содержится.
Томас,

7

Идентификатор неверен по следующим причинам:

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

Это может привести к ошибкам кода. Если вы используете базу данных, которая позволяет использовать естественное объединение (я не думаю, что вы должны когда-либо использовать это, но когда функции будут доступны, кто-то будет их использовать), вы присоединитесь к неправильной вещи, если получите разработчика, который использует это.

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


+1: это убедительные причины, на мой взгляд, в то время как другие ответы против IDменя не убеждают.
Фог

Re: «Если вы копируете объединения для создания сложного запроса» - значит, ваша проблема заключается в копировании и вставке. Остановите копирование и вставку, и вы увидите, насколько удобно именование car.id. Для соединения с FK используйте car.mfg = mfg.id, car.color = color.id, car.model = model.id - очень просто и соответствует тому, что вы написали бы в LINQ.
alpav

Попробуйте написать что-нибудь с 30 объединениями, и вы поймете, почему это антипаттерн.
HLGEM

Псевдоним - это первая и главная причина - это такая головная боль при выполнении больших сложных отчетов. Естественные объединения - просто сладкий бонус. Удивительно, как другие ответы просто игнорируют эти пункты. Я думаю, что добавление некоторых примеров прояснит ситуацию и поднимет этот ответ выше, чем он должен быть.
Лулу

5

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

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

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

Да, многое из этого может быть достигнуто с помощью стандарта наличия «id» и умения всегда использовать его в качестве «tableNameID», но это требует как знания, что практика существует, так и зависимости от первоначальных разработчиков, выполняющих с меньшими затратами интуитивная стандартная практика.

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

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


Предположим, что Companiesтаблица имеет 2 внешних ключа к Personsтаблице. Один представляет президента компании; другой представляет казначея компании. Вы бы действительно назвали колонки PersonID1и PersonID2? Было бы гораздо более наглядным назвать их PresidentIDи TreasurerID. Мне намного легче читать, inner join Person AS Presidents ON Company.PresidentID = Presidents.IDчемinner join Person AS Person1 ON Company.PersonID1 = Person1.PersonID
phoog

1
Нет. В вашем примере у меня, вероятно, была бы таблица CompanyOfficerили, CompanyPersonкоторая допускает отношения многие-ко-многим, между Companyи Personс дополнительной информацией о природе отношений. Если бы я реализовал это в Companyтаблице, я бы использовал имена столбцов PresidentPersonIDи TreasurerPersonIDсохранил часть имени * PersonID при добавлении дополнительного дескриптора. inner join Person as Presidents on Company.PresidentPersonID = Presidents.PersonID
Малахи

5

Практика использования Id в качестве поля первичного ключа приводит к практике, в которой id добавляется в каждую таблицу. Многие таблицы уже содержат уникальную информацию, которая однозначно идентифицирует запись. Используйте THAT в качестве первичного ключа, а не поле id, которое вы добавляете в каждую таблицу. Это одна из основ реляционных баз данных.

И именно поэтому использование идентификатора является плохой практикой: идентификатор часто не является информацией, а просто увеличивается.

рассмотрим следующие таблицы:

PK id | Countryid   | Countryname
    1 |         840 | United States
    2 |         528 | the Netherlands

Что не так с этой таблицей, так это то, что она позволяет пользователю добавить еще одну строку: Соединенные Штаты, с кодом страны 840. Она просто нарушила целостность отношений. Конечно, вы можете применить уникальность для отдельных столбцов или просто использовать первичный ключ, который уже доступен:

PK Countryid   | Countryname
           840 | United States
           528 | the Netherlands

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


1
Вы поймете, почему люди добавляют столбец общего ключа в каждую таблицу, когда вам приходилось переносить базы данных между разными системами или когда у вас было удовольствие объединять базы данных вместе.
Cypher

1
Иногда это так, но по моему опыту довольно редко бывает иметь уникальный уникальный неизменяемый ключ. Но даже в вашем примере у вас есть бессмысленный уникальный номер для идентификации стран, только тот, который выделен ISO, а не вашей базой данных.
CodesInChaos

И теперь, когда название страны меняется, вы должны обновить его по всей базе данных, чтобы исправить. Если бы вы просто использовали суррогатный ключ (например ... "id"), обновление было бы тривиальным. Натуральные ключи хороши - когда они полностью неизменны и никогда не меняются. На самом деле очень мало случаев, когда это правда.
Геррат

@Gerrat: при изменении названия страны числовой код ISO 3166-1 остается прежним, меняются только коды ISO 3166-1 alpha-2 и alpha-3. Это случилось с Бирмой / Мьянмой, например. Аналогично, если страна меняет свою территорию, но сохраняет свое название, числовой код ISO 3166-1 изменяется, но коды ISO 3166-1 alpha-2 и alpha-3 остаются. Это произошло, когда Южный Судан отделился от Судана, а Эритрея - от Эфиопии. Когда Восточная и Западная Германия воссоединились, они сохранили альфа-2 и альфа-3 коды Западной Германии, но получили новый числовой код. Когда страны полностью распадаются или трансформируются (подумайте…
Йорг Миттаг

… Результат балканских войн 90-х), они получают как новые числовые, так и буквенно-2 и альфа-3 коды.
Йорг Миттаг

4

Я всегда использую 'id' в качестве имени основного столбца для каждой таблицы просто потому, что это соглашение фреймворков, которые я использую (Ruby on Rails, CakePHP), поэтому мне не нужно переопределять его все время.

Это не победит академические причины для меня.


2

Я не думаю, что это плохая практика, если она используется правильно. Распространено иметь поле идентификатора с автоинкрементом, называемое «ID», к которому вы никогда не должны прикасаться, и использовать более дружественный идентификатор для приложения. Написание кода может быть немного громоздким, from tableA a inner join tableB b on a.id = b.a_idно этот код можно спрятать.

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


Вы никогда не объедините две таблицы, используя каждый первичный ключ, особенно идентификатор с автоматическим приращением. В приведенном выше примере из таблицы A будет внутренняя таблица соединений B b для a.id = b.table_a_id.
Билл Липер

Да, это то, что я имел в виду. Почти обеденный перерыв и нужна энергия.
Уэйн Молина

2

Удостоверение личности достаточно распространено, и я не думаю, что это кого-то смущает. Вы всегда будете хотеть знать стол. Помещать имена полей в производственный код без включения таблицы / псевдонима - плохая практика. Если вы чрезмерно обеспокоены возможностью быстрого ввода специальных запросов, вы сами по себе.

Надеюсь, никто не разработает базу данных sql, где ID - это зарезервированное слово.

CREATE TABLE CAR (ID);

Заботится об имени поля, первичном ключе и автоматическом увеличении на 1, начиная с 1, в одном симпатичном маленьком 2-символьном пакете. О, и я бы назвал это CARS, но если мы собираемся сэкономить на нажатиях клавиш, и кто на самом деле думает, что таблица с именем CAR будет иметь только одну?


1
это показывает, почему знание формальной реляционной теории важно, а имя таблицы представляет собой одну строку . Таблица Carпредставляет собой Tableгде каждый Rowпредставляет один Car. Призыв Carsменяет семантику и демонстрирует полное непонимание формальных основных принципов теории отношений. Rails - яркий пример того, кто знал достаточно опасно .

2

Этот вопрос задавали снова и снова, но я подумал, что тоже добавлю свое мнение.

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

  2. Поле id является автоинкрементом, без знака (это означает, что мне никогда не нужно устанавливать его значение, и оно не может быть отрицательным)

  3. Для внешних ключей я использую tablenameid (опять же, вопрос стиля), но первичный ключ, к которому я присоединяюсь, это поле id таблицы, поэтому согласованность означает, что я всегда могу легко проверять запросы

  4. Идентификатор короткий и сладкий тоже

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


1

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

Например, вы не сможете загрузить свою схему в такой инструмент, как Visio, и получить точные ERD.


Это будет ошибка стороннего инструмента, хотя. Соглашения об именах столбцов не заменяют фактические внешние ключи, которые инструмент должен анализировать.
Геррат

1

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

Это более или менее то, как люди читают данные таблиц и как они пишут свой код. Лично я, и, скорее всего, это самый популярный способ, который я вижу чаще всего, это то, что кодеры пишут полную ссылку как table.id, даже если им не нужно делать объединения или / и объединения. Например:

SELECT cars.color, cars.model FROM cars WHERE cars.id = <some_var>

Таким образом, вы можете перевести его на английский как «Дайте мне цвет и модель того автомобиля, который пронумерован как». а не как «Дайте мне цвет и модель той машины, которая идентифицируется как номер». Идентификатор автомобиля никоим образом не обозначает автомобиль, это всего лишь индекс автомобиля, если хотите, серийный номер. Так же, как когда вы хотите взять третий элемент из массива.

Подводя итог, я хотел бы добавить, что это просто вопрос предпочтений, и описанный способ чтения SQL является самым популярным.

Однако в некоторых случаях это не используется, например (гораздо более редкий пример), когда идентификатор представляет собой строку, которая действительно описывает. Например id = "RedFordMustang1970"или что-то подобное. Я действительно надеюсь, что смогу объяснить это по крайней мере, чтобы получить идею.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.