SQL: предотвращение жесткого кодирования или магических чисел

Вопрос: Каковы некоторые другие стратегии относительно предотвращения магических чисел или трудно кодированных значений в Ваших сценариях SQL или хранимых процедурах?

Рассмотрите хранимую процедуру, задание которой состоит в том, чтобы проверить/обновить значение записи на основе StatusID или некоторая другая таблица поиска FK или диапазон значений.

Рассмотрите a Status таблица, где идентификатор является самым важным, поскольку это - FK к другой таблице:

alt text

Сценарии SQL, которых нужно избежать, являются чем-то как:

DECLARE  @ACKNOWLEDGED tinyint

SELECT  @ACKNOWLEDGED = 3   --hardcoded BAD

UPDATE  SomeTable
SET     CurrentStatusID = @ACKNOWLEDGED
WHERE   ID = @SomeID

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

Также стараться избегать a SELECT на основе текстового описания/имени состояния:

UPDATE  SomeTable
SET     CurrentStatusID = (SELECT ID FROM [Status] WHERE [Name] = 'Acknowledged')
WHERE   ID = @SomeID

Вопрос: Каковы некоторые другие стратегии относительно предотвращения магических чисел или трудно кодированных значений в Ваших сценариях SQL или хранимых процедурах?

Некоторые другие мысли о том, как достигнуть этого:

  • добавьте новое bit столбец (названный как 'IsAcknowledged') и ряды правил, где может быть только одна строка со значением 1. Это помогло бы в нахождении уникальной строки: SELECT ID FROM [Status] WHERE [IsAcknowledged] = 1)
19
задан p.campbell 4 January 2010 в 18:59
поделиться

9 ответов

На каком-то уровне будет некоторая "жесткая кодировка" значений. Идея их устранения звучит с двух сторон:

  1. сделать код более читабельным (т.е, говоря "Признано" , а не 3 , это , вероятно, сделает ваши намерения более очевидными для читателя.
  2. Сделать код более динамичным, когда одна функция может принимать параметр, а не несколько функций, которые не принимают (это, конечно, упрощение, но смысл все равно должен быть достаточно самоочевидным)

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

Самым большим "нет-нет" в жестком кодировании значений является жесткое кодирование значений, которые ссылаются на другие объекты (другими словами, жесткое кодирование первичного ключа для соответствующего объекта). Строка 'Acknowledged' все еще является жестко закодированным значением, она просто более прозрачна по своему значению и не является ссылкой на что-то другое. Для меня она сводится к этому: если вы можете (разумно) посмотреть на него, сделайте это . Если вы не можете (или если что-то делает это неразумной задачей либо с точки зрения производительности, либо с точки зрения удобства обслуживания), то это жесткий код. Используя это, вы можете найти значение 3, используя Acknowledged; вы не можете найти Acknowledged ни от чего другого.

.
7
ответ дан 30 November 2019 в 03:20
поделиться

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

.
1
ответ дан 30 November 2019 в 03:20
поделиться

Ну, начнем с того, что Бизнес-логики , вероятно, следует избегать на уровне хранилища.

Поскольку это кажется неизбежным при использовании БД, например, Sql Server, где много BL может существовать в DB, я думаю, вам лучше вернуться к использованию строковых идентификаторов , а не автоматических идентификаторов .

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

Например, используя .Net подход, можно хранить множество уникальных идентификаторов строк в любом месте, начиная с конфигурационных файлов , и заканчивая дополнительными поисками с помощью выбранных db, XML файлов.

.
0
ответ дан 30 November 2019 в 03:20
поделиться

Для таких ситуаций, как ваша таблица состояния, я создаю так называемые "статические" наборы данных. Эти таблицы содержат данные, которые

  • установлены и определены при создании,
  • Никогда не изменяются, и
  • ВСЕГДА одинаковы, от экземпляра БД к экземпляру БД, с no exceptions

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

Вы не должны использовать числа, вы можете использовать строки -- или двоичные файлы, или даты, или что угодно простое, легкое и наиболее подходящее. (Когда я могу, я использую строки типа char - а не варвары - такие как "RCVD", "DLVR", ACKN и т.д. - это более простые жестко закодированные значения, чем, скажем, 0, 2 и 3.)

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

.
12
ответ дан 30 November 2019 в 03:20
поделиться

Недавно я выяснил, что магические числа могут быть реализованы видами:

CREATE VIEW V_Execution_State AS
SELECT 10 AS Pending, 20 AS Running, 30 AS Done

DECLARE @state INT
SELECT @state = Pending FROM V_Execution_State
10
ответ дан 30 November 2019 в 03:20
поделиться

Вот как я бы это сделал. (Потому что это намного быстрее, чем ваш пример)

UPDATE SomeTable
SET CurrentStatusID = [Status].[ID]
FROM SomeTable
 RIGHT JOIN [Status] ON [Name] = 'Acknowledged'
WHERE SomeTable.[ID] = @SomeID

(не протестированные могут иметь опечатки)

.
3
ответ дан 30 November 2019 в 03:20
поделиться

Не полагайтесь на IDENTITY для всех ваших удостоверений личности. Когда у вас есть, например, таблица поиска, которая будет состоять менее чем из 50 строк, то вполне разумно либо определить эти поиски как имеющие определенные ID, либо использовать для них строковый код. В любом случае, "жесткое кодирование" больше не является проблемой

.
3
ответ дан 30 November 2019 в 03:20
поделиться

Одна идея:

CREATE FUNC dbo.CONST_ACKNOWLEDGED()
RETURNS tinyint
AS
BEGIN
   RETURN 3
END

Однако, это имеет смысл только в том случае, если у вас нет автономера, IMHO

.
3
ответ дан 30 November 2019 в 03:20
поделиться
[

] Если сущность 'Статус', которая является частью вашей доменной модели, имеет предопределенные значения, некоторые из которых должны быть обработаны определенным образом хранимыми процедурами, то совершенно нормально жестко закодировать ссылки на эти конкретные значения в вашем коде. Проблема здесь заключается в том, что вы путаете то, что потенциально является абстрактным ключом (столбец идентификатора ID) для значения, которое имеет значение в вашей доменной модели. Хотя сохранять столбец ID ID идентичности нормально, следует использовать значимый атрибут вашего доменного объекта, когда вы ссылаетесь на него в коде, это может быть имя, или это может быть числовой псевдоним. Но этот числовой псевдоним должен быть определен в вашей доменной модели, например, 3 означает 'Acknowledged', и его не следует путать с полем абстрактного идентификатора, которое, как вы говорите, может быть столбцом идентификатора в некоторых экземплярах вашей базы данных.[

].
1
ответ дан 30 November 2019 в 03:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: