2011-11-02 3 views
1

타사 시스템에서 데이터를 추출해야합니다 (설계에 영향을주지 않습니다). SQL Server 2005 데이터베이스는 비트 맵을 사용하여 사용자 권한을 저장합니다. 최대 5 * 32 = 160 특권을 제공하는 5 개의 INT 필드가 있습니다. 그것은 많은 유형의 권한을 저장하고 각 유형에 대해 비트 맵을 다시 사용합니다. 그래서 전체적으로 권한을 운전하는 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 비트가 설정된 권한 테이블의 단일 행은 3 개의 행을 반환합니다.

테이블을 여러 행으로 나누는 것에 대한 답변을 검색했습니다. 다양한 조인과 피벗을 살펴 봤지만 필요한 것을 할 수있는 것을 찾을 수 없습니다. 위가 가능합니까? 어떤 조언도 감사합니다 ...

답변

1

당신은 (아래 @UserPrivileges라고 함) 첫 번째 테이블을 피벗 해제 및 권한 유형에 대한 두 번째 (@Privileges)에 참여할 수 :

그렇지 않으면, 당신의 삽입에 노조되는 6 별개의 select 문을 , 비트 맵 ID 및 첫 번째 테이블의 비트 맵과 두 번째 테이블의 BITVALUE 사이의 비트 AND 결과입니다.

다음은 구현 한 것입니다.

설정 :

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

이것이 ON RIGHT OFF 작업이거나 RARELY 만 실행되는 것이라면 CURSORS!

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"은에 같은 필드의 비트 맵 나는 그러한 조합을 추출 할 수있는 가장 좋은 방법이 무엇인지 확신 할 수 없다.나는 이런 종류의 비트를 나타내는 새로운 컬럼을 만들려고했으나 많은 비트가있을 때 스케일되지 않는다./* 테이블 권한 */ , 사례 p. [PRIVTYPE] WHEN 0x00000014 - 테이블 그 다음에 CAST (P [BITMAP1] & 0x8 INT)/0x8 ELSE 0 END as PRIVILEGE_VIEW – starfry

+0

아, 미안하지만, 나는 오해하고 있습니다. –