如何从位图向表中插入多行

时间:2011-11-02 14:56:35

标签: sql-server bitmapdata

我需要从第三方系统中提取数据(我对其设计没有任何影响)。它是一个SQL Server 2005数据库使用位图来存储用户权限。它有五个INT字段,最多可提供5 * 32 = 160个权限。它存储许多类型的权限,并重新使用每种类型的位图。总共有6个字段可以驱动特权。可以将每个权限分配给给定类型的特定项目。

类型的一个例子是“table”,因此该上下文中的项目将是表名。

特权表如下所示:

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 个答案:

答案 0 :(得分:1)

您可以取消第一个表(下面称为@UserPrivileges)并将其连接到第二个表(@Privileges)上的特权类型,位图ID以及第一个位图之间的按位AND结果表格和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

答案 1 :(得分:0)

如果这是一个OFF OFF任务或者只能运行RARELY的东西,那么CURSORS!

否则,只需在插入中执行6个不同的select语句:

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