Как вставить несколько строк в таблицу из растрового изображения - PullRequest
1 голос
/ 02 ноября 2011

Мне нужно извлечь данные из сторонней системы (я не имею никакого влияния на ее дизайн). Это база данных 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

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

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

Ответы [ 2 ]

1 голос
/ 03 ноября 2011

Вы можете отменить поворот первой таблицы (называемой @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 голосов
/ 02 ноября 2011

Если это ОДНА ВЫКЛ задача или что-то, что будет выполняться только РЕАЛЬНО, то CURSORS!

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

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