Возьмите этот сценарий: у вас есть несколько перечислений флагов в С#, связанных с (и фактически сгенерированных) таблицами Enum-ish в SQL Server. Скажите, что вы являетесь дистрибьютором, и вы разрешаете своим реселлерам указывать, в какие штаты США они отправляются. Будучи блестящим и элегантным инженером-программистом, вы реализовали их как бит-комбинируемое значение флага для сохранения хранилища:
create table USState (
StateID bigint, StateAbbr char(2), StateName varchar(50))
/* insert all US States + DC into USState, StateIDs must be in powers of two */
/* StateID 0 reserved for 'None': */
create procedure GetStatesByFlag (@StateFlags bigint) as
declare @StateIDs table
(
StateID bigint,
primary key (StateID)
)
insert into @StateIDs
select StateID
from USState
where @StateFlags & StateID != 0
or (@StateFlags = 0 and StateID = 0)
select s.StateID, s.StateAbbr, s.StateName
from
USState s join
@StateIDs si
on si.StateID = s.StateID
Сладкое. Вы можете включать/исключать динамически как в SQL, так и в С# с помощью побитовой логики, которая позволяет мгновенно убрать списки флажков и выбирать списки в Asp.NET, сохраняя при этом только одно 64-разрядное число, чтобы сохранить любую комбинацию выбранных. И вам не нужен неиндексируемый оператор сравнения в ваших процедурах. Предложения WHERE, за исключением самой таблицы перечислений, которая имеет максимум 64 строки. Поиск ваших дистрибьюторов для всех, кто отправляется в Индию и Калифорнию, по-прежнему может использовать сравнение равенства и индекс.
Теперь у вас есть просьба добавить поддержку для территорий США, коды почтовых отправлений вооруженных сил и провинций Канады и сделать это в обратном порядке. Там нет резки списка до < 64 записи, и бизнес действительно хочет избежать необходимости разделять страны старой школы с остальными территориями и подразделениями.
Чем вы занимаетесь?
Приветствуются творческие ответы, но реальная проблема заключается в следующем: существует ли способ заставить одну и ту же побитовую математику, которая работает с 64-битными значениями без знака, работать над подписанными, используя отрицательное пространство, чтобы превысить 64 возможных бита, как в С#, так и в SQL (2008)? Если это имеет значение, флаг моделируется, а не "реальный" флаг, поэтому технически не обязательно, чтобы это работало против перечня CLR с атрибутом [Flags].
Вы не можете превышать 64 бит по 64-битовому значению, даже не используя "отрицательное пространство". Если у вас 64 бит, у вас есть 64 бит. Вы можете использовать Guid, чтобы получить 128 бит, что помешает проблеме на некоторое время, но в конечном итоге вам нужно будет добавить дополнительные поля.
В SQL Server вы можете попробовать десятичное (38,0)
Это дает вам 38 цифр слева от десятичной точки (1E38). В двоичных выражениях это около 126 бит (8.5E37). И его можно манипулировать как число.
Однако одним из вариантов было бы определить, что вы хотите в .NET, и использовать в SQL Server соответствующий тип данных CLR. Таким образом, это может быть согласовано между двумя платформами.
Однако, я бы действительно подумал о том, чтобы отказаться от флагов...
Мой 2c: Ты пытаешься быть умным, и ты причиняешь себе боль. Битфилды и SQL не очень хорошо смешиваются, прежде всего потому, что битовые поля не могут быть правильно проиндексированы, и любой поиск должен будет выполнить полное сканирование. Например. чтобы найти всех реселлеров, отправляющихся в АК, вам нужно отсканировать всю таблицу реселлеров. Также решение не масштабируется до более чем 64 значений (как вы уже обнаружили). Это также плохой выбор хранилища, для этого требуется бит со значением 0 для хранения отрицательной информации (отсутствие связи).
Используйте отдельную таблицу для моделирования отношений "многие-ко-многим" между реселлерами и государствами/территориями/провинциями/странами, к которым они отправляются.