2011-11-02 4 views
1

Мне нужно извлечь данные из сторонней системы (я не влияю на ее дизайн). База данных SQL Server 2005 использует растровые изображения для хранения пользовательских привилегий. Он имеет пять полей INT, дающих максимум 5 * 32 = 160 привилегий. Он хранит несколько типов привилегий и повторно использует растровые изображения для каждого типа. Таким образом, в общей сложности есть 6 полей, которые управляют привилегиями. Каждая привилегия может быть назначена определенному элементу определенного типа.Как вставить несколько строк в таблицу из растрового изображения

Примером типа является «таблица», поэтому элементы в этом контексте будут именами таблиц.

Привилегия таблица выглядит следующим образом:

ID | PRIVTYPE | USERNAME | ITEMNAME | BITMAP1 | BITMAP2 | BITMAP3 | BITMAP4 | BITMAP5 

Например

123 | Table | Joe | Customers | 0x408 | 0x1 | 0x5c | 0x1000 | 0x0 

Другая таблица содержит привилегии, представленные каждым битом. Это выглядит следующим образом:

PRIVTYPE | BITMAP_ID | BITVALUE | PRIVILEGE_NAME 

Например, запись, относящаяся к вышеуказанным растровым изображениям будет:

Table | 1 |0x8 | View 
Table | 1 |0x400 | Edit 
Table | 2 |0x1 | Report 
Table | 3 |0x4 | View Address Data 
Table | 3 |0x8 | View Order Data 
Table | 3 |0x10 | View Payment Data 
Table | 3 |0x40 | View System Data 
Table | 4 |0x1000| View Hidden Fields 

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

USERNAME | ITEMNAME |PRIVILEGE_NAME 
Joe | Table | Customers | View 
Joe | Table | Customers | Edit 
Joe | Table | Customers | Report 
Joe | Table | Customers | view Address Data 
Joe | Table | Customers | view Order Data 
Joe | Table | Customers | view Payment Data 
Joe | Table | Customers | view System Data 
Joe | Table | Customers | view Hidden Fields 

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

Я искал ответы о разбиении таблиц на несколько строк. Я рассматривал различные объединения и свопы, но я не могу найти то, что будет делать то, что мне нужно. Возможно ли это? Любое руководство оценивается ...

ответ

1

Вы можете UNPIVOT первой таблицы (называемую @UserPrivileges ниже) и присоединиться к его второму (@Privileges) по типу привилегий , идентификатор растрового изображения и результат побитового И между растровым изображением в первой таблице и BITVALUE во второй таблице.

Ниже приводится моя реализация.

Установка:

DECLARE @UserPrivileges TABLE (
    ID int, 
    PRIVTYPE varchar(50), 
    USERNAME varchar(50), 
    ITEMNAME varchar(50), 
    BITMAP1 int, 
    BITMAP2 int, 
    BITMAP3 int, 
    BITMAP4 int, 
    BITMAP5 int 
); 
INSERT INTO @UserPrivileges 
    (ID, PRIVTYPE, USERNAME, ITEMNAME, BITMAP1, BITMAP2, BITMAP3, BITMAP4, BITMAP5) 
SELECT 123, 'Table', 'Joe', 'Customers', 0x408, 0x1, 0x5c, 0x1000, 0x0 
; 

DECLARE @Privileges TABLE (
    PRIVTYPE varchar(50), 
    BITMAP_ID int, 
    BITVALUE int, 
    PRIVILEGE_NAME varchar(50) 
); 
INSERT INTO @Privileges (PRIVTYPE, BITMAP_ID, BITVALUE, PRIVILEGE_NAME) 
SELECT 'Table', 1, 0x8 , 'View    ' UNION ALL 
SELECT 'Table', 1, 0x400 , 'Edit    ' UNION ALL 
SELECT 'Table', 2, 0x1 , 'Report   ' UNION ALL 
SELECT 'Table', 3, 0x4 , 'View Address Data ' UNION ALL 
SELECT 'Table', 3, 0x8 , 'View Order Data ' UNION ALL 
SELECT 'Table', 3, 0x10 , 'View Payment Data ' UNION ALL 
SELECT 'Table', 3, 0x40 , 'View System Data ' UNION ALL 
SELECT 'Table', 4, 0x1000, 'View Hidden Fields' 
; 

Запрос:

WITH unpivoted AS (
    SELECT 
    ID, 
    PRIVTYPE, 
    USERNAME, 
    ITEMNAME, 
    RIGHT(BITMAP_ID, 1) AS BITMAP_ID, -- OR: STUFF(BITMAP_ID, 1, 6, '') 
             -- OR: SUBSTRING(BITMAP_ID, 7, 999) 
             -- OR: REPLACE(BITMAP_ID, 'BITMAP', '') 
    BITMAP_VAL 
    FROM UserPrivileges 
    UNPIVOT (
    BITMAP_VAL FOR BITMAP_ID IN (
     BITMAP1, BITMAP2, BITMAP3, BITMAP4, BITMAP5 
    ) 
) u 
), 
joined AS (
    SELECT 
    u.USERNAME, 
    u.PRIVTYPE, 
    u.ITEMNAME, 
    p.PRIVILEGE_NAME 
    FROM unpivoted u 
    INNER JOIN Privileges p 
     ON u.PRIVTYPE = p.PRIVTYPE 
     AND u.BITMAP_ID = p.BITMAP_ID 
     AND u.BITMAP_VAL & p.BITVALUE <> 0 
) 
SELECT * FROM joined 

Результаты:

 
USERNAME PRIVTYPE ITEMNAME PRIVILEGE_NAME 
-------- -------- --------- ------------------ 
Joe  Table  Customers View    
Joe  Table  Customers Edit    
Joe  Table  Customers Report    
Joe  Table  Customers View Address Data 
Joe  Table  Customers View Order Data 
Joe  Table  Customers View Payment Data 
Joe  Table  Customers View System Data 
Joe  Table  Customers View Hidden Fields 
+0

Это красиво и отлично. Спасибо!!! – starfry

0

Если это задача ONE OFF или что-то, что будет работать только RARELY, то CURSORS!

В противном случае, просто сделать 6 различных операторов выбора, которые в профсоюзе в вашей вставке:

INSERT INTO FOO (myName, myValue) 
SELECT myName, myCol1 
    From BAR 
UNION 
SELECT myName, myCol2 
    FROM BAR 
UNION 
SELECT myName, myCol3 
    FROM BAR 
+0

Я пытался вещи вокруг союзов, но данные "myCol1/2/3" в растровое изображение в том же поле. Я не уверен, что лучший способ - извлечь их, чтобы я мог сделать такой союз.Я пробовал это, чтобы создать новый столбец, представляющий один бит, но он не масштабируется, когда есть много бит:/* Табличные привилегии */ , CASE p. [PRIVTYPE] WHEN 0x00000014 - Таблица THEN CAST (стр. [BITMAP1] & 0x8 as INT)/0x8 ELSE 0 END as PRIVILEGE_VIEW – starfry

+0

А, извините, я неправильно понял. –

Смежные вопросы