Могу ли я выполнить побитовое и на набор чисел в Sql Server? - PullRequest
3 голосов
/ 05 мая 2011

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

Конечно, я легко могу сделать это в своем коде, но я бы предпочел сделать это в базе данных, поскольку могут быть тысячи элементов, для которых я запрашиваю права.

Я бы предпочел решение на основе множеств, а не курсор.

Обратите внимание, что у меня нет контроля над схемой.

Ответы [ 4 ]

4 голосов
/ 05 мая 2011

Решение, основанное на множестве, возможно, если все значения, которые вы хотите побитовые или однобитовые значения: Выполнение побитовой суммы

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

DECLARE @BitSum INT
SET @BitSum = 0
SELECT @BitSum = @BitSum | BitValue
FROM (
    SELECT 1 AS BitValue
    UNION SELECT 7
    UNION SELECT 16
) AS SampleValues
SELECT @BitSum

Редактировать: Уго Корнелис довольно подробно отвечает на вопрос в этом другом посте: http://www.eggheadcafe.com/software/aspnet/33139293/bitwise-aggregate-function.aspx

3 голосов
/ 05 мая 2011

SQL Server изначально поддерживает битовую математику .Например, & является побитовым И:

select  10 & 3
-->
2

Записано:

10 = 1010
3  = 0011
&  = bitwise and
2  = 0010

Вы можете использовать это в запросе, как и любой другой оператор:

select  ss.SecurityBits & cs.CustomerBits
from    SecuritySettings ss
join    CustomerSettings cs
on      ss.ID = cs.SecuritySettingsID
0 голосов
/ 11 февраля 2015

Вы можете создавать агрегатные функции SQL Server в .NET, которые затем можно будет встроить в встроенный SQL-сервер. Я думаю, что для этого требуется минимум SQL Server 2005 и Visual Studio 2010. Я сделал один с использованием Visual Studio 2013 Community Edition (бесплатно даже для коммерческого использования) для использования с .NET 2 и SQL Server 2005.

См. Статью MSDN: https://msdn.microsoft.com/en-us/library/91e6taax(v=vs.90).aspx

Сначала вам нужно включить функцию CLR на сервере SQL: https://msdn.microsoft.com/en-us/library/ms131048.aspx

sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'clr enabled', 1;
GO
RECONFIGURE;
GO
  1. Создание SQL Server -> Проект базы данных SQL Server
  2. Щелкните правой кнопкой мыши новый проект и выберите Свойства
  3. Настройка целевой версии SQL Server в разделе «Параметры проекта»
  4. Настройка целевого языка CLR в SQL CLR (например, VB)
  5. Щелкните правой кнопкой мыши новый проект и выберите Добавить -> Новый элемент ...
  6. Когда появится диалоговое окно, выберите SQL Server -> SQL CLR VB -> SQL CLR VB Aggregate

Теперь вы можете написать свой побитовый код в VB:

Imports System
Imports System.Data
Imports System.Data.SqlClient
Imports System.Data.SqlTypes
Imports Microsoft.SqlServer.Server


<Serializable()> _
<Microsoft.SqlServer.Server.SqlUserDefinedAggregate(Format.Native)> _
Public Structure AggregateBitwiseOR

    Private CurrentAggregate As SqlTypes.SqlInt32

    Public Sub Init()
        CurrentAggregate = 0
    End Sub

    Public Sub Accumulate(ByVal value As SqlTypes.SqlInt32)
        'Perform Bitwise OR against aggregate memory
        CurrentAggregate = CurrentAggregate OR value
    End Sub

    Public Sub Merge(ByVal value as AggregateBitwiseOR)
        Accumulate(value.Terminate())
    End Sub

    Public Function Terminate() As SqlInt32
        Return CurrentAggregate
    End Function

End Structure

Теперь разверните его: https://msdn.microsoft.com/en-us/library/dahcx0ww(v=vs.90).aspx

  1. Создайте проект с помощью строки меню: Build -> Build ProjectName (если сборка завершится неудачно с ошибкой 04018, загрузите новую версию инструментов данных @ http://msdn.microsoft.com/en-US/data/hh297027 или перейдите в строку меню: Tools - > Расширения и обновления, затем в разделе обновлений выберите обновление для обновления Microsoft SQL Server для баз данных)
  2. Скопируйте скомпилированную DLL в C: \ Program Files \ Microsoft SQL Server \ MSSQL.1 \ MSSQL \ Binn и в C: \
  3. Зарегистрировать DLL:

    СОЗДАТЬ СБОРКУ [CLRTools] ИЗ ‘c: CLRTools.dll’ С PERMISSION_SET = SAFE

  4. Создание агрегата в SQL:

    CREATE AGGREGATE [dbo]. [AggregateBitwiseOR] (@ значение INT) ВОЗВРАЩАЕТ INT ВНЕШНЕЕ ИМЯ [CLRTools]. [CLRTools.AggregateBitwiseOR];

Если вы получили ошибку «Неверный синтаксис рядом с« EXTERNAL »», измените уровень совместимости базы данных, используя следующие команды:

Для SQL Server 2005: EXEC sp_dbcmptlevel 'DatabaseName', 90

Для SQL Server 2008: EXEC sp_dbcmptlevel 'DatabaseName', 100

  1. Проверьте ваш код:

    ВЫБРАТЬ dbo.AggregateBitwiseOR (Foo) КАК Foo ИЗ БРАКА

Мне показалась эта статья полезной: http://www.codeproject.com/Articles/37377/SQL-Server-CLR-Functions

0 голосов
/ 05 мая 2011

Вы можете использовать рекурсивный CTE для выполнения побитового И.

DECLARE @table TABLE (UserID int, AccessRights int)
INSERT @table (UserID, AccessRights) VALUES (2, 0x3)
INSERT @table (UserID, AccessRights) VALUES (2, 0x2)
INSERT @table (UserID, AccessRights) VALUES (2, 0x7)

;WITH Ranked AS
(
    SELECT UserID, AccessRights
    , DENSE_RANK() OVER (PARTITION BY UserID ORDER BY AccessRights) RankNum
    , CASE WHEN DENSE_RANK()
                OVER (PARTITION BY UserID ORDER BY AccessRights DESC) = 1 
          THEN 1 
          ELSE 0 
      END IsLastItem
    FROM @table
),
RecursiveCTE AS
(
    SELECT R.UserID, RankNum, IsLastItem, R.AccessRights
    FROM Ranked R
    WHERE R.RankNum = 1

    UNION ALL

    SELECT R.UserID, R.RankNum, R.IsLastItem
            , R.AccessRights & RecursiveCTE.AccessRights
    FROM RecursiveCTE
    INNER JOIN Ranked R ON R.UserID = RecursiveCTE.UserID
    WHERE R.RankNum = RecursiveCTE.RankNum + 1
)
SELECT UserID, AccessRights
FROM RecursiveCTE
WHERE IsLastItem = 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...