Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Primary Key и Unique key


Страницы:   1 2 3 4

Piter ©   (2005-10-04 22:19:00) 

Объясните, пожалуйста, человеческим языком - зачем нужен Primary Key?

Большинство отвечает - чтобы создать уникальное поле. Ок, а чем это тогда отличается от Unique key?
Большинство отвечает, что в Primary Key можно указывать несколько полей.

Это весь функционал этих директив?

А что физически в базе происходит при этом? Так ли важно задавать первичный ключ? Если первичный ключ - одно поле, то можно легко заменить на Unique key?

А если у меня все поля могут быть одинаковые - то Primaty Key не нужен?

А если уникальность нужна только для всех полей - допустим указывать в Primary Key все поля базы? Имеет ли это смысл?

Запутался чего-то я...


ANB   (2005-10-05 11:06:00) [41]


> Там была прога еще на ЕС-ках
- на больших ? Круто. Вообще то я на них только учился, работать нормально уже не довелось. Но когда учился - то делали учетную систему для курсантов. На адабасе. Кстати, куда он делся ? Клевая СУБД была.


msguns   (2005-10-05 11:02:00) [42]

>ANB ©   (05.10.05 10:47) [28]

Похожая траблища была и на радиозаводе, где я когда-то работал. Там была прога еще на ЕС-ках по з/пл, где ключом был табельный номер. Все бы хорошо, но вся закавыка была в том, что этот табельный у чела вполне мог поменяться, например, при переходе из одного подразделения в другое (таб номер был ПППЧЧЧЧ (№ подразделения+№чела в подразделении). И получалась милая штука: в первые несколько месяцев после смены места работы челу нельзя было посчитать ни отпускные, но больничные, ни квартальную премию. Все делалось "ручками" непосредственно в расчетной группе бухгалтерии. А в ИВЦ два прогера трудились исключительно для выявления "перебежчиков", сбора по ним данных из разных ТН, распечатке этих данных и предоставлении отчетов в расчетную группу. Учитывая, что на заводе работало 12-14 тыщ народу, работы у них было выше крыши.
И уж совсем ж.. начиналась, когда надо было дать инфу для исчисления пенсии. Помницца, даже написал прожку на асме, которая выгребала из архивов инфу по челу, ища его по ФИО и доп.указанным реквизитам (номер подразделения, дата рождения, стаж, должность и т.д.).
Кстати, насколько асмовские проги, работающие с лентами (архивы были на лентах) на физуровне были шустрее аналогичных кобол- и PL-ных ;))


Desdechado   (2005-10-05 11:00:00) [43]

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

Для примера. Я первичные ключи всегда делаю суррогатными. Но это не мещает на таблицу с ним влепить еще и уникальный. Просто уникальность со временем может вырости из одного поля в 2 и более, а первичный-суррогатный останется таким, как я пожелал. И логику БД менять не придется, не придется и данные переконвертировать.

В некоторых условиях на таблицу я накладываю ограничение уникальности, не ставя первичного ключа. Например, если это таблица с внешним ключом (он же будет и уникальным). Эта таблица может использоваться чрезвычайно редко, да и строк в ней меньше, чем в той, на которую она ссылается. Поэтому я не объединяю эти 2 таблицы в одну. Денормализация, конечно, но иногда оправданная.

Кстати, в некоторых СУБД есть еще дополнительные возможности при наличии в таблице первичного ключа. Например, в Оракл таблицу можно организовать по индексу, но только по PK. Т.е. без PK так сделать нельзя. Организовать по индексу - это таблица-индекс в одном флаконе.


ANB   (2005-10-05 10:47:00) [44]

Чисто логически ПК и УК не отличаются. Более того, по ПК автоматически создается УК.
Идея придумана для облегчения жизни нам - разработчикам. Когда залезаешь в таблицу, то УК там может быть много, а ПК - только один и я сразу вижу, что является ключом таблицы. И другим программистам видно. В своем проекте через год уже придется разбираться заново, а в чужом, так вообще без указания ПК повесишься копаться.

Как правило, ПК делают суррогатным. ИНН, кстати, попытка использовать естественный ключ, так же как и номер в ПФР. Я раз попался на эту удочку - сделал его ключом (в Clipper прямое понятие ПК нет, генераторов тоже и я поленился делать суррогатную генерацию ключей). Сколько граблей я после этого огреб - мама дорогая. Выяснилось, что далеко не у всех работников есть ИНН и номер ПФР. А различать их надо. Пришлось генерить "суррогатные" номера ПФР, отличать их от обычных (в документах левый номер не должен был появляться). Затем начались проблемы с каскадным обновлением при присвоении номеров.
Когда перешел на оракл - завязал я с естественными ключами баловаться.
Более того, на одном месте работы нас приучили даже в линковочные таблицы вставлять суррогатный ИД (там то он вообще не нужен), в противном случае не принимали таблицу на генерацию на реальный сервер.


Sergey_Masloff   (2005-10-05 10:43:00) [45]

Val ©   (05.10.05 10:14) [22]
>ну и что? где противоречие? думаете старые присвоили другим людям? :)
Не исключаю. Допустим с бланками полисов ОСАГО такое было - а это БСО со степенью защиты как у ден. знаков. Это сведения 100% точности и не единичный случай а массовое явление было.

>записи с pk тоже удаляют из таблиц, но pk не перестает однозначно >определять запись.
У меня не удаляют. В историю можно отправить а удалить - фигушки. Много раз спасало от таких проблем что страшно представить. Вообще, насколько я сталкивался, в больших системах это довольно распространенная практика.


evvcom   (2005-10-05 10:41:00) [46]

Кроме того, чем ближе разрядность PK к разрядности регистра процессора, тем быстрее будет осуществляться связка (join). Поэтому в качестве первичных ключей крайне нежелательно использовать символьные поля длиной более 4 байт для 32-разрядных ОС, имхо.
Наиболее часто употребимо, насколько мне известно, первое поле с именем, начинающимся на "ID" целого типа (4 байта) (суррогатный ключ). На все остальное, если надо, создаются индексы уникальные (ключи) или неуникальные.


Sergey_Masloff   (2005-10-05 10:39:00) [47]

MOA ©   (05.10.05 10:26) [24]
ап чем и речь ;-))


MOA   (2005-10-05 10:26:00) [48]

Кстати, с коды наподобие ИНН и пример приведённый msguns ©   (05.10.05 10:08) [20] как раз хорошая иллюстрация.
Делаем суррогатный ключ, назначаем его первичным.
А затем объявляем, что поле ИНН (пенсионный код, код мед. страхования) д.б. уникальное (не может быть одинаковый код у двух людей). Понятно, что они уникальные, понятно, первичный-один. И крайне желательно, чтобы не менялся - иначе геморрой с каскадными обновленмиями - но это уже как раз тема холивара ;).
Или объявляем, что msguns © комбинация полей "[год]-[месяц]-[ид-р работника]-[код начисления/удержания]" - должна быть уникальной. Тем самым, вводим "бизнес-правила" - и гарантируем, что база будет избавлена хотя бы от этих ошибок.


msguns   (2005-10-05 10:15:00) [49]

>Sergey_Masloff   (05.10.05 10:10) [21]
>У меня лично ИНН менялся 3 раза. Официально.

Сережа, помилосердствуй.. Для наших "правителей", меняющих законы и системы контроля и учета, как перчатки, в угоду то одной, то другой правящей верхушке, вообще правила не писаны. Какие уж тут БД. Однако разработчик модели данных любой прикладухи должен исходить из определенных предпосылок-догм. Иначе вообще ничего не стоит проектировать.


Val   (2005-10-05 10:14:00) [50]

>Sergey_Masloff   (05.10.05 10:10)
ну и что? где противоречие? думаете старые присвоили другим людям? :) записи с pk тоже удаляют из таблиц, но pk не перестает однозначно определять запись.


Sergey_Masloff   (2005-10-05 10:10:00) [51]

msguns ©   (05.10.05 10:08) [20]
>Именно по ИНН чел может быть однозначно идентифицирован
Побожись ;-)
У меня лично ИНН менялся 3 раза. Официально.


msguns   (2005-10-05 10:08:00) [52]

>Piter ©   (05.10.05 09:55) [17]
>погодь... а если PK по нескольим полям... Что, у у записи ни одно это поле менять не надо?!

Существует два типа PK:
- нативный (естественный). Например, данные при рождении человека ФИО. Этот "ключ" содержит 3 поля. И, в общем-то может меняться. Однако эта триада уникальна лишь в отдельном, небольшом пространстве объектов. Например, в семье. У Петра Иванова вряд ли будет два сына Сидора, однако в классе, где учится Сидор Петрович Иванов, запросто может быть его полный тезка. В этом случае ключ уже не будет уникальным и к нему следует добавить еще одно поле: например дату рождения. Хотя нет никакой гарантии, что когда Сидор поступит в институт, там не будет учиться такой же Сидор, но родившийся с ним в один день.
Кроме того, по жизни Сидор Петрович может поменять свое имя или даже фамилию.
Именно поэтому нативный PK имеет ограниченное использование, хотя порою весьма оправданное. Как пример, можно привести лицевой счет по з/пл, где в качестве нативного ключа используется связка [год]-[месяц]-[ид-р работника]-[код начиления/удержания]. В рамках БД этот "салат" гарантированно не должен повторяться.

- суррогатный, т.е. реально не сущестующий, но необходимый для однозначной идентификации объекта хранения атрибут-поле. Как пример - ИНН (индивидуальный налоговый номер). Один раз присвоенный, такой ключ не меняется до самой смерти человека. Но даже когда он помрет, инфа о нем останентся в БД. Именно по ИНН чел может быть однозначно идентифицирован. При этом он может менять свой адрес, ФИО, даже паспорт.


Sergey_Masloff   (2005-10-05 10:01:00) [53]

Piter ©   (05.10.05 09:55) [17]

>погодь... а если PK по нескольим полям... Что, у у записи ни одно это поле >менять не надо?!
Именно так. Или не использовать эти поля как первичный ключ. Как уникальный - пожалуйста.


msguns   (2005-10-05 09:55:00) [54]

Основное семантичесое (смысловое) назначение PK - поддержка межтабличных связей. Как наиболле распространенный пример - счет-фактура. Для того, чтобы строки фактуры не "потерялись" в самом счете (заголовке) и служит PK таблицы заголовка, на которую ссылаются записи таблицы фактуры. Именно поэтому не имеет смысла менять это поле в главной таблице.
Кроме того, на PK посторен механизм FK, обеспечивающий т.н. справочніе ссылки.
Для лучшего понимания механизма PK советую почитать немного теории. В частности о нормализации, избыточности и ссылочной целостности данных в БД.
Еще одна характеристика PK - это существенное ускорение доступа к данным из-за встроенного в любой сервер механизма индексации и кэширования. Доступ к таблицам без PK, даже линейным (не имеющим структурированные данные и хранящие инфу об объектах в виде одиночных, несвязанных записей), в сотни, а то и тысячи раз медленнее по сравнению с той же таблицей, но имеющей PK.

УИ - это совсем другое, хотя, как справедливо заметил АП, механизм его реализации построен похоже. Однако, в отличие от PK, неграмотно и невдумчиво построенные индексы могут не только не ускорить работу с таблицами, но и существенно ее замедлить (нарушено правило 20%).


Piter   (2005-10-05 09:55:00) [55]

Sergey_Masloff   (05.10.05 6:24) [14]
Да все я понял. Лучше считай что нельзя - ну честное слово


погодь... а если PK по нескольим полям... Что, у у записи ни одно это поле менять не надо?!

А как же быть тогда в случае, который я привел - что все поля могут совпадать, например Имя, Фамилия, год рождения человека?


MOA   (2005-10-05 09:41:00) [56]

>чем грозит отсутствие PK?
Тем, что данное отношение не будет ни в какой нормальной форме. Все кортежи в отношении обязаны быть уникальными - по определению отношения (мнодества). Та минимальная совокупность полей, которая позволяет отличить один кортеж от другого - есть ключ-кандидат. Таких совокупностей в отношении может быть не одна. Из ключей-кандитатов выбираем какой-то один и называем его первичным ключом.
Можно самим ввести суррогатный ключ (автоинкремент, GUID и т.д.). Холиваров по этому поводу куча.
Если мы не выделяем первичный ключ - значит, мы игнорируем ту теорию, на которой, собственно, и построены РСУБД - а значит, рано или поздно наступим на грабли, и чем позже наступим - тем больше разобъём лоб ;).


Sergey_Masloff   (2005-10-05 06:26:00) [57]

Megabyte ©   (05.10.05 01:29) [13]
>Да и послений номер автоинкрементного говорит о том, сколько записей >вносилось в эту базу
Не, вот так лучше не делать (обычно). Не говоря о том что шаг инкремента не обязан быть 1, есть и масса других "против"


Sergey_Masloff   (2005-10-05 06:24:00) [58]

Piter ©   (05.10.05 00:55) [12]
>>Нельзя. На то он и первичный

>мне кажется, ты меня не понял. Я имел в виду, что значение поля, которое >является уникальным ключом, можно менять. Это ведь так?

Да все я понял. Лучше считай что нельзя - ну честное слово. Вот смотри - есть у меня интерфейс. У него есть уникальный идентификатор - GUID. Я создаю другой интерфейс с таким же идентификатором - физически это возможно, языковые средства позволяют. Но сделать так - путь к огромным проблемам так как вся идеология COM базируется на предположении что IID каждого интерфейса - разный.
 Продолжим. Можно в Delphi в наследнике понизить видимость члена класса? Был паблик стал привейт? Да пожалуйста. Ну подумаешь хинт компайлера. Только делать это нельзя ибо противоречит всей идеологии ООП (да и, к счастью, ,бесполезно потому что реально все останется как было ).  
 Также и с ПК. В некоторых (большинстве) СУБД менять можно его значение. Просто необходимость в изменении значения ПК записи - в 99.9999 % случаев признак плохого проектирования.

>Имеет смысл заводить какое-то отдельное auto increment поле, которое и >назначать уникальным ключом?
>И если это имеет смысл - то какой?
Экономия времени и памяти на индексах внешних ключей.


Megabyte   (2005-10-05 01:29:00) [59]

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


Piter   (2005-10-05 00:55:00) [60]

Sergey_Masloff   (04.10.05 23:05) [7]
Нельзя. На то он и первичный


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

Ну например, есть поле Name, оно является уникальным ключом. Могу же я у конкретной записи сменить значение Name?
Или другими словами, поле Name может входить в выражение UPDATE?

А то, что менять сам ключ, например с поля Name на поле Family, не рекомендуется - это понятно...

Anatoly Podgoretsky ©   (04.10.05 23:22) [9]
в свое время огреб проблем с МФ из-за отсуствия ключа


На самом деле, вопрос не из-за МФ возник, тут просто захотелось разобраться в вопросе.
Да и в принципе, как таковых проблем я в МФ не замечал, хоть там и действительно не задан PK.
Единственное, что может он может быть мог работать быстрее, если было бы PK...

Вообще, сейчас интересен вопрос - а чем грозит отсутствие PK? Я так понимаю, только тормозами?

И вот еще что хотелось бы узнать. Например, логика базы такова, что уникальными могут быть сочетания только всех полей. Имеет смысл делать PK по ВСЕМ полям таблицы?

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

Name | Family | Year ...

В предельном случае понятно, что все поля могут совпадать у двух сотрудников. Имеет смысл заводить какое-то отдельное auto increment поле, которое и назначать уникальным ключом?
И если это имеет смысл - то какой?


Страницы:   1 2 3 4

Наверх

Титульная страница Поиск, карта сайта Написать письмо