簡體   English   中英

根據表中的值運行動態 sql,然后將它們附加到同一結果集

[英]Running dynamic sql based on values in a table, and then appending them to the same result set

我有一個需要查詢的名為“customData”的表。
該表包含三列(相關列)。 一個包含一個字段,另一個包含一個表名,第三個包含外部表中記錄的 id。 目標是獲取這些值,在該外部表中查找該字段的值,並將 append 作為結果集中的列。 這甚至可能嗎? 如果尚未讀取表格,我無法使用表格中的數據構建動態 sql 的方法。

我正在嘗試通過將其轉換為存儲過程來修復當前在未映射字段中發生的異常緩慢的查找。

ID  Value  foreignTable ftIndex ftRow   customField 
1  "yes"  "tblDriver"    2001    "Name"  "Licensed?"  
2  "no"   "tblDriver"    2002    "Name"  "Licensed?"
3  "7"    "tblOrigin"    1131    "Name"  "tank count"

預期 output:

1 "licensed" "yes" 'Darryl Coffman'
2 "licensed" "no"  'Cash Rainer'
3 "tank count" "7"   'texas field'

盡管這並沒有具體回答這個問題,但我想將我的上述評論總結為一個答案,以說明為什么您的設計存在如此大的缺陷,以及為什么它不起作用; 以及為什么你需要修復它。 請注意,我們沒有足夠的信息來建議修復是什么,除了 state 您需要花費大量時間將設計修復為標准化方法。

首先,實現最終目標的唯一方法是使用動態 SQL。 如果您只在單個列值之后,那么您實際上會“好”,因為您可以編寫如下語句:

SELECT DT.ID,
       DT.CustomField,
       DT.[Value],
       D.[Name]
FROM dbo.DenormalisedTable DT
     JOIN dbo.tblDriver D ON DT.ForeignTable = N'tblDriver'
                         AND DT.ftIndex = D.ID
WHERE DT.ftRow = N'Name';

不幸的是,您的 go 到 state 並非如此,這意味着您需要如下查詢(對於我們擁有的 2 個示例表):

SELECT DT.ID,
       DT.CustomField,
       DT.[Value],
       CASE DT.ForeignTable WHEN N'tblDriver' THEN CASE DT.CustomField WHEN N'Name' THEN D.[Name] END
                            WHEN N'tblOrigin' THEN CASE DT.CustomField WHEN N'Name' THEN O.[Name] END
       END
FROM dbo.DenormalisedTable DT
     LEFT JOIN dbo.tblDriver D ON DT.ForeignTable = N'tblDriver'
                              AND DT.ftIndex = D.ID
     LEFT JOIN dbo.tblOrigin O ON DT.ForeignTable = N'tblOrigin'
                              AND DT.ftIndex = O.ID;

然而,顯然,它有許多其他表,並且很可能還有其他列(不僅僅是name列)來動態獲取其值。 所以你最終會得到一個像這樣可怕的東西:

SELECT DT.ID,
       DT.CustomField,
       DT.[Value],
       CASE DT.ForeignTable WHEN N'tblDriver' THEN CASE DT.CustomField WHEN N'Name' THEN D.[Name]
                                                                       WHEN N'Age' THEN D.Age
                                                                       WHEN N'Dob' THEN D.Dob
                                                   END
                            WHEN N'tblOrigin' THEN CASE DT.CustomField WHEN N'Name' THEN D.[Name]
                                                                       WHEN N'Age' THEN D.Age
                                                                       WHEN N'Dob' THEN D.Dob
                                                   END
                            WHEN ... --20 more WHENs, 50? Plus all the inner CASE expressions
                            WHEN N'tblOwner' THEN CASE DT.CustomField WHEN N'FirstTraded' THEN Onr.FirstTraded
                                                                      ...
                                                  END
       END AS ColumnValue
FROM dbo.DenormalisedTable DT
     LEFT JOIN dbo.tblDriver D ON DT.ForeignTable = N'tblDriver'
                              AND DT.ftIndex = D.ID
     LEFT JOIN dbo.tblOrigin O ON DT.ForeignTable = N'tblOrigin'
                              AND DT.ftIndex = O.ID
     LEFT JOIN ...
     ---20 more JOINs, 50?
     LEFT JOIN dbo.tblOwner Onr ON DT.ForeignTable = N'tblOwner'
                               AND DT.ftIndex = Onr.ID;

然而,這有一些主要問題。 第一個是數據類型的隱式轉換

例如,請注意我在這里有NameAgeDob列。 這些選擇是有意的,因為數據類型完全不同; 分別是字符串、數字和日期和時間。 如果CASE表達式返回不同的數據類型,則數據類型優先級將用於確定返回的數據類型。 這很可能以日期和時間數據類型結束,這意味着您的數字和/或(n)varchar列將由於轉換錯誤而使語句失敗。 這意味着上述失敗。 盡管您可以CONVERT THEN中返回的每個表達式,但這會嚴重影響數據,並且很容易導致數據可消耗或無法按您的意願顯示。

此問題也適用於ON子句,它假定每個ID列都是相同的數據類型( int ?),因為具有不同的數據類型會完全破壞這一點。 如果不是,那么您需要對適當的數據類型使用TRY_CONVERT ,這將我們帶到下一點:性能

性能會很糟糕 我們不要拐彎抹角。 由於不同表需要大量讀取,這樣的查詢不會很好地執行。 您會很幸運,這會在幾分鍾甚至幾小時內返回數據,具體取決於您的數據庫有多大。 ON中添加類似TRY_CONVERT的內容會破壞 RDBMS 使用索引進行查找的任何(微弱)機會。

最后,我們有可擴展性。 編寫上述內容本身就是一項任務,這意味着您必須使用動態 SQL。 但是你在這里試圖解決的問題是性能問題,我也告訴過你,這個解決方案會很,我的意思是很慢 動態語句不會改善這一點,甚至首先要使語句起作用所需的考慮因素也不小; 所以我們甚至不要沿着這條路走 go,因為它已經扔掉了 window。

因此,這里唯一的解決方案是修復您的設計,以獲得高性能查詢。 規范化您的數據,並且不要存儲諸如查找表在表中的位置之類的信息。 像這樣的設計,雖然對用戶來說可能“看起來”很直觀,但不能擴展,也不能很好地執行。 這種設計通常來自於將 RDBMS 視為一種編程語言,並應用相同的邏輯。 SQL 不是一種編程語言,它不像一個編程語言; 它擅長的東西和它所掙扎的東西是完全不同的。


TL; DR:您的設計實際上是您的查詢緩慢的原因。 您無法解決這個問題,因為您擁有的查詢(無論它是什么)不是根本原因。 只有修復設計才能解決性能問題,這就是您需要集中大量時間和資源來修復的地方。

暫無
暫無

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

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