2017-03-31 93 views
1

我們目前正在參與一個數據遷移項目,爲此我們必須分析數據的使用,這意味着我們需要弄清楚哪些是用來表和列,需要遷移,哪些數據已過時。 我們不僅擁有許多基於存儲過程的SSRS報告,而且還有數百個(如果不是數千個)用於臨時分析的TSQL腳本。幾乎不可能用手分析它們。解析TSQL腳本並返回表和列使用

我在尋找解析這些腳本並返回腳本使用的數據的方法。我設法在EditPad中編寫了一個從腳本中提取表格的宏,但是我沒有對列做同樣的處理。這裏的主要問題是別名,CTE以及腳本中與其他命令區別的列名。

相較於簡單的基於正則表達式的宏,SQL Server必須有其列由腳本中使用一個明確的想法 - >執行計劃。 有什麼方法可以將這種功能用於我們的目的?甚至更好:是否有任何第三方工具可以滿足我們的需求?到目前爲止,我找不到任何東西。

非常感謝您的任何建議!

+0

程序不是太糟糕,至少得到表,但列是另一回事。即使使用sys.sysdepends也只會讓你看到對象。這些對象可以是表格,但它們也可以是函數,視圖等,這些也必須進行分析。然後,當您進行臨時查詢時,幾乎不可能精確地手動解析它。 –

+0

RedGate SQL Search具有影響分析功能,可以讓您找到存儲過程中引用列名稱的位置。不知道它會幫助你的特別查詢。 http://www.red-gate.com/products/sql-development/sql-search/ – mallan1121

回答

2

解析執行計劃中的表和列可能是可能的,但這不是一件容易的事。 (我會看着這個帖子,以防有人說出來。)第三方工具可能要做到這一點,另一件需要注意的事情。根據我的經驗,我認爲這可能是不可行的,而不是你所需要的全部程度。

橫向的方法:你可以安排對數據庫「運行一切」,讓你知道所有可能試圖訪問你的數據都被打?如果是這樣的:

  • 創建數據庫的副本。
  • 只包含儘可能少的數據以使查詢正常工作。
  • (所以,無論是備份/恢復,或使用SSMS爲「腳本出」數據庫)
  • 配置的安全性,使得使用可以訪問什麼
  • 運行第一個查詢的登錄,它就會失敗。確定哪些表和列它需要訪問。授予,只有那些表和列的訪問。
  • 運行一個查詢,重複。
  • 賠率是可以運行查詢的批次,並添加表/列集體
  • 保存通過首先啓用已知/明顯的表格
  • 一旦所有查詢都可以成功運行,因爲所有相關的表和列都已啓用,您將擁有最小集合。

事情是...寫了這麼多,我看到很多潛在的警告,邊緣案例和陷阱(完全取決於你要處理什麼 - 視圖怎麼樣?觸發器?同義詞?),我必須質疑是否值得努力。如果你確定會裁減掉一半的數據庫,那就去做吧,但是如果減少10%,這可能不值得。 (對於減少10%,儘量只重命名最可疑的表,看看會發生什麼。)

+0

非常感謝,如果我們無法開發自動化解決方案,這是一個很好的後備解決方案。 –

1

的部分答案:

基於this article,有可能使用PowerShell(或編譯。Net語言)使用Microsoft.SqlServer.Management.SqlParser爲Microsoft工具使用的SQL語句生成分析樹。

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Management.SqlParser") | Out-Null 
$ParseOptions = New-Object Microsoft.SqlServer.Management.SqlParser.Parser.ParseOptions 
$ParseOptions.BatchSeparator = 'GO' 
$ParseOptions.CompatibilityLevel = [Microsoft.SqlServer.Management.SqlParser.Common.DatabaseCompatibilityLevel]::Current 
$ParseOptions.IsQuotedIdentifierSet = $true 
$ParseOptions.TransactSqlVersion= [Microsoft.SqlServer.Management.SqlParser.Common.TransactSqlVersion]::Current 

set-psdebug -strict 

#$SQL=get-content $Args[0] |foreach-object{"$_`n"} 

$SQL = "SELECT c.COLUMN_NAME, 
     c.TABLE_NAME, 
     t.TABLE_SCHEMA, 
     t.TABLE_TYPE, 
     t.TABLE_NAME AS t2 
FROM INFORMATION_SCHEMA.TABLES AS t 
JOIN INFORMATION_SCHEMA.COLUMNS AS c 
ON c.TABLE_NAME = t.TABLE_NAME 
AND c.TABLE_SCHEMA = t.TABLE_SCHEMA 
AND c.TABLE_CATALOG = t.TABLE_CATALOG 
" 

$Script=[Microsoft.SqlServer.Management.SqlParser.Parser.Parser]::Parse($SQL, $ParseOptions) 

$flags = [System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::NonPublic 
$Script.GetType().GetProperty("Script", $flags).GetValue($Script).Xml 

我有本地版本的SSMS 2016和SQL Server 2014安裝,這工作沒有安裝任何其他。

這仍然留下了很多工作要解釋樹,但你可能能夠利用它。

+0

很好,非常感謝,這看起來很有希望。我們一定會試試這個。 –

0

我的一位同事曾使用XML解析查詢執行計劃的聰明的想法:

執行計劃已經被保存爲XML,然後過濾網站上,以減少層級深度/號碼,其必須不大於128:

http://xmltoolbox.appspot.com/

1. Paste the XML 
2. Add Column Reference as a filter 
3. Format xml 
4. Save it again as flatfile 

過濾的XML可以讀取和在SQL處理:

DECLARE @xml xml = (
       SELECT CAST(BulkColumn AS XML) FROM OPENROWSET(  
       BULK 'c:\temp\Herkunftsselect_filtered.xml',  
       SINGLE_BLOB) AS ExecPlan 
   ); 

WITH XMLNAMESPACES ('http://schemas.microsoft.com/sqlserver/2004/07/showplan' AS SP) 
SELECT DISTINCT 
       'Database' = n.xml.value('./@Database','nvarchar(100)'), 
       'Schema' =          n.xml.value('./@Schema','nvarchar(100)'), 
       'Tabelle' =         n.xml.value('./@Table','nvarchar(100)'), 
       'Alias' =           n.xml.value('./@Alias','nvarchar(100)'), 
       'Column' =          n.xml.value('./@Column','nvarchar(100)') 
FROM @xml.nodes('/Root/SP:ColumnReference') n(xml) 
WHERE n.xml.value('./@Column','nvarchar(100)') NOT LIKE 'Expr%' 
  AND n.xml.value('./@Column','nvarchar(100)') NOT LIKE 'Chk%' 
  AND n.xml.value('./@Column','nvarchar(100)') NOT LIKE 'Bitmap%' 
  AND n.xml.value('./@Column','nvarchar(100)') NOT LIKE 'IsBaseRow%' 
  AND n.xml.value('./@Column','nvarchar(100)') NOT LIKE 'Union%' 
  AND n.xml.value('./@Column','nvarchar(100)') NOT LIKE 'Segment%' 

ORDER BY 1,2,3,4,5 

現在,唯一缺少的部分是如何完全自動化進程以遍歷腳本文件,生成執行計劃,過濾xml並運行查詢。我的同事考慮的一種方式可能是將所有腳本文件合併成一個大文件(循環遍歷文件並追加它們),以便手動過程只需要完成一次。