2015-11-16 47 views
0

我有140,000條INSERT語句需要運行。我試圖將記錄插入到數據庫表中,然後將創建的PK輸入到一個臨時表中,然後返回。它看起來是這樣的:存儲過程中的臨時表在首次執行後不可用

CREATE PROCEDURE sp_MassInsertProcedure 
    @PassInVariable int 
AS 
    CREATE TABLE #TempTable(OriginalID int IDENTITY(1,1), NewID int); 

    --These two inserts are essentially repeated 70,000 times 
    INSERT INTO MyDBTable (something, something, something) VALUES (1, 2, @PassInVariable); 
    INSERT INTO #TempTable(NewID) SELECT SCOPE_IDENTITY(); 

    SELECT * FROM #TempTable; 
    DROP TABLE #TempTable; 

我有一些其他的存儲過程就是這樣的具有最大2000條INSERT語句和這樣完美的作品,但我想是因爲報表在這個特定的SP它給數我在嘗試創建過程時發現「查詢已完成且出錯」,但實際上並未創建過程。

然後我每增加一個GO插入語句,但在第一個GO執行後,必須釋放臨時表並且我得到「TempTable is unavailable」錯誤(我也在第一個GO之後爲@PassInVariable獲取了相同的錯誤執行)。奇怪的是,當我將上面解釋的SQL放在標準腳本中(而不是在存儲過程中)時,它就可以工作。

所以我的問題是,有誰知道如何在單個存儲過程中通過GO命令使用多個批處理執行來存儲臨時表/變量?

CREATE PROCEDURE sp_MassInsertProcedure 
    @PassInVariable int 
AS 
    CREATE TABLE #TempTable(OriginalID int IDENTITY(1,1), NewID int); 

    --These inserts are essentially repeated 70,000 times 
    INSERT INTO MyDBTable (something, something, something) VALUES (1, 2, @PassInVariable); 
    INSERT INTO #TempTable(NewID) SELECT SCOPE_IDENTITY(); 
    GO 
    INSERT INTO MyDBTable (something, something, something) (1, 2, @PassInVariable); 
    INSERT INTO #TempTable(NewID) SELECT SCOPE_IDENTITY(); 

    SELECT * FROM #TempTable; 
    DROP TABLE #TempTable; 
+1

您正在用錯誤的解決方案解決問題。你可以使用'OUTPUT'子句 –

回答

0

感謝大家的答案......我結束了以下解決方案:

從腳本,在呼喚着我的存儲過程,我創建了#TempTable

CREATE TABLE #TempTable (OriginalID int IDENTITY(1,1), NewID int); 
EXEC sp_InsertMassRecords 777; 

然後在我的存儲過程我有:

CREATE PROCEDURE sp_InsertMassRecords 
    @IncomingVariable int 
AS 
BEGIN 
    SET NOCOUNT ON; 

    INSERT MyDBTable (col1, col2, col3) 
    OUTPUT Inserted.ID INTO #TempTable(NewID) 
    SELECT 1, @IncomingVariable, 3 UNION ALL 
    SELECT 4, @IncomingVariable, 6 UNION ALL... 

我大約每隔100個選擇語句左右重複INSERT/OUTPUT行整件事成功地運行得非常快!

0

本,這是在SQLServer中關於「GO」的常見誤解。 「GO」不是T-SQL的一部分,它是SQLServer工具(ssms,sqlcmd,sqlwb,isql等)的指令,可以在不同的語句中分割腳本。 所以你不能在SP和函數中使用它(即使在動態SQL中),只能在腳本中使用它。

雖然我不知道爲什麼你的SP無法創建,但如果你想從Java,.NET,運行程序等平臺,你需要添加

SET NOCOUNT ON 
0

不是Temptable不可用

您會收到此錯誤消息,因爲本地臨時表僅對創建它的連接可見,並在該連接關閉時被刪除。在存儲過程中使用GO會結束批處理並因此結束存儲過程。

一種解決方案是使用單個INSERT查詢並使用OUTPUT子句來存儲新插入IDs

INSERT INTO MyDBTable (something, something, something) 
OUTPUT Inserted.ID INTO #TempTable(NewID) 
VALUES (1, 2, @PassInVariable); 

INSERTED.ID用正確的ID從MyDBTable


更換 ID

要多次插入一行,可以使用Tally Table

WITH E1(N) AS(
    SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t(N) 
), 
E2(N) AS(SELECT 1 FROM E1 a CROSS JOIN E1 b), 
E4(N) AS(SELECT 1 FROM E2 a CROSS JOIN E2 b), 
E8(N) AS(SELECT 1 FROM E4 a CROSS JOIN E4 b), 
Tally(N) AS(
    SELECT TOP(70000) 
     ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) 
    FROM E8 
) 
INSERT INTO MyDBTable(something, something, something) 
OUTPUT Inserted.ID INTO #TempTable(NewID) 
SELECT 
    1, 2, @PassInVariable 
FROM Tally 

用您想要插入的行數替換TOP

Here is a simplified explanation of Tally Table.

0

在MS SQL GO語句釋放資源並清理您的會話;這就是爲什麼臨時表不見了你的變量。

在你的存儲過程或至少上面的SQL腳本中,你不需要go語句。

您在其他腳本中看到的GO語句將阻止解析器在先前的語句出錯後停止執行。它類似於Visual Basic「On Error Resume Next」語句。這樣您的腳本將繼續執行,直到腳本文件結束。

您將看到GO語句將主要用於包含多個事務的腳本文件;在每次交易之後都是去聲明。例如,一個腳本文件包含用於不同存儲過程的多個CREATE語句。但是在一個事務中,您不想使用GO語句,因爲您將在腳本中看到所有變量(包括臨時表)。

雖然我在您的存儲過程中看不到需要。

+0

使用單個查詢來做到這一點好吧,所以我已經刪除了GO,並且簡化了我的SP,因此它傳遞了一個參數,然後執行70,000條插入語句...... .still只是得到「查詢完成有錯誤」,但沒有消息。我懷疑它只是與大量的插入物有關,但無法證實......試圖尋找如何獲得更多信息。 –

+0

我還沒有使用SCOPE_IDENTITY()函數;我只使用@@ IDENTITY參數來獲取新添加的標識值。你爲什麼不嘗試? – NPToita

+0

Felix Pamittan,回答可能有興趣並值得研究。 – NPToita

0

原因臨時表不可用是因爲存儲過程是:

CREATE PROCEDURE sp_MassInsertProcedure 
    @PassInVariable int 
AS 
    CREATE TABLE #TempTable(OriginalID int IDENTITY(1,1), NewID int); 

    --These inserts are essentially repeated 70,000 times 
    INSERT INTO MyDBTable (something, something, something) VALUES (1, 2, @PassInVariable); 
    INSERT INTO #TempTable(NewID) SELECT SCOPE_IDENTITY(); 
    GO 

定義停在GO,理由在其他的答案解釋。

現在,一些有用的建議:

  • 把存儲過程的主體中BEGIN/END塊或BEGIN CATCH/END TRY塊。那麼它的存在或結束的位置就不存在歧義。
  • 您不需要刪除存儲過程結尾處的臨時表。它會自動發生。但我承認,我個人更喜歡錶變量,因爲它們更明顯是被刪除的。
  • 獲取返回值的最佳方法是使用OUTPUT子句。 SCOPE_IDENTITY()非常安全。但OUTPUT更好,通常是推薦的方法。