2

我有一個存儲過程,並且cte不能很好地在一起玩。我曾嘗試做一些研究,但都沒有成功。當我註釋掉插入到cte的##選項卡時,SP工作,我看到了cte的結果。它就在我插入到全局臨時表##選項卡時。存儲過程不能使用插入臨時表

我收到這些錯誤。 Msg 102,Level 15,State 1,Line 39

'ALL'附近語法不正確。

消息102,級別15,狀態1,行39

附近有語法錯誤 'ALL'。

消息102,級別15,狀態1,行39

附近有語法錯誤 'ALL'。

消息102,級別15,狀態1,行39

附近有語法錯誤 'ALL'。

消息102,級別15,狀態1,行39

附近有語法錯誤 'ALL'。

SET ANSI_NULLS ON 
GO 

SET QUOTED_IDENTIFIER ON 
GO 




ALTER PROCEDURE [dbo].[csp_CALL_UCBI_DCN_DATES] 
    @FMDATE DATETIME ='2014-01-20 00:00:00.000', 
    @TODATE DATETIME ='2014-06-30 00:00:00.000' 
AS 
BEGIN 
SET NOCOUNT ON; 

DECLARE 
[email protected] DATETIME 
--,@TODATE DATETIME 
@FM_DATEPART_MONTH VARCHAR(2) 
,@FM_DATEPART_YEAR VARCHAR(4) 
,@TO_DATEPART_MONTH VARCHAR(2) 
,@TO_DATEPART_YEAR VARCHAR(4) 

--SET @FMDATE = '2014-01-20 00:00:00.000' 
--SET @TODATE = '2014-06-30 00:00:00.000' 
SET @FM_DATEPART_MONTH = CAST(DATEPART(M,@FMDATE) AS VARCHAR(2)) 
SET @FM_DATEPART_YEAR = CAST(DATEPART(YYYY,@FMDATE) AS VARCHAR(4)) 
SET @TO_DATEPART_MONTH = CAST(DATEPART(M,@TODATE) AS VARCHAR(2)) 
SET @TO_DATEPART_YEAR = CAST(DATEPART(YYYY,@TODATE) AS VARCHAR(4)) 

    CREATE TABLE ##tab (id INT IDENTITY(1,1) PRIMARY KEY,myDate VARCHAR(50), SQLname VARCHAR(50),myMonth VARCHAR(50),myYear VARCHAR(50)) 
;WITH cte(myDate,myMonth,myYear,SQLname) AS (

    SELECT @FMDATE AS myDate 
    ,CAST(DATEPART(M,@FMDATE) AS VARCHAR(2)) AS myMonth 
    ,CAST(DATEPART(YYYY,@FMDATE) AS VARCHAR(4)) AS myYear 
    ,CAST(DATEPART(M,@FMDATE) AS VARCHAR(2))+'_'+CAST(DATEPART(YYYY,@FMDATE) AS VARCHAR(4)) AS SQLname 
    UNION ALL 
    SELECT DATEADD(MONTH,1,myDate) AS myDate 
    ,CAST(DATEPART(M,DATEADD(MONTH,1,myDate)) AS VARCHAR(2)) AS myMonth 
    ,CAST(DATEPART(YYYY,DATEADD(MONTH,1,myDate)) AS VARCHAR(4)) AS myYear 
    ,CAST(DATEPART(M,DATEADD(MONTH,1,myDate)) AS VARCHAR(2))+'_'+CAST(DATEPART(YYYY,DATEADD(MONTH,1,myDate)) AS VARCHAR(4)) AS SQLname 
    FROM cte 
    WHERE DATEADD(MONTH,1,myDate) <= @TODATE 
) 
INSERT INTO [##tab] 
(myDate,myMonth,myYear,SQLname) 
SELECT * 
FROM cte 
--output INSERTED.myDate,INSERTED.myMonth,INSERTED.myYear,INSERTED.SQLname into [##tab] 
--(myMonth,myYear,SQLname) 
--OPTION (MAXRECURSION 0) 

------------------------------------ 

DECLARE @sql VARCHAR(8000) 
, @i INT 
,@count INT 
, @sqlname VARCHAR(15) 
, @myMonth VARCHAR(50) 
, @myYear VARCHAR(50) 

SET @i=1 
SELECT @count= COUNT(*) FROM ##tab 
WHILE @i <= @count 

BEGIN 
SELECT @SQLname=SQLname, @myMonth=myMonth, @myYear=myYear FROM ##tab WHERE [email protected] 

SET @sql = ' 
    SELECT 
''UCBI_DCE_'[email protected]+''' AS [Table], 
CAST('''[email protected]+'/'[email protected]+'/01'' AS DATETIME) AS Date, 
     lEntity , 
     lValue , 
     lAccount , 
     lICP , 
     lCustom1 , 
     lCustom2 , 
     lCustom3 , 
     lCustom4 , 
     dP0_Input , 
     dP0_InputTransType , 
     dP1_Input , 
     dP1_InputTransType , 
     dP2_Input , 
     dP2_InputTransType , 
     dP3_Input , 
     dP3_InputTransType , 
     dP4_Input , 
     dP4_InputTransType , 
     dP5_Input , 
     dP5_InputTransType , 
     dP6_Input , 
     dP6_InputTransType , 
     dP7_Input , 
     dP7_InputTransType , 
     dP8_Input , 
     dP8_InputTransType , 
     dP9_Input , 
     dP9_InputTransType , 
     dP10_Input , 
     dP10_InputTransType , 
     dP11_Input , 
     dP11_InputTransType , 
     dTimestamp 
     FROM [DB100].[DB].[dbo].[DCN_'[email protected]+'] 
     UNION ALL 
' 
IF @i = @count SET @sql = LEFT(@sql,LEN(@sql) - 15) 
--PRINT @sql 
EXEC (@sql) 

SET @[email protected]+1 
END 
IF(OBJECT_ID('tempdb..##tab') IS NOT NULL) 
BEGIN 
    DROP TABLE ##tab 
END 
END 

GO 
+0

請意識到你有併發問題在這裏,因爲全局臨時表的。您還有一些性能方面的挑戰,因爲您的主查詢具有nonSARGable謂詞。最後但並非最不重要的,我會建議不要使用while循環來建立一個像這樣的動態sql字符串。你可以做這整個過程簡單得多。 –

回答

1

我相信這是問題所在。我得到,你正在試圖建立一些動態的SQL和UNION ALL。問題是你在循環中執行@sql,而聲明仍在構建中。所以基本上你每次迭代都會建立並執行@sql。將最終執行移到循環外部。我縮短了您的代碼以顯示問題所在。

噢,當你將insert註釋到臨時表中時,它正在工作的原因是因爲該表中沒有行,所以你永遠不會進入循環。

BEGIN 
SELECT @SQLname=SQLname, @myMonth=myMonth, @myYear=myYear FROM ##tab WHERE [email protected] 

SET @sql = ' 
    YOUR CODE 
    UNION ALL' 
IF @i = @count SET @sql = LEFT(@sql,LEN(@sql) - 15) 
--PRINT @sql 

/*HERE YOU EXECUTE WHILE IN LOOP SO THE LAST LINE IS UNION ALL*/ 
EXEC (@sql) 
SET @[email protected]+1 
END 

這裏的修復

SET @i=1 
/* Set @sql outside of loop */ 
SET @sql = '' 
SELECT @count= COUNT(*) FROM ##tab 
WHILE @i <= @count 

BEGIN 
SELECT @SQLname=SQLname, @myMonth=myMonth, @myYear=myYear FROM ##tab WHERE [email protected] 

/* Modified this to add to @sql each interation to build your select statement.*/ 
SET @sql = @sql + ' 
    select 1 
    UNION ALL' 

IF @i = @count SET @sql = LEFT(@sql,LEN(@sql) - 15) 

SET @[email protected]+1 
END 

/* Moved exec out of loop*/ 
EXEC (@sql) 
+0

這不是問題所在。印刷品出來看起來不錯。 – dbahiker

+0

@dbahiker這是因爲你正在打印每一個迭代,所以結果看起來像它的一個大字體,但實際上它是6.在你的打印下面添加另一行'PRINT'STATEMENT EXECUTED'',你會看到我的意思 – SQLChao

+0

Gotcha,好的Im尋找解決方案。有任何想法嗎? – dbahiker

0

爲什麼聯合ALL在動態SQL查詢的底部?這是其中的誤差來自... UNION ALL將兩個單獨的select語句與像場

簡單的例子:

select 1 
union all 
select 2 

這將返回2行...... 1和2

這裏你在這裏沒有任何跟隨它。除非你有另一個語句在它下面運行,否則將所有聯合移除,在這種情況下......將其他語句包含在代碼中。

+0

查詢設置爲在while循環中建立,因此聯合都在那裏將它們連接在一起。如果只有一個查詢需要,IF i = Count中會有一個刪除步驟,以消除它。我認爲它正在建造的方式有些問題。把你的PRINT @sql輸出放到查詢窗口中,查找錯誤。 –

+0

我與UNION ALL一起使用它,因爲我選擇了多於兩條SELECT語句。基本查詢可以有9個結果,然後我將有9個SELECT語句,它們之間都有UNION ALL。然後在最後一個循環中,您會看到我刪除了15個字符的LENGTH。 – dbahiker

+0

伯爵G是的,當我打印它時,我即將運行它。當運行整個事件作爲查詢而不是存儲過程時也工作正常 – dbahiker

相關問題