2013-10-29 252 views
5

我有一個存儲過程作爲SQL命令文本,它正在傳遞一個包含表名的參數。 proc然後從該表中返回數據。我無法直接將該表作爲OLE DB源調用,因爲某些業務邏輯需要發生在proc中的結果集中。在SQL 2008中,這工作得很好。在升級後的2012包中,我得到「元數據無法確定,因爲...包含動態SQL,請考慮使用WITH RESULT SETS子句明確描述結果集。」在SSIS 2012的OLE DB源中使用動態SQL

問題是我無法在proc中定義字段名稱,因爲作爲參數傳遞的表名可能是不同的值,並且每次生成的字段都可能不同。任何人遇到這個問題或有任何想法?我用動態SQL使用「dm_exec_describe_first_result_set」,包含WITH RESULT SETS的臨時表和CTE嘗試了各種各樣的事情,但它在SSIS 2012中不起作用,同樣的錯誤。上下文是很多動態SQL方法的問題。

這是我想最近的事,沒有運氣:

DECLARE @sql VARCHAR(MAX) 
SET @sql = 'SELECT * FROM ' + @dataTableName 

DECLARE @listStr VARCHAR(MAX) 
SELECT @listStr = COALESCE(@listStr +',','') + [name] + ' ' + system_type_name FROM sys.dm_exec_describe_first_result_set(@sql, NULL, 1) 

exec('exec(''SELECT * FROM myDataTable'') WITH RESULT SETS ((' + @listStr + '))') 
+0

如果您嘗試過'SET FMTONLY OFF; EXEC MyProc'在你的OLEDB源。這會讓它變得更好嗎? – billinkc

+0

嘗試過,但它不起作用。 SSIS需要元數據。 – jdf35

+0

無賴。如果這個技巧適用於從2008年到2012年處理臨時表的朋友。 – billinkc

回答

4

那麼請問出於好心,明白爲什麼上帝的綠色地球您使用的SSIS數據流任務來處理這樣的動力源數據?

你正在運行陷入困境的原因是因爲你的委曲的SSIS數據流任務的每一個宗旨:

  • 提取與可靜態類型和設計緩存元數據,已知的已知來源-time
  • 通過與直接的(並且理想地異步)公知的方法變換運行
  • 採取這一轉換後的數據並將其裝載到一個已知的目標還與已知的元數據

具有帶回不同數據的參數化數據源很好。但是,要讓他們每次都帶回完全不同的元數據,而且不同套之間沒有一致性,坦白地說,這很荒謬,而且我不完全確定我想知道在2008年包中如何處理所有列元數據。

這就是爲什麼它要求您將結果集添加到SSIS查詢 - 因此它可以生成一些元數據。它在運行時不會這樣做 - 它不能!它必須有一組已知的列(因爲它將它們全部變換成編譯變量)來處理。它期望每次運行數據流任務時使用相同的列 - 完全相同的列,直到名稱,類型和約束。

這導致了一個(可怕的,可怕的)解決方案 - 只需將所有數據粘貼到一個臨時表中,使用Column1,Column2 ... ColumnN,然後使用您用作表名參數的相同變量來有條件地分支你的代碼,並做任何你想要的列。

另一個更理智的解決方案是爲每個源表創建一個數據流任務,並在優先約束中使用您的參數來選擇運行哪個數據流任務。

對於這個針對開箱即用的ETL定製的解決方案,您應該高度考慮只在C#或腳本任務中自行展開,而不是SSIS提供的數據流任務。

總之,請不要這樣做。想想孩子們(包)!

+0

這在理論上沒有問題,但實際上,如果您有230個SSIS包需要升級到2012年,並且在2008年完成如此完美的數百個ole數據庫源,那麼您正在尋找一個快速解決方案。 – jdf35

1

我已經使用CozyRoc Dynamic DataFlow Plus來實現這一點。

使用配置表構建SQL Select語句,我有一個SSIS包將Oracle和Sybase(或任何OLEDB源)的數據加載到MS SQL中。一些結果集有數百萬行,性能非常好。

每次需要新表格時,都可以在幾分鐘內完成配置,而不必在新的軟件包中編寫新的軟件包,而是在經過預先測試的強大的現有軟件包上運行。

沒有它,我會一直寫了數百包。