Проблема разработки хранимых процедур SQL - PullRequest
2 голосов
/ 09 июня 2009

Я недавно видел базу данных, где была таблица Types со столбцами Id, Key и Name.

Id был просто идентификатором типа, Key был коротким именем ключа для типа, например «beer», а Name был текстом, который мог отображаться для пользователя (например, «Наше величайшее пиво»). Идентификатор был, конечно, уникальным и был основным ключом для этой таблицы. Ключ также был уникальным . Другие таблицы всегда связывались с типами таблиц с использованием столбца Id, но хранимые процедуры всегда использовали ключ для фильтрации (например, "X inner join Types on X.type_Id = Types.Id where Types.Key = 'beer' " вместо "X.type_Id = 3").

Я думал об этом как о плохом подходе. Я бы использовал Id вместо Key, даже если бы знал, что Key уникален. Я думаю, что было бы возможно (и хорошо), что Ключ изменяется, но Идентификатор не должен изменяться, поскольку он используется в других таблицах для связи. Есть ли какие-то правила, чтобы этого не делать? Я имею в виду, что если мы изменим Key "beer" на "beers", некоторые хранимые процедуры перестанут работать должным образом (и на самом деле была такая ситуация). Для меня было довольно интуитивно понятно, что если Id идентифицирует строку в таблице, мы всегда должны использовать идентификатор, так как другие атрибуты могут измениться, если это необходимо, и это не должно вызывать проблем. Я прав?

Ответы [ 5 ]

5 голосов
/ 09 июня 2009

Key - более значимый и понятный способ доступа к данным в таблицах. Позвольте мне сказать это так: вы бы предпочли отладку этого

SELECT ColumnA, ColumnB
FROM Table T
INNER JOIN Keys K
ON T.KeyId = K.KeyId
WHERE K.Key = 'Beer'

Или

SELECT ColumnA, ColumnB
FROM Table T
WHERE T.KeyId = 103461

Когда вы понятия не имеете, что представляет собой «103461»? ​​

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

EXEC get_items_by_category 'Beer'

Или

EXEC get_items_by_category 103461

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

1 голос
/ 09 июня 2009

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

Лично я бы никогда не зависел от конкретного идентификатора, если это автоинкремент. Особенно, если строка может быть удалена. Что делать, если вы однажды сбросите данные и импортируете их снова, возможно, потому что хотите установить новую установку. Сервер SQL повторно перечислит идентификатор, и все ваши запросы будут прерваны.

РЕДАКТИРОВАТЬ : (отвечая на ваш комментарий)

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

1 голос
/ 09 июня 2009

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

0 голосов
/ 09 июня 2009

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

0 голосов
/ 09 июня 2009

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

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

Однако в этом случае могут работать другие конструкции, например таблица IsBeer, содержащая все идентификаторы «Beers», или таблица Flags, в которой есть столбец IsBeer (и столбец IsFood) или что-то подобное , Опять же, вы вообще не можете зависеть от их существования, но вам, по крайней мере, не придется беспокоиться об изменении столбца, нарушающем логику, поскольку у вас будет отношение FK.

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

SELECT ColumnA, ColumnB
FROM Table T
INNER JOIN Keys K
    ON T.KeyId = K.KeyId
    WHERE K.IsBeer = 1
...