2016-07-26 52 views
0

我有一個接收ID參數並執行插入/更新的存儲過程。T-SQL:執行過程從表中獲取參數值(SQL Server 2012)

我有大約25K記錄需要更新,我一直在想方設法增強單個參數存儲過程,以便它可以處理來自表的多個值或一組ID。

最近我做到這一點,是通過創建一個遊標並在執行存儲過程時循環它,不幸的是,我已經意識到這是一個非常緩慢的方法。

我想知道如果我可以幫助修改我的存儲過程,以便它可以有更好的性能。

這是我使用遊標的代碼。通過objectNotFound做出

SET NOCOUNT ON; 
DECLARE @Id VARCHAR(32); 

DECLARE csr CURSOR 
FOR SELECT DISTINCT ID 
    FROM table 
    ORDER BY id; 

OPEN csr; 

FETCH NEXT FROM csr INTO 
    @Id; 

WHILE @@FETCH_STATUS = 0 
    BEGIN 
     PRINT 'Running for '[email protected]; 
     EXEC update_product_xml_single_id @Id; 
     FETCH NEXT FROM csr INTO 
      @Id; 
    END; 

CLOSE csr; 
DEALLOCATE csr; 

UPDATE

以下建議:我現在面臨

--Create User-defined Table Type 
CREATE TYPE IdTableType AS TABLE ([Id] VARCHAR(20) NOT NULL); 

-- Modified old stored proc: update_product_xml_single_id, to receive the new type 
CREATE PROCEDURE update_product_xml_tvp (@id IdTableType READONLY) 

-- Called stored proc with a table variable 
DECLARE @ID IdTableType 

INSERT @ID 
SELECT DISTINCT ID 
FROM Products 
WHERE ID LIKE 'N0%' 
ORDER BY ID; 

EXEC update_product_xml_tvp @ID 

問題是與原來的存儲過程或步驟2#。我唯一修改的是名稱和參數類型,但是當我嘗試保存更改時,出現如下錯誤:

消息137,級別16,狀態1,過程update_product_xml_tvp,行43 必須聲明標量變量「@id」。

該消息抱怨的標量變量是我剛剛從varchar修改爲表類型的相同參數。我不知道如何在這裏進行形式,或者如果我的步驟錯了。任何幫助都很好,謝謝。

回答

2

您需要的是表值參數作爲存儲過程的輸入(update_product_xml_single_id)。因此,不是傳遞int類型的標量值(@Id),而是傳遞一個列表(比如@TVP),其中包含您當前正在處理的來自OP中表「table」的所有ID。在你的存儲過程中,你可以像使用其他普通表一樣使用該表變量@TVP。

此鏈接顯示瞭如何用一個例子做(我抄這個例子樓下):

USE AdventureWorks2012; 
GO 

-- Step 1 
/* Create a table type. */ 
CREATE TYPE LocationTableType AS TABLE 
(LocationName VARCHAR(50) 
, CostRate INT); 
GO 

-- Step 2 
/* Create a procedure to receive data for the table-valued parameter. */ 
CREATE PROCEDURE dbo. usp_InsertProductionLocation 
    @TVP LocationTableType READONLY 
    AS 
BEGIN 
    SET NOCOUNT ON 
    INSERT INTO AdventureWorks2012.Production.Location 
      (Name 
      ,CostRate 
      ,Availability 
      ,ModifiedDate) 
     SELECT *, 0, GETDATE() 
     FROM @TVP; 
    END 
    GO 

用法:從上面的MSDN鏈接

https://msdn.microsoft.com/en-us/library/bb510489.aspx?f=255&MSPPError=-2147217396

例通過TVP到存儲過程:

/* Declare a table variable that references the type. */ 
DECLARE @LocationTVP AS LocationTableType; -- This was created in Step 1 above. 

/* Add data to the table variable. So this would be the same as your Declare Cursor SQL except its inserting into a Table Valued Parameter @LocationTVP */ 
INSERT INTO @LocationTVP (LocationName, CostRate) 
    SELECT Name, 0.00 
    FROM AdventureWorks2012.Person.StateProvince; 

/* Pass the table variable data in @LocationTVP to a stored procedure that now expects a Table valued parameter as input */ 
EXEC usp_InsertProductionLocation @LocationTVP; 
GO 

編輯:

我只是測試你創建SP代碼,它工作得很好,這是我試過

CREATE TYPE IdTableType AS TABLE ([Id] VARCHAR(20) NOT NULL); 
GO 

-- Modified old stored proc: update_product_xml_single_id, to receive the new type 
CREATE PROCEDURE update_product_xml_tvp 
(@id IdTableType READONLY) 
AS 
BEGIN 
    SELECT * FROM @id --- Obviously you will be using it differently but this is just to prove that it works 
END 

也是「INTO」缺少在INSERT語句中

這:

INSERT @ID 
SELECT DISTINCT ID 
FROM Products 
WHERE ID LIKE 'N0%' 
ORDER BY ID; 

應該是

INSERT INTO @ID 
SELECT DISTINCT ID 
FROM Products 
WHERE ID LIKE 'N0%' 
ORDER BY ID; 

我將INTO部分添加到了我的代碼中。但它仍然給我同樣的錯誤。 我想確保您知道存儲的proc update_product_xml_tvp 與我在CURSOR中使用的存儲過程相同,我在其中更改的唯一內容是輸入參數類型。它曾經是: @pf_id VARCHAR(100)

,現在是: @Id ID READONLY

由於我沒有在該過程中的代碼修改的東西,錯誤來自於像部分: WHERE ai.ID = @id

東西看起來不正確,就像@id不再是與ai.id相同的數據類型,因此比較不再有效,但我不知道如何糾正它,或在哪裏。

因此,要確保這是正確的,我結束了

1. A user defined table type named id 

CREATE TYPE idTableType AS TABLE ([some_id] VARCHAR(20) NOT NULL); 

2. A stored procedure that populates that table type: 

CREATE PROC [dbo].[mn_pass_id_table] (@id_spVariable idTableType READONLY) 
AS 
BEGIN 
    SET NOCOUNT ON 
    SELECT DISTINCT ID 
    FROM Products 
    WHERE ID LIKE 'N0%' 
    ORDER BY ID; 
END 

3. And a modification to the stored procedure that existed already. 

    From: 
    ALTER PROCEDURE update_product_xml_single (@id VARCHAR(100)) 

    To:  
    ALTER PROCEDURE update_product_xml_tvp (@id_spVariable idTableType READONLY) 

這裏面的程序也有,我沒有改變,也沒有改裝4個WHERE條件和正在給我的錯誤,不會讓我更新的存儲過程:

WHERE ai.ID IN (Select some_id from @id_spVariable ) 

我的理解是,在年底,我將能夠做到從一個新的查詢窗口如下:

DECLARE @ID_Var_That_We_Will_Pass_To_Your_SP as idTableType 

INSERT INTO @ID_Var_That_We_Will_Pass_To_Your_SP 
SELECT SOME_COLUMN FROM REAL_TABLE (This will be the one that you currently use to Declare the Cursor) 

EXEC update_product_xml_tvp @ID_Var_That_We_Will_Pass_To_Your_SP 

我相信我在這裏搞點東西。我真的想把它做對。感謝您的耐心和幫助。

+0

謝謝objectNotFound,我在代碼中實現更改有點困惑,但我會試一試。 –

+0

@erasmocarlos它非常直截了當......我複製/粘貼的例子中的最後3個語句在SP之外。我將編輯帖子以澄清這一點。 – objectNotFound

+0

第一部分第二步,爲什麼插入從命名爲Location的表中獲取數據,然後在插入語句的最後三個語句中,tvp使用來自不同表的數據填充。 –

0

我是初學者,但我認爲這會幫助你嘗試一下。

創建用戶定義的函數

< --step 1: - >

create type [dbo].[IdTableType ] as table 
(
[Id] BIGINT NOT NULL 
) 
GO 

現在< --step 2: - >

CREATE PROCEDURE update_product_xml_tvp 
    (
    @table1 IdTableType READONLY 
    ) 
AS 
BEGIN TRY 
Declare @ID BIGINT 

INSERT into YOUR_TABLE 
    (
    ID 
    ) 
SELECT DISTINCT ID 
FROM @table1 
WHERE ID LIKE 'N0%' 
ORDER BY ID; 

END TRY 
BEGIN CATCH 
print error_message() 
END CATCH 

並調用它通過array

+0

嗨abcool,謝謝你的幫助。令我困惑的是,update_product_xml_tvp已經是一個存儲過程。如果你注意到這個過程,我用光標在我的代碼上使用,但是光標的性能太慢了。 –

+0

我幾個月前曾經有過同樣的事情,我需要在單次插入時多次將多個值插入到2個表中。所以,直到現在,我沒有任何緩慢或任何錯誤,實際上我喜歡它。所以我建議你是複製你的代碼,並創建備份和刪除過程和/(或創建新的)類型和過程像上面,並告訴我你從哪個平臺使用這個過程?所以我可以提供提示,如果我可以 – abcool

相關問題