2012-04-18 51 views
2

是否有一種簡單的方法(或工具)用於查找大型數據庫中從一個表到另一個表的聯接路徑?如何在大型數據庫中查找從一個表到另一個表的聯接路徑

我目前正在研究一個其數據庫超過150個表的項目。下面是我想要做的一些用例。

使用案例:

輸入

  • 選擇表A
  • 選擇表B

輸出

  • 打印出表之間所有可用路徑。
  • 打印出最有效的路線。
+1

這樣的系統將如何工作?基於聲明的參照完整性約束?常用列名稱?那麼如何確定「效率」呢?中間表的數量最少?查詢優化器是否需要參與? – 2012-04-18 13:04:18

+1

如果有一個模型,並且如果數據庫設計得很好,就不需要這種工具,但是您正在倒過來......無論如何,您應該檢查表格的元數據並查找外鍵 – jazzytomato 2012-04-18 13:08:00

+0

I使用超過1000個表的數據庫,並且從不需要像這樣的工具。你爲什麼做這個?特別是對於這樣一個小數據庫。除非你擁有一個設計得非常糟糕的數據庫,否則連接應該是不言而喻的。此外,如果你有一個表格到另一個表格的多條路徑,那麼你也可能有一個糟糕的設計。 – HLGEM 2012-04-18 20:55:49

回答

3

這應該對你有幫助。它會向您顯示您的表格,具有FK,表格和列的列以及FK名稱。

SELECT 
K_Table = FK.TABLE_NAME, 
FK_Column = CU.COLUMN_NAME, 
PK_Table = PK.TABLE_NAME, 
PK_Column = PT.COLUMN_NAME, 
Constraint_Name = C.CONSTRAINT_NAME 
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS C 
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS FK ON C.CONSTRAINT_NAME = FK.CONSTRAINT_NAME 
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS PK ON C.UNIQUE_CONSTRAINT_NAME = PK.CONSTRAINT_NAME 
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU ON C.CONSTRAINT_NAME = CU.CONSTRAINT_NAME 
INNER JOIN (
SELECT i1.TABLE_NAME, i2.COLUMN_NAME 
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS i1 
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE i2 ON i1.CONSTRAINT_NAME = i2.CONSTRAINT_NAME 
WHERE i1.CONSTRAINT_TYPE = 'PRIMARY KEY' 
) PT ON PT.TABLE_NAME = PK.TABLE_NAME 
+0

謝謝,我明天會看看它是否有效。 :) – 2012-04-19 22:11:56

5

因爲我認爲你必須通過數據庫中的一些非常複雜的路徑,你就不能只用一個查詢,甚至幾個查詢做到這一點。我已經完成了它(我繼承了一個項目),並學習了一些有趣的事情。但我必須編寫一個程序來完成它。

我所做的是在他的答案中使用模式視圖迭代參考,並應用一些方法來解決圖論問題(因爲這基本上就是你所得到的,在這裏,表是節點和外鍵鏈接)

基本上,如果我沒有記錯的話(這是幾年前),你從一個表開始,然後通過將其他表的每個引用的名稱放入一個隊列來處理其所有外鍵。檢查自引用和循環(您需要一個散列集或您已處理的表的列表。)然後將下一個表從隊列中彈出並重復。最終,您將會遇到另一張桌子,或者處理了您可以從原始桌子「伸手可及」的每張桌子。

+0

這正是我的想法。看到沒有人知道一個實用程序看起來像我將很快開始另一個開源項目。一旦它處於穩定狀態,我會在我的問題中發佈鏈接。 – 2012-04-19 22:14:54

+0

@TannerWatson其實,我正在考慮用我的工具來做這件事(假設我能找到原始代碼!) – 2012-04-20 00:40:04

+0

更好! :D當您找到原始源時,讓我知道存儲庫位於何處/何處。再次感謝! – 2012-04-20 13:37:15

1

我借用Zen和上述代碼中的代碼並創建此代碼。目前看起來工作得很好。

IF OBJECT_ID('tempdb.dbo.#TableSchema') IS NOT NULL BEGIN DROP TABLE #TableSchema END 
SELECT 
PK_Table = PK.TABLE_NAME, 
PK_Column = PT.COLUMN_NAME, 
K_Table = FK.TABLE_NAME, 
FK_Column = CU.COLUMN_NAME, 
Constraint_Name = C.CONSTRAINT_NAME 
INTO #TableSchema 
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS C 
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS FK ON C.CONSTRAINT_NAME = FK.CONSTRAINT_NAME 
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS PK ON C.UNIQUE_CONSTRAINT_NAME = PK.CONSTRAINT_NAME 
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU ON C.CONSTRAINT_NAME = CU.CONSTRAINT_NAME 
INNER JOIN (
SELECT i1.TABLE_NAME, i2.COLUMN_NAME 
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS i1 
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE i2 ON i1.CONSTRAINT_NAME = i2.CONSTRAINT_NAME 
WHERE i1.CONSTRAINT_TYPE = 'PRIMARY KEY' 
) PT ON PT.TABLE_NAME = PK.TABLE_NAME 


CREATE TABLE [#TablesList] (
c_from NVARCHAR(450), 
c_to NVARCHAR(450), 
PRIMARY KEY (c_from, c_to) 
); 


INSERT INTO [#TablesList] 
SELECT DISTINCT PK_Table,K_Table from #TableSchema 


IF OBJECT_ID('__TablesLink__') IS NOT NULL BEGIN DROP TABLE [__TablesLink__] END 
CREATE TABLE [__TablesLink__] (c_path NVARCHAR(MAX));-- PRIMARY KEY); 


WITH PathCTE 
AS 
(SELECT c_from, c_to, 
     CAST('>' + CAST(c_from AS NVARCHAR(MAX)) + '>' + 
     CAST(c_to AS NVARCHAR(MAX)) + '>' AS NVARCHAR(MAX)) AS c_path 
FROM [#TablesList] AS C1 
UNION ALL 
SELECT C.c_from, C.c_to, 
     CAST(P.c_path + C.c_to + '>' AS NVARCHAR(max)) 
FROM PathCTE AS P 
JOIN [#TablesList] AS C 
    ON P.c_to = C.c_from 
WHERE P.c_path NOT LIKE '%>' + 
        CAST(C.c_from AS NVARCHAR(max)) + 
        '>' + 
        CAST(C.c_to AS NVARCHAR(max)) + 
        '>%') 

INSERT INTO [__TablesLink__] 
SELECT c_path FROM PathCTE; 


SELECT c_path 
FROM [__TablesLink__] 
WHERE c_path LIKE '>' + 'tableA' + '>%' 
    AND c_path LIKE '%>'+ 'tableZ' +'>'; 
+1

它不會爲我返回任何東西 – reddy 2014-11-14 09:55:31

相關問題