簡體   English   中英

SQL Server,自引用外復合鍵

[英]SQL Server, self referencing foreign compound key

我有一個表,其中包含列task_id(pk),client_id,parent_task_id,標題。 換句話說,任務歸客戶端所有,某些任務具有子任務。

例如,客戶端7可以具有任務“洗車”,以及子任務“真空地毯”和“擦拭儀表板”。

我想要一個約束,以便任務及其子項始終由同一客戶端擁有。

通過一些實驗,為此,我創建了一個自引用外鍵(client_id,parent_task_id)引用(client_id,task_id)。 最初,我收到一個錯誤(被引用表中沒有與外鍵中的引用列列表匹配的主鍵或候選鍵。)因此,我為task_id,client_id列添加了唯一鍵。 現在看來可行。

我想知道這是否是實施此約束的最佳解決方案(或至少是合理的解決方案)。 任何想法將不勝感激。 非常感謝!

“父”記錄不需要[parent_task_id]

TASK ID | CLIENT ID | PARENT TASK ID | TITLE
1       | 7         | NULL           | wash the car

(要查找所有父記錄, SELECT * FROM TABLE WHERE [parent_task_id] is null

“子”記錄將需要一個[parent_task_id],但不需要一個[client_id](因為正如您所規定的,子與父具有相同的客戶端)。

TASK ID | CLIENT ID | PARENT TASK ID | TITLE
2       | NULL      | 1              | vacuum carpent
3       | NULL      | 1              | wipe dashboard

這樣,您的自引用外鍵就是您所需要的全部約束。 不需要與子記錄上的[client_id]有關的約束/規則,因為子記錄上的所有[client_id]值都將被忽略,有利於父記錄的[client_id]。

例如,如果您想知道子記錄的[client_id]是什么:

SELECT
   c.task_id,
   p.client_id,
   c.title
FROM
   table p --parent
   INNER JOIN table c --child
   ON p.task_id = c.parent_task_id

更新 (如何查詢孫代的客戶端ID)

--Create and populate your table (using a table var in this sample)
DECLARE @table table (task_id int, client_id int, parent_task_id int, title varchar(50))
INSERT INTO @table VALUES (1,7,NULL,'wash the car')
INSERT INTO @table VALUES (2,NULL,1,'vacuum carpet')
INSERT INTO @table VALUES (3,NULL,1,'wipe dashboard')
INSERT INTO @table VALUES (4,NULL,2,'Step 1: plug-in the vacuum')
INSERT INTO @table VALUES (5,NULL,2,'Step 2: turn-on the vacuum')
INSERT INTO @table VALUES (6,NULL,2,'Step 3: use the vacuum')
INSERT INTO @table VALUES (7,NULL,2,'Step 4: turn-off the vacuum')
INSERT INTO @table VALUES (8,NULL,2,'Step 5: empty the vacuum')
INSERT INTO @table VALUES (9,NULL,2,'Step 6: put-away the vacuum')
INSERT INTO @table VALUES (10,NULL,3,'Step 1: spray cleaner on the rag')
INSERT INTO @table VALUES (11,NULL,3,'Step 2: use the rag')
INSERT INTO @table VALUES (12,NULL,3,'Step 3: put-away the cleaner')
INSERT INTO @table VALUES (13,NULL,3,'Step 4: toss the rag in the laundry bin')

--Determine which grandchild you want the client_id for
DECLARE @task_id int
SET @task_id = 8 -- grandchild's ID to use to find client_id

--Create your CTE (this is the recursive part)
;WITH myList (task_id, client_id, parent_task_id, title)
AS
(
    SELECT a.task_id, a.client_id, a.parent_task_id, a.title
    FROM @table a
    WHERE a.task_id = @task_id
    UNION ALL
    SELECT a.task_id, a.client_id, a.parent_task_id, a.title
    FROM @table a
    INNER JOIN myList m
    ON a.task_id = m.parent_task_id
)

--Query your CTE
SELECT task_id, client_id, title FROM myList WHERE client_id is not null

在此示例中,我使用了格蘭孩子的task_id(8-'清空真空')來找到它的最高級別的父對象,其中包含client_id。

如果要查看每個父母,父母的父母等等,直到最后一個父母的記錄,都可以從最后一步中刪除WHERE子句。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM