2014-11-02 2 views
2

CTE를 사용하여 db의 테이블에 대한 감사 레코드를 검색합니다. 고객의 테이블에 대한CTE 곱한 레코드가 반환되었습니다.

CREATE TABLE [audit] 
(
    [id] [int] IDENTITY(1,1) NOT NULL, 
    [user_name] [varchar](50) NULL, 
    [date_time] [datetime] NULL DEFAULT (getdate()), 
    [parent_table] [varchar](50) NULL, 
    [parent_id] [int] NULL, 
    [table_name] [varchar](50) NULL, 
    [table_id] [int] NULL, 
    [action] [varchar](1) NULL 
) 

엔트리는 각각 table_nametable_id로 설정 parent_tableparent_id 열이됩니다

CREATE TABLE [customers] 
(
    [id] [int] IDENTITY(1,1) NOT NULL, 
    [name] [varchar](50) NULL 
); 

CREATE TABLE [customers_orders] 
(
    [id] [int] IDENTITY(1,1) NOT NULL, 
    [customer_id] [int] NOT NULL, 
    [date_time] [datetime] NULL DEFAULT (getdate()) 
); 

CREATE TABLE [customers_orders_lines] 
(
    [id] [int] IDENTITY(1,1) NOT NULL, 
    [order_id] [int] NOT NULL, 
    [quantity] [int] NULL, 
); 

내 감사 테이블이있다 : 예를 들어, 나는 다음과 같은 테이블이있다. 작업의 삽입, 업데이트 또는 삭제에 대한 I, U, D 값을 가질 수 있습니다. 나는 고객이 자신의 주문 및 주문 행을 추가, 그래서

DECLARE @tablename varchar(100) 
SET @tablename = 'customers' 

DECLARE @tableid int 
SET @tableid = 100 

;WITH cteAudit AS 
(
    SELECT id, [user_name], date_time, table_name, table_id, action, 1 AS audit_level 
    FROM audit 
    WHERE 
     table_name = @tablename AND 
     table_id = @tableid 
    UNION ALL 
    SELECT a.id, a.[user_name], a.date_time, a.table_name, a.table_id, a.action, cteAudit.audit_level + 1 
    FROM audit a 
     INNER JOIN cteAudit 
      ON a.parent_id = cteAudit.table_id 
      AND a.parent_table = cteAudit.table_name 
    WHERE 
     a.parent_table <> a.table_name AND 
     a.parent_id <> a.table_id 
) 
SELECT * FROM cteAudit ORDER BY date_time DESC, id_no, audit_level 

:

내 CTE이있다. 행동은 모든 기록에 대한 것입니다. 감사 cte 레코드를 올바르게 검색합니다. 작업 U가있는 고객에 대해 단 하나의 감사 레코드 만 추가하면 반환되는 레코드는 두 배가됩니다.

cte는 고객 및 관련 테이블에 대한 모든 감사 레코드를 반환해야합니다.

SQLFiddle에 문제가 있습니다.

여기에 뭔가가 있습니까?

+0

이 cte와 관련된 다른 테이블 구조를 공유 할 수 있습니까? –

답변

1

자, 재귀 적 CTE가 있습니다. seems to work as designed입니다. 앵커 행을 가져온 후, 업데이트 된 행에 연결된 모든 하위 노드로 다시 순환합니다.

SELECT * FROM cteAudit 
WHERE AUDIT_LEVEL = 1 
ORDER BY date_time DESC, audit_level 

SqlFiddle here

편집
을 : 당신은 그냥 audit_level 필터링, 자녀가없는 재귀 단지 지정된 테이블을 제한해야하는 경우

은 CTE는 이미 audit_level을 통해 깊이를 추적하기 때문에 정보를 감사하는 방식의 문제는 동일한에 다시 연결되는 audit rows (예 : 삽입 및 업데이트)참조하는 버전의 컨텍스트없이 라이브 테이블 PK를 통해 테이블 ​​참조 데이터.

의미 언제든지 parent update을 추가하면 (고객에게 새로운 'U'를 추가 한 것처럼) 재귀 CTE는 '언제'와 관계없이 모든 연결된 자식 감사 레코드를 다시 가져옵니다 (크로스 결합). 변경됨 - 위와 같이 감사 모델과 CTE의 설계/의도가 나타납니다. 데이터 모델의 현재 화신에서는 부모/자식/손자 그래프의 실제 버전을 다시 작성할 수 없으므로 수정되었습니다. version or timestamp를 포함

집계 루트 (customer와 자식 customers_orders와 손자 customers_orders_lines) 실제로 변화의 시간에 수정 된 데이터 만의 당기하는 CTE를 제한하려면, 당신은 당신의 감사 패턴을 변경해야합니다 변경된 데이터의

이 버전은 새로운 분야로 감사 테이블에 포함해야하고,이 버전 (table_name, table_idrecord_version 즉) 열팽창 계수의 조인 키에 포함 할 필요가있다.

+0

SqlFiddle 예제로 내 질문을 편집했습니다. 그것은 문제를 보여줍니다. –

+0

10 년 이상 된 감사 테이블이 있기 때문에 버전을 추가 할 수 없습니다. 감사 테이블에는 이미 date_time 열이 있지만 레코드가 삽입 될 때 초/밀리 초에 약간의 차이가있을 수 있기 때문에 작동하는지 알 수는 없습니다. –

0

잘 모르겠지만이 경우에는 UNION ALL 연산자가 필요하지 않다고 생각합니다. UNION ALL 운영자가 중복을 제거하지 않음 Union은 (는) 쿼리에서 허용되지 않습니다.

DECLARE @tablename varchar(100); 
DECLARE @tableid int; 

SELECT @tablename = 'customers', @tableid = 100; 

;WITH cteAudit AS 
(
    SELECT id, [user_name], date_time, table_name, table_id, action, 1 AS audit_level 
    FROM audit  
) 
SELECT * FROM cteAudit 
ORDER BY date_time DESC, audit_level; 

하지만이 방법이 귀하의 응용 프로그램에 대한 감사 데이터를 저장하는 최선의 표준 방법은 아니라고 생각합니다.

가장 좋은 방법은 당신이 수행 한 마지막 삽입의 정보를 저장하는 하나 개 테이블을 얻을 것이다 Triggers to Audit your data.

On Insert of new Row : 

을 사용하는 것입니다. 삽입 된 테이블 &에서 값을 가져 와서 감사 테이블에 삽입하면됩니다.

On DElete of new Row : 

어떤 하나 테이블을 삭제에 다음 액세스를 얻을 것이다 테이블에서 모든 레코드를 삭제합니다. 이 테이블은 마지막으로 삭제 된 레코드의 정보를 저장합니다.

On Update of table : 

이 경우 두 inserted & deleted 테이블에 대한 액세스를 얻을 것이다. updatation 삽입 된 표는 그 갱신

후 새로운 데이터로 구성하기 전에

삭제 된 테이블이 모든 의심 & 트리거에 대한 기본 개념 & 감사 데이터를 삭제하는 가장 좋은 링크입니다 오래된 데이터로 구성되어 있습니다.

Click Here For Triggers Information

+0

감사 테이블이 그에 따라 업데이트되도록 CLR 트리거를 이미 사용하고 있습니다. 이 cte는 감사 레코드를 검색하는 것입니다. –

+0

알았어 위의 쿼리를 확인 했습니까? –