Мой учитель t-sql сказал нам, что именование нашей колонки PK "Id" считается плохой практикой без каких-либо дополнительных объяснений.
Почему именование столбца PK таблицы "Id" считается плохой практикой?
Мой учитель t-sql сказал нам, что именование нашей колонки PK "Id" считается плохой практикой без каких-либо дополнительных объяснений.
Почему именование столбца PK таблицы "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
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" ближе к тому, чтобы быть делом вкуса, чем к плохой практике.
ПРИМЕЧАНИЕ ДЛЯ РЕДАКТОРОВ: ошибка в этом запросе является преднамеренной и используется, чтобы сделать точку. Пожалуйста, прочитайте полный ответ перед редактированием.
cars
-> car
. Слава Богу - вы спасли мои пальцы). Не читайте слишком глубоко в это.
cars
и manufacturer
. Один во множественном числе, другой нет. Если люди хотят выбирать в БД, это плохая практика, на которую следует обратить внимание.
Потому что, когда у вас есть таблица с внешним ключом, вы не можете назвать этот внешний ключ "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
С точными именами это не проблема
SELECT * FROM cars c JOIN manufacturer m ON manufacturer.Id = c.ManufacturerId
. Я использовал в id
течение многих лет и никогда не находил то, что вы описали, как настоящую проблему.
SELECT manufacturer.id FROM ...
. Любая возникающая в результате трудность id
может быть преодолена очень легко, что делает ее просто делом вкуса.
Библиотека Ruby ActiveRecord и Groovy GORM используют «id» для суррогатного ключа по умолчанию. Мне нравится эта практика. Дублирование имени таблицы в каждом имени столбца является излишним, утомительным для записи и более утомительным для чтения.
Общие или ключевые имена столбцов, такие как «Имя» или «Id», должны иметь префикс TableName.
Это устраняет неоднозначность, ее легче искать, и это означает, что псевдонимы столбцов будут намного меньше, когда необходимы оба значения «Id».
Меньше используемый или аудит столбца или не ключ (скажем, LastUpdatedDateTime) не имеет значения
name
и id
? Почему у каждого столбца нет префикса с именем таблицы? Кажется произвольным выбрать эти два имени для указания префикса. Концептуально у вас должна быть таблица, чтобы в любом случае иметь контекст столбца. Почему бы просто не использовать это имя таблицы для уточнения запроса: Person.Name, Animal.Name, Part.Name, ...
Этот поток мертв, но я хотел бы добавить , что ИМО не используя Id
это плохая практика. Id
Колонна является особенным; это первичный ключ. Любая таблица может иметь любое количество внешних ключей, но она может иметь только один первичный ключ. В базе данных, где вызываются все первичные ключи , как только вы смотрите на таблицу, вы точно знаете, какой столбец является первичным ключом.Id
Поверьте, вот уже несколько месяцев я каждый день провожу целый день, работая во многих больших базах данных (Salesforce), и самое лучшее, что я могу сказать о схемах, это то, что у каждой таблицы есть первичный ключ с именем Id
. Уверяю вас, я абсолютно не путаюсь с присоединением первичного ключа к внешнему ключу, потому что вызывается PK Id
. Еще одна вещь, о которой люди не упоминали, это то, что таблицы могут иметь длинные глупые имена, например Table_ThatDoesGood_stuff__c
; это имя достаточно плохое, потому что у архитектора было похмелье в то утро, когда он придумывал эту таблицу, но теперь вы говорите мне, что нехорошо не вызывать первичный ключ Table_ThatDoesGood_stuff__cId
(помня, что имена столбцов SQL обычно не чувствительны к регистру).
Честно говоря, проблемы с большинством людей, которые преподают компьютерное программирование, заключаются в том, что они не писали ни одной строки производственного кода в течение многих лет, если вообще когда-либо, и они не представляют, что на самом деле делает работающий инженер-программист. Подождите, пока вы не начнете работать, а затем решите, что вы считаете хорошей идеей или нет.
Я не считаю это плохой практикой. Последовательность - это король, как обычно.
Я думаю, что это все о контексте. В контексте самой таблицы «id» просто означает именно то, что вы ожидаете, метку, чтобы помочь однозначно идентифицировать ее по отношению к другим, которые в противном случае могут быть (или могут казаться) идентичными.
В контексте объединений вы несете ответственность за создание объединений таким образом, чтобы сделать их читаемыми для вас и вашей команды. Точно так же, как при плохой фразировке или наименовании можно усложнить ситуацию, так же возможно создать значимый запрос с эффективным использованием псевдонимов и даже комментариев.
Точно так же Java-класс с именем 'Foo' не имеет своих свойств с префиксом 'Foo', не чувствуйте себя обязанным ставить префикс ID вашей таблицы с именами таблицы. В контексте обычно ясно, что это за идентификатор.
БУМ, вопрос ответил.
Теперь иди и скажи своему учителю, что ТАК практикует плохой дизайн базы данных
PostTypeId -> PostTypes.Id
; AcceptedAnswerId -> Answers.Id
; OwnerUserId -> Users.Id
, Почему такую легкую практику следует считать «плохой»?
Это затрудняет (и сбивает с толку) естественное соединение на столе, поэтому да, это плохо, если не очень плохо.
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
. Если вы можете сделать естественное объединение, вы можете игнорировать, каково это отношение на самом деле, что, на мой взгляд, довольно круто.
Существует ситуация, когда наклейка «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
, и , наконец , по моему субъективному мнению , является более удобным для чтения.
Почему бы просто не спросить своего учителя?
Подумайте об этом, когда все столбцы PK ваших таблиц имеют имена, ID
это делает их использование в качестве внешних ключей кошмаром.
Имена столбцов должны быть семантически значимыми. ID
является универсальным.
id
само по себе ничего не значит, особенно в контексте внешнего ключа к другой таблице. Это не имеет ничего classes
общего с хорошим базовым фундаментальным проектированием реляционных баз данных.
table.id
это вполне приемлемый способ обращения к id
полю. Префикс имени поля с именем таблицы является избыточным.
Идентификатор неверен по следующим причинам:
Если вы делаете много запросов на отчеты, вы всегда должны псевдоним столбцов, если вы хотите видеть оба. Таким образом, это становится пустой тратой времени, когда вы могли бы назвать его правильно для начала. Эти сложные запросы достаточно сложны (я пишу запросы длиной в сотни строк) без дополнительной нагрузки на выполнение ненужной работы.
Это может привести к ошибкам кода. Если вы используете базу данных, которая позволяет использовать естественное объединение (я не думаю, что вы должны когда-либо использовать это, но когда функции будут доступны, кто-то будет их использовать), вы присоединитесь к неправильной вещи, если получите разработчика, который использует это.
Если вы копируете объединения для создания сложного запроса, легко забыть изменить псевдоним на тот, который вам нужен, и получить неверное объединение. Если каждый идентификатор назван в соответствии с таблицей, в которой он находится, то обычно вы получите синтаксическую ошибку. Также легче определить, является ли неправильным сложный запрос объединения, если имя pPK и имя FK совпадают.
ID
меня не убеждают.
Есть некоторые ответы, которые подходят к тому, что я бы назвал наиболее важной причиной не использовать «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
CompanyOfficer
или, CompanyPerson
которая допускает отношения многие-ко-многим, между Company
и Person
с дополнительной информацией о природе отношений. Если бы я реализовал это в Company
таблице, я бы использовал имена столбцов PresidentPersonID
и TreasurerPersonID
сохранил часть имени * PersonID при добавлении дополнительного дескриптора. inner join Person as Presidents on Company.PresidentPersonID = Presidents.PersonID
Практика использования 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
Таким образом вы используете уже имеющуюся информацию в качестве первичного ключа, который лежит в основе проектирования реляционных баз данных.
Я не думаю, что это плохая практика, если она используется правильно. Распространено иметь поле идентификатора с автоинкрементом, называемое «ID», к которому вы никогда не должны прикасаться, и использовать более дружественный идентификатор для приложения. Написание кода может быть немного громоздким, from tableA a inner join tableB b on a.id = b.a_id
но этот код можно спрятать.
В качестве личного предпочтения я склоняюсь к префиксу Id с именем сущности, но я не вижу реальной проблемы с использованием только того, Id
что он полностью обрабатывается базой данных.
Удостоверение личности достаточно распространено, и я не думаю, что это кого-то смущает. Вы всегда будете хотеть знать стол. Помещать имена полей в производственный код без включения таблицы / псевдонима - плохая практика. Если вы чрезмерно обеспокоены возможностью быстрого ввода специальных запросов, вы сами по себе.
Надеюсь, никто не разработает базу данных sql, где ID - это зарезервированное слово.
CREATE TABLE CAR (ID);
Заботится об имени поля, первичном ключе и автоматическом увеличении на 1, начиная с 1, в одном симпатичном маленьком 2-символьном пакете. О, и я бы назвал это CARS, но если мы собираемся сэкономить на нажатиях клавиш, и кто на самом деле думает, что таблица с именем CAR будет иметь только одну?
Car
представляет собой Table
где каждый Row
представляет один Car
. Призыв Cars
меняет семантику и демонстрирует полное непонимание формальных основных принципов теории отношений. Rails - яркий пример того, кто знал достаточно опасно .
Этот вопрос задавали снова и снова, но я подумал, что тоже добавлю свое мнение.
Я использую id для обозначения того, что это идентификатор для каждой таблицы, поэтому, когда я присоединяюсь к таблице и мне нужен первичный ключ, я автоматически присоединяюсь к первичному ключу.
Поле id является автоинкрементом, без знака (это означает, что мне никогда не нужно устанавливать его значение, и оно не может быть отрицательным)
Для внешних ключей я использую tablenameid (опять же, вопрос стиля), но первичный ключ, к которому я присоединяюсь, это поле id таблицы, поэтому согласованность означает, что я всегда могу легко проверять запросы
Идентификатор короткий и сладкий тоже
Дополнительное соглашение - используйте строчные буквы для всех имен таблиц и столбцов, чтобы не было проблем из-за регистра
Следует также учитывать, что если имя первичного ключа отличается от имени внешнего ключа, то невозможно использовать определенные сторонние инструменты.
Например, вы не сможете загрузить свою схему в такой инструмент, как Visio, и получить точные ERD.
Я нахожу, что люди здесь охватывают почти все аспекты, но я хочу добавить, что «id» не является и не должен читаться как «идентификатор», это скорее «индекс», и, конечно, он не указывает и не описывает идентичность строки. (Я мог использовать неправильную формулировку здесь, пожалуйста, поправьте меня, если я сделал)
Это более или менее то, как люди читают данные таблиц и как они пишут свой код. Лично я, и, скорее всего, это самый популярный способ, который я вижу чаще всего, это то, что кодеры пишут полную ссылку как table.id
, даже если им не нужно делать объединения или / и объединения. Например:
SELECT cars.color, cars.model FROM cars WHERE cars.id = <some_var>
Таким образом, вы можете перевести его на английский как «Дайте мне цвет и модель того автомобиля, который пронумерован как». а не как «Дайте мне цвет и модель той машины, которая идентифицируется как номер». Идентификатор автомобиля никоим образом не обозначает автомобиль, это всего лишь индекс автомобиля, если хотите, серийный номер. Так же, как когда вы хотите взять третий элемент из массива.
Подводя итог, я хотел бы добавить, что это просто вопрос предпочтений, и описанный способ чтения SQL является самым популярным.
Однако в некоторых случаях это не используется, например (гораздо более редкий пример), когда идентификатор представляет собой строку, которая действительно описывает. Например id = "RedFordMustang1970"
или что-то подобное. Я действительно надеюсь, что смогу объяснить это по крайней мере, чтобы получить идею.