Мій учитель t-sql сказав нам, що називати наш стовпець ПК "Id" вважається поганою практикою без додаткових пояснень.
Чому називання таблиці PK стовпцем "Id" вважається поганою практикою?
Мій учитель t-sql сказав нам, що називати наш стовпець ПК "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
Практика ЗАВЖДИ з використанням 3-х літерних скорочень мені здається набагато гіршою, ніж використання назви стовпців id
. (Справа в точці: хто насправді скоротить назву таблиці cars
абревіатурою car
? Який кінець це служить?)
Сенс у цьому: бути послідовним. Якщо ваша компанія використовує Id і ви часто робите помилку вище, тоді звикайте використовувати повні таблиці імен. Якщо Ваша компанія забороняє стовпчик Id, поступово виконайте його і використовуйте будь-яку угоду про іменування, яку вони вважають за краще.
Зосередьтеся на вивченні речей, які САМО погані практики (наприклад, кілька вкладених співвіднесених підзапитів), а не обдумування таких питань. Питання іменування своїх стовпців "ідентифікатором" ближче до питання смаку, ніж до поганої практики.
ПРИМІТКА ДЛЯ РЕДАКТОРІ: помилка в цьому запиті навмисна і використовується для визначення точки. Будь ласка, прочитайте повну відповідь перед редагуванням.
cars
-> car
. Слава Богу - ви зберегли мені пальці). Не читайте це занадто глибоко.
cars
та manufacturer
. Одне - множина, інше - ні. Якщо люди хочуть забрати у db, це погана практика, яку слід обрати.
Тому що, коли у вас є таблиця із зовнішнім ключем, ви не можете назвати цей зовнішній ключ "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 називається ManufacturerId, але це робить менш ймовірним виникнення помилок в умовах приєднання, оскільки помилки стають очевидними.
Це здається простим, але коли ви приєднаєтесь до декількох таблиць, швидше за все ви помилитесь, знайдіть його нижче ...
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
можна подолати дуже легко, зробивши це просто справою смаку.
Бібліотека ActiveRecord Ruby та GORM Groovy за замовчуванням використовують "id" для сурогатного ключа. Мені подобається така практика. Дублювання назви таблиці у кожному імені стовпця є зайвим, нудним для запису та більш стомливим для читання.
Загальні або ключові назви стовпців, наприклад, "Ім'я" або "Ідентифікатор", повинні мати префікс таблиці "Таблиця".
Це усуває двозначність, простіше шукати, означає набагато менше псевдонімів стовпців, коли потрібні обидва значення "Id".
Менш використаний або стовпець аудиту або неклавішний (скажімо LastUpdatedDateTime) значення не має
name
та id
? Чому б у кожному стовпці не було вказано назву таблиці? Мабуть, довільно вибрати ці два імена для призначення префікса. Концептуально ви повинні мати таблицю, щоб у будь-якому випадку мати контекст стовпця. Чому б просто не використовувати цю назву таблиці для уточнення запиту: Person.Name, Animal.Name, Part.Name, ...
Цей потік мертвий, але я хотів би додати , що ІМО НЕ використовуючи Id
це погана практика. Id
Колона є особливим; це первинний ключ. Будь-яка таблиця може мати будь-яку кількість сторонніх ключів, але вона може мати лише один ключ, який є первинним. У базі даних, де викликаються всі первинні ключі , як тільки ви дивитесь на таблицю, ви точно знаєте, який стовпець є первинним ключем.Id
Повірте, я вже місяцями щодня витрачаю цілий день, працюючи в багатьох великих базах даних (Salesforce), і найкраще, що я можу сказати про схеми, - це те, що в кожній таблиці є виклик первинного ключа Id
. Можу запевнити, що я абсолютно ніколи не плутаюсь щодо приєднання первинного ключа до іноземного ключа, оскільки викликається ПК Id
. Інша річ, про яку люди не згадували - це те, що таблиці можуть мати довгі нерозумні назви Table_ThatDoesGood_stuff__c
; це ім'я досить погано, оскільки архітектор мав похмілля вранці, коли він придумав цю таблицю, але тепер ви говорите мені, що погана практика не викликати первинний ключ Table_ThatDoesGood_stuff__cId
(пам’ятаючи, що імена стовпців SQL взагалі не чутливі до регістру).
Якщо чесно, проблеми з більшістю людей, які навчають комп'ютерному програмуванню, полягають у тому, що вони не написали коду виробничого коду за роки, якщо ніколи, і не мають поняття, що насправді працює інженер з програмного забезпечення. Зачекайте, поки ви почнете працювати, а потім складіть свою думку про те, що ви вважаєте гарною ідеєю чи ні.
Я не вважаю це поганою практикою. Консистенція королева, як завжди.
Я думаю, це все в контексті. У контексті самої таблиці "id" означає саме те, що ви очікуєте, мітка, яка допомагає однозначно ідентифікувати її проти інших, які в іншому випадку можуть бути (або видатися) однаковими.
У контексті приєднань, ви несете відповідальність за конструювання приєднань таким чином, щоб зробити їх читабельними для вас та вашої команди. Так само, як можна ускладнити речі при поганому фразуванні чи називанні, так само можливо створити змістовний запит з ефективним використанням псевдонімів і навіть коментарів.
Таким же чином, клас Java під назвою "Foo" не має своїх властивостей з префіксом "Foo", не відчувайте зобов'язання префіксувати ваші ідентифікатори таблиці з іменами таблиць. Зазвичай в контексті зрозуміло, що таке ідентифікатор.
БУМ, відповів на запитання.
Тепер іди, скажи своєму вчителю, що ТАК практикує поганий дизайн бази даних.
PostTypeId -> PostTypes.Id
; AcceptedAnswerId -> Answers.Id
; OwnerUserId -> Users.Id
. Чому така простою практикою слід вважати «поганою»?
Це важко (і заплутано) виконувати природне поєднання на столі, тому так, це погано, якщо не дуже погано.
Natural Join - це древній артефакт SQL Lore (тобто реляційна алгебра), можливо, ви бачили одне із них: 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
поле. Префіксація назви поля із назвою таблиці зайва.
Ідентифікатор поганий з наступних причин:
Якщо ви робите багато запитів щодо звітування, вам завжди доведеться псевдоніми стовпців, якщо ви хочете бачити обидва. Таким чином, це стає марною витратою часу, коли ви можете назвати це належним чином. Ці складні запити досить важкі (я пишу запити, які можуть бути довгими сотнями рядків) без додаткового навантаження на непотрібну роботу.
Це може спричинити помилки коду. Якщо ви використовуєте базу даних, яка дозволяє використовувати природне приєднання (не те, що я думаю, ви коли-небудь повинні використовувати це, але коли є доступні функції, хтось їх використовуватиме), ви приєднаєтесь до неправильної речі, якщо отримаєте розробника, який це використовує.
Якщо ви копіюєте приєднання, щоб створити складний запит, легко забути змінити псевдонім на потрібний і отримати неправильне з'єднання. Якщо кожен ідентифікатор названий за таблицею, в якій він знаходиться, то, як правило, ви отримаєте синтаксичну помилку. Так само простіше визначити, якщо складний запит приєднатися до Ina неправильний, якщо ім'я 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 додається до кожної таблиці. У багатьох таблицях вже є унікальна інформація, яка однозначно ідентифікує запис. Використовуйте ТО як основний ключ, а не ідентифікаційне поле, яке ви додаєте до кожної таблиці. Це одна з основ реляційних баз даних.
І тому використання id - це погана практика: ідентифікатор часто не є інформацією, а лише автоматичним збільшенням.
розглянемо наступні таблиці:
PK id | Countryid | Countryname
1 | 840 | United States
2 | 528 | the Netherlands
Що не так у цій таблиці, це те, що вона дозволяє користувачеві додати ще один рядок: США, з кодом країни 840. Він просто порушив реляційну цілісність. Звичайно, ви можете надати унікальність для окремих стовпців, або ви можете просто використовувати первинний ключ, який уже доступний:
PK Countryid | Countryname
840 | United States
528 | the Netherlands
Таким чином ви використовуєте інформацію, яку ви вже маєте, як основний ключ, який лежить в основі дизайну реляційних баз даних.
Я не думаю, що це погана практика, якщо вона використовується правильно. Зазвичай є поле з автоматичним збільшенням ідентифікатора під назвою "Ідентифікатор", до якого ніколи не потрібно торкатися, та використовувати дружніший ідентифікатор для програми. Написати код, як, наприклад, може бути дуже громіздким, from tableA a inner join tableB b on a.id = b.a_id
але цей код можна витягнути.
В якості особистого уподобання я схильний префіксувати Id з назвою сутності, але я не бачу справжньої проблеми з просто використанням, Id
якщо цією обробкою керується база даних.
Ідентифікатор досить поширений, і я не думаю, що це когось бентежить. Ти завжди хочеш знати таблицю. Введення імен полів у виробничий код, не включаючи таблицю / псевдонім, є поганою практикою. Якщо ви надто стурбовані можливістю швидко вводити спеціальні запити, ви самостійно.
Сподіваємось, ніхто не розробляє базу даних sql, де ID - це зарезервоване слово.
CREATE TABLE CAR (ID);
Дбає про назву поля, первинний ключ та автоматичні кроки на 1, починаючи з 1 все в одному приємному пакеті з 2 символами. О, і я б назвав це АВТОМОБІЛІ, але якщо ми збираємося заощадити на натисканнях клавіш і хто насправді думає, що таблиця під назвою CAR буде мати лише одну?
Car
являє собою місце, Table
де кожен Row
представляє єдину Car
. Звернення Cars
зміни змістовно і показує повне нерозуміння формальних теорій реляційних основних принципів. Рейки - це прекрасний приклад того, хто знав достатньо, щоб бути небезпечним .
Це питання знову і знову побито, але я подумав, що я теж додам свою думку.
Я використовую id, щоб означати, що це ідентифікатор для кожної таблиці, тому коли я приєднуюся до таблиці і мені потрібен первинний ключ, я автоматично приєднуюся до первинного ключа.
Поле id - це автоматичне збільшення, не підписане (це означає, що я ніколи не повинен встановлювати його значення, і це не може бути негативним)
Для зовнішніх ключів я використовую tablenameid (знову ж таки, питання стилю), але первинний ключ, до якого я приєднуюся, - це поле таблиці id, тому послідовність означає, що я завжди можу легко перевіряти запити
id короткий і милий теж
Додаткова умовна умова - використовуйте малі регістри для всіх назв таблиць і стовпців, тому жодних проблем не може бути знайдено через регістр
Інша річ, яку слід врахувати, це те, що якщо ім'я первинного ключа відрізняється від імені іноземного ключа, то використовувати певні інструменти сторонніх виробників неможливо.
Наприклад, ви не зможете завантажити вашу схему в такий інструмент, як Visio, і дозволити їй створити точні ERD.
Я вважаю, що люди тут висвітлюють майже кожен аспект, але хочу додати, що "id" не є і не повинен читатися як "ідентифікатор", це більше "індекс", і, безумовно, він не вказує і не описує особу рядка. (Я, можливо, тут використав неправильне формулювання, будь ласка, виправте мене, якщо я це зробив)
Це більш-менш те, як люди читають дані таблиці та як вони пишуть свій код. Я особисто, і, швидше за все, це найпопулярніший спосіб, який я бачу частіше, це те, що кодери пишуть повне посилання table.id
, навіть якщо їм не потрібно робити об'єднання або / і приєднуватися. Наприклад:
SELECT cars.color, cars.model FROM cars WHERE cars.id = <some_var>
Таким чином, ви можете перекласти це англійською мовою як "Дайте мені колір та модель того автомобіля, який пронумерований як". а не як "Дайте мені колір та модель того автомобіля, який ідентифікується як номер". Ідентифікатор ніяк не представляє автомобіль, це лише індекс автомобіля, серійний номер, якщо ви хочете. Так само, як коли потрібно взяти третій елемент з масиву.
Отже, підсумовуючи те, що я хотів додати, це те, що це лише питання переваги, а описаний спосіб читання SQL є найпопулярнішим.
Хоча, є деякі випадки, коли це не використовується, наприклад (набагато більш рідкісний приклад), коли ідентифікатор - це рядок, який справді описує. Наприклад id = "RedFordMustang1970"
або щось подібне. Я дуже сподіваюся, що я міг би це пояснити хоча б, щоб отримати ідею.