0

的有3種情況數據庫設計 - 保持記錄鏈接條目

1) Basic 
Sender ---> Receiver 

2) Parallel 
Sender ----> Receiver1 
     ----> ReceiverN 

3) Chained 
Sender ----> Primary Receiver -----> Secondary Receiver1 
           -----> Secondary ReceiverN 

對於1)基本和2)Parallels的,你可能會設計出這樣

Account 
-Id (PK) 
-UserId (FK) 
-Name 
-Description 
-etc 

Entry 
-Id (PK) 
-SenderAccountId (FK) 
-ReceiverAccountId (FK) 

你的表現在會怎樣你設計數據庫來記錄「連鎖」條目?

+0

這條鏈最多可以有多少「鏈接」? – NullUserException

+0

您好nulluserexception,鏈接,一個發送者只能發送到1個主要接收器,然後這個主要接收器可以發送到最多6個次要接收器。輔助接收器不能發送,因此最多2個鏈。 – 001

回答

1

您可以將很多添加到帳戶(ID-PK,用戶ID-FK,名稱,描述,...)和Entry(ID-PK)表之間的多對多關係: EntryAccount(ENTRYID & ACCOUNTID-PK,EntryAccountType ) 其中EntryAccountType字段可以具有以下值之一{S =發送者,R =接收者,P =主要接收者,N =次要接收者}。

爲EntryAccount表的INSERT語句將是:

--Basic 
INSERT EntryAccount (EntryId,AccountId,EntryAccountType) 
VALUES (...,...,'S') 
INSERT EntryAccount (EntryId,AccountId,EntryAccountType) 
VALUES (...,...,'R') 

--Parallel 
INSERT EntryAccount (EntryId,AccountId,EntryAccountType) 
VALUES (...,...,'S') 
INSERT EntryAccount (EntryId,AccountId,EntryAccountType) 
VALUES (...,...,'R') 
INSERT EntryAccount (EntryId,AccountId,EntryAccountType) 
VALUES (...,...,'R') 
INSERT EntryAccount (EntryId,AccountId,EntryAccountType) 
VALUES (...,...,'R') 

--Chained 
INSERT EntryAccount (EntryId,AccountId,EntryAccountType) 
VALUES (...,...,'S') 
INSERT EntryAccount (EntryId,AccountId,EntryAccountType) 
VALUES (...,...,'P') 
INSERT EntryAccount (EntryId,AccountId,EntryAccountType) 
VALUES (...,...,'N') 
INSERT EntryAccount (EntryId,AccountId,EntryAccountType) 
VALUES (...,...,'N') 
INSERT EntryAccount (EntryId,AccountId,EntryAccountType) 
VALUES (...,...,'N') 

然後,爲了執行一些業務規則(一個發送器S,一個主接收機-P和許多[二次]接收機-R/N)您可以在EntryAccount表上創建唯一的過濾索引(SQL Server 2008):IUF_EntryAccount_EntryId_EntryAccountType(鍵> EntryId & EntryAccountType,filter> EntryAccountType IN('S','P'))。此外,此索引適用於查詢優化。 但是,這個指標是不夠的,因爲你可以有「不一致」輸入業務對象這樣的:

Entry(1001) 
EntryAccoount(1001,...,'S') without EntryAccoount(1001,...,'R') 
or 
EntryAccoount(1001,...,'R') without EntryAccoount(1001,...,'S') 
, etc. 

要解決此問題,您需要一個AFTER觸發器INSERT,UPDATE,DELETE上EntryAccount表:

CREATE TRIGGER ... 
    AFTER INSERT, UPDATE, DELETE 
    ... 
    DECLARE @Results TABLE 
    (
    EntryId INT PRIMARY KEY 
    ,SendersCount INT NOT NULL DEFAULT O 
    ,ReceiversCount INT NOT NULL DEFAULT O 
    ,PrimaryReceiversCount INT NOT NULL DEFAULT O 
    ,SecondaryReceiversCount INT NOT NULL DEFAULT O 
    ); 
    INSERT @Results(EntryId) 
    SELECT EntryId 
    FROM inserted 
    UNION --no duplicates 
    SELECT EntryId 
    FROM deleted; 

    --Count senders 
    UPDATE @Results 
    SET SendersCount = q.Num 
    FROM @Results r 
    JOIN 
    (
    SELECT ea.EntryId, COUNT(*) Num 
    FROM EntryAccount ea 
    JOIN @Results i ON ea.EntryId = i.EntryId 
    WHERE ea.EntryAccountType = 'S' 
    GROUP BY ea.EntryId 
    ) q ON r.EntryId = q.EntryId; 

    -Count [standard-R] receivers 
    UPDATE @Results 
    SET ReceiversCount = q.Num 
    FROM @Results r 
    JOIN 
    (
    SELECT ea.EntryId, COUNT(*) Num 
    FROM EntryAccount ea 
    JOIN @Results i ON ea.EntryId = i.EntryId 
    WHERE ea.EntryAccountType = 'R' 
    GROUP BY ea.EntryId 
    ) q ON r.EntryId = q.EntryId; 

    --Count primary-P receivers 
    UPDATE @Results 
    SET PrimaryReceiversCount = q.Num 
    FROM @Results r 
    JOIN 
    (
    SELECT ea.EntryId, COUNT(*) Num 
    FROM EntryAccount ea 
    JOIN @Results i ON ea.EntryId = i.EntryId 
    WHERE ea.EntryAccountType = 'P' 
    GROUP BY ea.EntryId 
    ) q ON r.EntryId = q.EntryId; 


    --Count secondary-N receivers 
    UPDATE @Results 
    SET SecondaryReceiversCount = q.Num 
    FROM @Results r 
    JOIN 
    (
    SELECT ea.EntryId, COUNT(*) Num 
    FROM EntryAccount ea 
    JOIN @Results i ON ea.EntryId = i.EntryId 
    WHERE ea.EntryAccountType = 'N' 
    GROUP BY ea.EntryId 
    ) q ON r.EntryId = q.EntryId; 

    --Final validation 
    IF EXISTS 
    (
    SELECT * 
    FROM @Results r 
    WHERE NOT(r.SendersCount=1 AND r.ReceiversCount>=1 AND r.PrimaryReceiver=0 AND r.SecondaryReceiversCount=0 
    OR r.SenderCount=1 AND r.ReceiversCount=0 AND r.PrimaryReceiver=1 AND r.SecondaryReceiversCount >=1 
    OR r.SenderCount=0 AND r.ReceiversCount=0 AND r.PrimaryReceiver=0 AND r.SecondaryReceiversCount=0 
) 
    ) 
    ROLLBACK; 

如果您沒有SQL Server 2008(R1/R2),則無法創建篩選索引,但只能依靠觸發器。

PS:我還沒有測試過這個解決方案。

0

將parent_record_id添加到Entry表中。對於鏈中的第一步,它將爲空。第二,它將包含原始記錄的ID。第三步它將包含相關第二步的ID等等。

我在評論中看到,您所說的最多可以有2個鏈接深度,因此您可能會想出另一種解決方法,但這種方法是通用的,並且適用於多種場景,並且如果您的需求變爲3級或更多級別的鏈接,則繼續工作。

然後,您可以查找CONNECT BY SQL語法來對此類型的數據結構執行高效的層次結構查詢。

+0

那麼「Entry」表有多少屬性呢? – 001

+0

可能是Id,parent_id,sender_account_id,receiver_account_id –