2011-01-28 68 views
6

背景:有一個存儲過程用給定名稱的臨時表執行「填充」操作。該過程是通用的,因爲它檢查臨時表的模式,然後根據模式執行不同的「內容」。我明白,這有點奇怪,但我不願意改變它,因爲它在大多數情況下都可以正常工作,除了....爲什麼SQL Server在沒有時認爲臨時表已經存在?

如果我有一個存儲過程,它爲臨時表創建兩個不同的模式同名。從邏輯上講,它僅根據IF的哪個分支創建一個臨時表。問題是,當存儲過程由SQL Server檢查看起來它正在評估IF兩側

所以這個SQL失敗(這是有道理的,如果它檢查SQL語法):

IF (1=1) 
BEGIN 
    CREATE TABLE #test 
    (
     a BIGINT NOT NULL, 
     b BIGINT NOT NULL 
    ) 
END 
ELSE 
BEGIN 
    CREATE TABLE #test 
    (
     a BIGINT NOT NULL, 
     b BIGINT NOT NULL, 
     c BIGINT NOT NULL 
    ) 
END 

--exec SomeProcedureWhichDoesStuffWith#Test 

DROP TABLE #test 

,出現以下錯誤:

Msg 2714, Level 16, State 1, Line 14
There is already an object named '#test' in the database.

的IFS內跌幅榜的任何組合(之前或之後創建表DDL)似乎滿足SQL檢查。

任何想法,我可以做到這一點?例如,我可以告訴SQL不執行語法檢查,只是接受sproc原樣?

回答

6

這是一個限制。由於#tmp將在新會話中創建並立即丟失,因此動態SQL將不起作用。對於如圖所示的確切片段,這樣做同樣的

CREATE TABLE #test 
(
    a BIGINT NOT NULL, 
    b BIGINT NOT NULL 
) 

IF not (1=1) 
    ALTER TABLE #test ADD c BIGINT NOT NULL 

不能有兩個創建用..#NAME同一批次內,但是這也將在一般形式

IF (1=1) 
BEGIN 
    CREATE TABLE #test 
    (
     a BIGINT NOT NULL, 
     b BIGINT NOT NULL 
    ); 
END 
GO 

IF NOT (1=1) 
BEGIN 
    CREATE TABLE #test 
    (
     a BIGINT NOT NULL, 
     b BIGINT NOT NULL, 
     c BIGINT NOT NULL 
    ) 
END 
0

,因爲我不工作有SQL 2008,我無法測試它。但據我所知,這是一個解析器問題明確與臨時表。同樣的情況也很好地工作正常表

來排序了這一點,只是邏輯GO語句

分割你的代碼的理想:檢查臨時表的存在,您創建臨時表之前,如果它們存在刪除它們,火一去,又做臨時表的創建,火一展身手,那麼任何後處理,火一展身手,終於再次把它們和火最後去


你可能也想嘗試和使用如果上面的代碼不能解決這個問題,請使用表格變量而不是臨時表格

+0

是感謝您的信息。不幸的是,它是在一個存儲過程中創建表,所以它必須在同一批次中(所以它不是GO)。 – 2011-01-28 13:20:05

0

你總是可以 「欺騙」:

DECLARE @SQL VARCHAR(200) 

IF (1=1) 
BEGIN 
    SET @SQL = 'CREATE TABLE #Temp  ' + 
       '(      ' + 
       ' a BIGINT NOT NULL, ' + 
       ' b BIGINT NOT NULL ' + 
       ')      ' 
END 
ELSE 
BEGIN 
    SET @SQL = 'CREATE TABLE #Temp  ' + 
       '(      ' + 
       ' a BIGINT NOT NULL, ' + 
       ' b BIGINT NOT NULL, ' + 
       ' c BIGINT NOT NULL ' + 
       ')      ' 
END 

EXEC SP_EXECUTESQL @SQL 
+0

這將不起作用,因爲它會立即超出範圍並且不能在外部腳本中使用它需要是全局臨時表或臨時表的所有用法都需要位於動態SQL中。 – 2011-02-09 17:49:27

2

相反#TEST的,使用完全合格的名稱。例如,

[tempdb].[dbo].[temptable] 

我在這裏學到了這個小技巧Insert result of executing dynamic query into a table

智能感知會發出抱怨,但您仍然可以創建或更改存儲過程。

當用它做,一定要刪除它:

DROP TABLE [tempdb].[dbo].[temptable] 
相關問題