2010-06-18 41 views
3

我正在嘗試編寫使用CTE的動態查詢。但我面臨的問題 - 見下文 這是一個簡化的情況使用CTE的SQL Server 2008動態查詢

declare @DynSql varchar(max)=''; 
declare @cnt as integer; 
with months as (
select CAST('07/01/2010' as DATE) stdt 
UNION ALL 
SELECT DATEADD(MONTH,1,STDT) FROM months 
WHERE DATEADD(MONTH,1,STDT)<CAST('06/30/2011' AS DATE) 
) 
select COUNT(*) from months 
set @DynSql='select * from months' 
exec (@DynSql) 

這不工作 - 我得到的錯誤是 無效的對象名稱「月」

是否有實現的任何方式我想。如果我使用Temp表或表變量,它會起作用嗎?

+0

您不能在cte中引用cte。 – websch01ar 2010-06-18 20:39:57

+0

爲什麼你需要'從月份選擇COUNT(*)?爲什麼你需要一個'動態'查詢? – van 2010-06-18 20:41:09

+0

如果我不把選擇計數(*)它抱怨'未使用CTE'。我正在嘗試創建Y軸上數月的數據透視查詢。月數是可變的。所以我將不得不創建樞軸像樞軸(sum(fld)爲col in(['jan-10'],['feb-10'] ...) – josephj1989 2010-06-18 20:54:23

回答

2

您的動態SQL無法引用months。一個CTE的範圍是單個聲明

with cte as (cte definiton) select from cte; 

如果你想重新使用CTE的結果或定義,你必須要麼你想用的時候就重新定義了CTE(如。在@DynSql中)或將其結果實現爲一個表@variable並重新使用表@variable。

+1

不,我嘗試了一個表變量,但它看起來像你不能在動態SQL中使用表變量 – josephj1989 2010-06-18 20:55:50

+1

動態sql在不同的作用域中執行基本上是一個函數調用它不能引用當前上下文中的變量使用'exec sp_executesql @DynSql',@parameterName type',@ localTVP'作爲參數傳入要從當前作用域/上下文中使用的任何變量。 – 2010-06-18 21:10:23

+0

請參見http://msdn.microsoft.com/en-us/庫/ bb510489。aspx爲一個示例如何將一個本地表@variable傳遞給一個過程。 – 2010-06-18 21:12:49

0

嗯,我得到它的工作,但我不現在我有移動信息瞭解這個範圍...

declare @DynSql varchar(max) 
declare @cnt as integer; 
declare @stdt datetime; 
Set @DynSql ='' 
Select @stdt = CAST('07/01/2010' as DATEtime); 
with months as ( 
SELECT DATEADD(MONTH,1,@stdt) As [month] WHERE DATEADD(MONTH,1,@stdt)<CAST('06/30/2011' AS DATEtime) 
) 
select COUNT(*) from months 

修訂:

declare @DynSql varchar(max) 
declare @cnt as integer; 
declare @stdt datetime; 
Set @DynSql = 'With ctemonths as (' 
Select @stdt = CAST('07/01/2010' as DATEtime); 
Set @cnt = 1; 
while @cnt <= 11 --(Select DateDiff(mm, @stdt, '06/30/2011')) 
Begin 
    IF (@CNT =1) 
     Set @DynSql = @DynSql + 'Select DATEADD(MONTH,' + Cast(@cnt as nvarchar(2)) + ',''' + Convert(varchar(10), @stdt, 103) + ''') As [month] ' 
    eLSE 
     Set @DynSql = @DynSql + 'UNION Select DATEADD(MONTH,' + Cast(@cnt as nvarchar 

(2)) + ',''' + Convert(varchar(10), @stdt, 103) + ''') As [month] ' 
Set @cnt = @cnt + 1 

End; 

Set @DynSql = @DynSql + ') Select * from ctemonths' -- PIVOT (max([month]) for [month] in ([month]))' 

exec (@DynSql) 
+0

沒有我的問題是不從cte中選擇count(*),而是使用Dynamic Sql中的CTE。 – josephj1989 2010-06-18 20:57:25

+0

現在我看到你正在嘗試使用Pivot()。利用您提供的數據,您將獲得一個參考點。你想把它與什麼比較?多一點信息,我可以使用cte。 – websch01ar 2010-06-18 20:59:32

+0

幾乎完成了重寫... – websch01ar 2010-06-18 22:10:33

3

的關鍵詞中不聲明可以在以後的查詢中引用的對象。它是選擇查詢的一部分。你的動態sql試圖引用一個不存在的對象months。將CTE包含在定義dyanic查詢的字符串中。

declare @DynSql varchar(max)=''; 
set @DynSql= 
'with months as ( 
    select CAST(''07/01/2010'' as DATE) stdt 
    UNION ALL 
    SELECT DATEADD(MONTH,1,STDT) FROM months 
    WHERE DATEADD(MONTH,1,STDT)<CAST(''06/30/2011'' AS DATE)) 
select * from months' 
exec (@DynSql) 

但是,我沒有看到你通過使SQL動態獲得什麼,因爲SQL語句中沒有任何變化。


如果你想要一個對象,你可以在以後參考,你可以創建一個視圖(一次),將您的動態查詢使用,而類似的查詢(多次)。

create view months_v as 
    with months as (select CAST('07/01/2010' as DATE) stdt 
     UNION ALL 
     SELECT DATEADD(MONTH,1,STDT) FROM months 
     WHERE DATEADD(MONTH,1,STDT)<CAST('06/30/2011' AS DATE)) 
    select * from months; 
go 

declare @DynSql varchar(max)=''; 
set @DynSql='select * from months_v' 
exec (@DynSql) 
+0

我已經試過這個。我需要使用數據透視表來顯示整個頁面的月度數據。我正在嘗試創建一個跨Y軸數月的數據透視查詢。月數是可變的。所以我將不得不創建樞軸,像pivot(sum(fld)for col in(['jan-10'],['feb-10'] ...)。因此,我必須創建月份列表一部分是動態查詢。但是數據透視查詢與CTE月份交叉連接。因此,我需要在動態SQL之外定義月CTE,並在其中添加月份。我試圖將月份插入到表變量中並將它傳遞給sp_execsql,但它確實不接受表格變量 – josephj1989 2010-06-18 21:36:59

+0

是的,沒有視圖,你需要在動態SQL裏面創建CTE,我不明白問題是什麼,也許發佈更多的問題和錯誤信息會有幫助。 – 2010-06-18 21:52:46

0

您不能使用CTE或@TableVariable在動態SQL,但你可以使用一個#TEMP表這一點。創建一個臨時表,將數據存儲在那裏(你可以將你的CTE結果複製到臨時表)並在動態查詢中使用它。這是解決方案。