Имитировать 128-разрядное целое число без знака в SQL и C #, используя 64-разрядное значение со знаком? - PullRequest
1 голос
/ 14 ноября 2009

Возьмем такой сценарий: у вас есть несколько перечислений флагов в C #, привязанных (и фактически сгенерированных) к таблицам перечисления в 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, так и в C #, используя побитовую логику, которая позволяет мгновенно гидрировать списки флажков и выбирать списки в Asp.NET, сохраняя при этом только одно 64-разрядное число для хранения любой комбинации выборов. И вам не нужен неиндексируемый оператор сравнения в предложениях WHERE ваших процедур, за исключением самой таблицы enum, которая имеет максимум 64 строки. Поиск в ваших дистрибьюторах всех, кто отправляет товары в Индиану и Калифорнию, все еще может использовать сравнение на равенство и индекс.

Теперь у вас есть запрос на добавление поддержки для территорий США, почтовых кодов вооруженных сил и канадских провинций, а также для обеспечения обратной совместимости. Там нет сокращения списка до <64 записей, и бизнес <em>действительно хочет избежать необходимости отделять государства старой школы от остальных территорий и округов.

Что ты делаешь?

Творческие ответы приветствуются, но реальная проблема здесь заключается в следующем: существует ли способ заставить ту же побитовую математику, которая работает с 64-разрядными значениями без знака, работать со знаковыми, используя отрицательное пространство для превышения 64 возможных битов, в обоих C # и SQL (2008)? Если это имеет значение, флаг имитируется, а не «настоящий» флаг, поэтому технически необязательно для этого работать с перечислением CLR с атрибутом [Flags].

Ответы [ 3 ]

5 голосов
/ 14 ноября 2009

Нельзя превышать 64 бита для 64-битного значения, даже не используя «отрицательный пробел». Если у вас есть 64 бита, у вас есть 64 бита. Вы можете использовать Guid для получения 128 битов, что на некоторое время устранит проблему, но в конечном итоге вам потребуется добавить дополнительные поля.

3 голосов
/ 14 ноября 2009

В SQL Server вы можете попробовать десятичное число (38,0)

Это дает вам 38 цифр слева от десятичной точки (1E38). В двоичном выражении это около 126 бит (8.5E37). И им можно манипулировать как числом.

Однако, одним из вариантов будет определение того, что вы хотите в .NET и использование соответствующего типа данных CLR в SQL Server. Таким образом, это может быть согласованным между двумя платформами.

Однако, я бы действительно подумал об отказе от флагов ...

1 голос
/ 14 ноября 2009

Мой 2с: Ты пытаешься быть умным, и ты причиняешь себе боль. Битовые поля и SQL не очень хорошо сочетаются, прежде всего потому, что битовые поля не могут быть правильно проиндексированы и при любом поиске потребуется выполнить полное сканирование. Например. чтобы найти всех реселлеров, которые отправляют на АК, вам нужно отсканировать всю таблицу реселлеров. Также решение не масштабируется до более чем 64 значений (как вы уже обнаружили). Это также плохой выбор хранилища, для хранения отрицательной информации требуется бит со значением 0 (отсутствие ассоциации).

Используйте отдельную таблицу для моделирования отношения «многие ко многим» между торговыми посредниками и государствами / территориями / провинциями / странами, в которые они отправляют.

...