Руководство по использованию составных ключей для идентификации строк

8

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

Для наглядности представьте следующую таблицу. У нас есть элементы инвентаризации, которые организованы следующим образом: ( [K]символ первичного ключа, строки - это отношения)

    Sheet_Class        Sheet_Type         Sheet_Size
    ===========        ==========         ==========
[K] Sheet_Class-.  [K] Sheet_Type--.  [K] Sheet_Size
                 '---- Sheet_Class  '---- Sheet_Type
                                          Length
                                          Width
                                          Thickness

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

 Sheet_Class    Sheet_Type    Sheet_Size                        (Tables)
[Sheet_Class]  [Sheet_Type]  [Length], [Width], [Thickness]     (Column Values)
=============  ============  ==============================

Aluminum
               5052-H32
                             48, 96, 0.032
                             48, 96, 0.040
                             48, 96, 0.063

               6061-T6
                             60, 120,0.032
                             60, 120,0.040
                             60, 120,0.063

Steel
               1018-CRS
                             48, 96, 0.018
                             48, 96, 0.023
                             48, 96, 0.031

В его нынешнем виде (и я показал это в моей «схеме» выше) я использую простой (с автоматическим приращением) первичный ключ целого числа для записей в таблице Sheet_Size . Однако я хотел бы знать, лучше ли вместо этого использовать комбинацию столбцов Sheet_Type , Length , Width и Thickness ? Учитывая, что каждая запись в Sheet_Size должна обладать всеми этими уникальными качествами, и что автоинкрементное поле не продемонстрирует этого достаточно хорошо, это лучший путь?

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

Любое руководство будет оценено.

Обновление (08-12-2011)

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

К сожалению, я не могу принять оба ответа, поэтому я собираюсь принять X-Zeros за то, что они (что я чувствую) более критически оценили проблему и предложили корректировку схемы.

Спасибо всем за ваши ответы.

Брэд Кристи
источник

Ответы:

6

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

Sheet_size
===========
Id
Length
Width
Thickness

Во-вторых, создайте таблицу отношений размера листа / типа:

Sheet_size_type
================
Sheet_Type_Id
Sheet_Size_Id

Затем создайте следующие ограничения:

  1. Первичный ключ (и индекс) Sheet_sizeдолжен быть столбцом id
  2. Должен быть какой-то уникальный ключ (и индекс), применяемый к измерениям в Sheet_size. Подумайте, равны ли два листа измерений (48, 96, .5) и (96, 48, .5) (то есть имеет ли значение направление измерений)? Эту проблему может быть трудно решить, если использовать столбцы как часть первичного ключа, но она становится более управляемой при использовании ограничений и хранимых процедур.
  3. Первичный ключ (и индекс) Sheet_size_typeдолжен использовать оба внешних ключа, начиная с ключа с меньшим количеством элементов (вероятно sheet_type, в вашем примере). Вы можете захотеть дополнительный индекс в другом направлении, но это может быть необязательно.

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


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

Заводной-Muse
источник
Я планировал ограничить длину и ширину одной (возможно, двумя) десятичными точками, а толщина (максимум) расширилась бы до трех. Кроме того, мы становимся слишком конечными (и сама акция никогда не входит в числа, описанные в любом случае). Помимо этого, мне нравится мысль о разбивке размеров листа, но проблема, с которой я сталкиваюсь, - это другие вовлеченные столбцы (которые я исключил). (нужно больше места, см. следующий пост)
Брэд Кристи
Поскольку это список инвентарных запасов, я должен включить другую информацию, такую ​​как Плотность и Стоимость / фунт (которая в большой степени зависит от типа (и даже от толщины. Например, «Сталь» / «1018» может составлять 0,55 долл. США / фунт). при толщине 0,018-0,125 дюйма, но при толщине, превышающей 0,125 дюйма, она становится равной 0,65 долл. США / фунт. (И это также может отличаться между размером листа 48 "x96" x0.250 "1018 и 5052-H32). В вашем примере У меня была бы только одна запись для 48 "x96" x0.125 "(хотя я предполагаю, что таблица отношений могла бы иметь эти дополнительные метрики)
Брэд Кристи
Если вам нужно только небольшое количество десятичных знаков, тогда да, используйте фиксированную точность. Да, именно здесь (в данном случае) вы бы поместили такую ​​информацию (например, стоимость зависит от типа и размера листа), хотя вы можете создать дополнительные таблицы, на которые можно ссылаться. Вы также можете рассмотреть возможность создания пользовательских типов данных (например, плотности), чтобы люди не пытались сделать запрос ваших данных неожиданными способами.
Заводная муза
6

Выглядит как естественное против суррогатного ключевого решения, мнение которого варьируется от взвешенного и практического до академического , граничащего с догмой. В зависимости от РСУБД, существуют некоторые соображения относительно физической модели, которые могут иметь существенное влияние на производительность, например выбор кластеризованного ключа в SQL Server.

Лично, если у меня есть узкий ключ-кандидат с одним атрибутом, я испытываю желание использовать его. Широкие и / или составные ключи, по умолчанию я добавляю суррогат в модель. В вашем случае я бы проголосовал за столбец идентификаторов на Sheet_Size в качестве первичного кластеризованного ключа и уникального ограничения на тип / длину / ширину / толщину.

Марк Стори-Смит
источник
Но с учетом того, что теперь у вас есть «произвольный» ключ, заданный для строки, как уникальное условие гарантирует, что столбцы (при объединении) не могут иметь повторяющиеся значения? Насколько я понимаю, уникальный атрибут относится к ключу. Вы говорите , Sheet_Size INT PRIMARY KEYи Length UNIQUE, Width UNIQUE, Thickness UNIQUE? Я до сих пор не понимаю, как это предотвращает дублирование в таблице (без применения логики к интерфейсу вставки). (Может быть, я что-то упустил?)
Брэд Кристи
Уникальное ограничение для трех столбцов: ALTER TABLE dbo.Sheet_Size ADD CONSTRAINT UC_LengthWidthThickness UNIQUE ([Длина], [Ширина], [Толщина])
Марк Стори-Смит,
Спасибо за ваш отзыв! Я согласен, что уникальное ограничение на столбцы было бы отличным решением, но мне также нравится рекомендация X-Zero разбить размеры на новую таблицу (связанную с новой таблицей). Поэтому, чтобы объединить идеи, я буду применять уникальное ограничение для таблицы размеров «Урезанный», удаляя информацию о плотности и стоимости / фунтах и ​​помещая ее в таблицу отношений.
Брэд Кристи
4

Я перенаправлю вас немного на этот ответ из предыдущего вопроса .

Цитата: «Что касается способа разработки этого первичного ключа, есть две школы мысли:

  • тот, который делает PK отдельным столбцом, обычно самогенерируемым, например GUID или с автоматическим приращением INT (в вашем случае это отдельный столбец uniqueidentifier);
  • тот, который делает PK как столбец (или набор столбцов) внутренним по отношению к таблице (в вашем случае это будет имя пользователя, адрес электронной почты или SSN, что бы ни делало этого пользователя уникальным), которые однозначно идентифицируют запись.

Какой линии ты придерживаешься, это только вопрос вкуса ».

Побочные эффекты любого выбранного решения могут быть:

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

    • увеличить хранилище для всех задействованных таблиц;
    • увеличение / усложнение индексов на часто используемых ФК;
    • немного усложнить написание всех ваших операторов соединения
    • осчастливить мистера Джо Селко :-) (ссылки на его мнения о натуральных или искусственных ключах можно найти здесь и здесь , и в основном везде, где его спрашивают о проблеме)
  • использование сгенерированных ключей скорее всего:

    • упростить предыдущие 3 шага
    • усложнить ситуацию с репликацией таблицы с идентификатором PK (ссылки здесь , здесь или здесь )

Я лично поддерживаю сгенерированные ключи INT IDENTITY, но то, что вам подходит, должно быть хорошо.

Мэриан
источник
2

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

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

nvogel
источник
... За исключением удаления автоинкремента, поскольку внешний ключ потребует использования всех столбцов измерения в качестве части внешнего ключа (то есть всех четырех столбцов , включая тип). Не то, что я хочу в качестве внешнего ключа, точка - только отдельные столбцы, пожалуйста. Я согласен, что это хорошая идея, чтобы поместить уникальный ключ (и / или проверить ограничение) на размеры (и тип, в зависимости от дизайна таблицы).
Заводная муза
@ X-Zero, я уже говорил о ссылках на внешние ключи во втором параграфе. Вопрос, который я прочитал, заключается в том, следует ли реализовывать составной ключ, а также использовать ли автоинкремент.
nvogel