2016-07-26 12 views
0

Ich habe eine gespeicherte Prozedur, die einen ID-Parameter empfängt und Einfügevorgänge/Aktualisierungen durchführt.T-SQL: Prozedur zum Abrufen des Parameterwerts aus Tabelle ausführen (SQL Server 2012)

Ich habe etwa 25K Datensätze, die aktualisiert werden müssen, und ich habe versucht, eine Möglichkeit zur Verbesserung der einzelnen gespeicherten Parameterprozedur herauszufinden, so dass es mehrere Werte oder Mengen von IDs aus einer Tabelle verarbeiten kann.

Am nächsten komme ich dazu, indem ich einen Cursor erzeuge und während der Ausführung der Stored Procedure hindurchschleiche, leider habe ich erkannt, dass dies ein sehr langsamer Weg ist.

Ich fragte mich, ob ich Hilfe bekommen könnte, meine gespeicherte Prozedur zu ändern, damit sie eine bessere Leistung haben kann.

Hier ist mein Code, der einen Cursor verwendet.

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

Empfehlung ObjectNotFound gemacht Folgende:

--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 

Das Problem, das ich bin vor ist mit der ursprünglichen gespeicherte Prozedur oder Schritt # 2. Das einzige, was ich änderte, war der Name und der Parametertyp, aber wenn ich versuche, die Änderungen zu speichern, erhalte ich Fehler wie:

Msg 137, Level 16, Status 1, Prozedur update_product_xml_tvp, Zeile 43 Muss den Skalar deklarieren Variable "@id".

Diese skalare Variable, über die sich die Nachricht beschweren, ist derselbe Parameter, den ich gerade von Varchar zu Tabellentyp geändert habe. Ich bin mir nicht sicher, wie ich hier vorgehen soll, oder ob ich die Schritte falsch gemacht habe. Jede Hilfe ist großartig, danke.

Antwort

2

Sie benötigen Table Valued Parameter als Eingabe für Ihre gespeicherte Prozedur (update_product_xml_single_id). Anstatt also einen Skalarwert vom Typ int (@Id) zu übergeben, übergeben Sie eine Liste (z. B. @TVP), die alle IDs enthält, die Sie gerade bearbeiten, aus der Tabelle "table" in Ihrem OP. Und innerhalb Ihrer gespeicherten Prozedur können Sie diese Tabellenvariable @TVP wie jede andere gewöhnliche Tabelle verwenden.

Diese Verbindungen zeigen Sie, wie es mit einem Beispiel zu tun (ich habe kopiere das Beispiel unten):

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

Beispiel aus dem oben Msdn Link:

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 

Nutzungs Übergeben des TVP an die gespeicherte Prozedur:

/* 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 

EDIT:

Getestet habe ich nur Ihre SP Code erstellen und es funktioniert gut das ist, was ich versucht

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 

Auch die "IN" ist in Ihrem Insert-Anweisung fehlt

Diese :

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

Sollte

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

Ich habe den INTO-Teil zu meinem Code hinzugefügt. Aber es gibt mir immer noch den gleichen Fehler. Ich möchte sicherstellen, dass Sie wissen, dass die gespeicherte Prozedur update_product_xml_tvp die gleiche gespeicherte Prozedur ist, die ich mit dem CURSOR verwendet habe, dass das einzige, was ich darin änderte, der Eingabeparametertyp war. Früher war es so: @pf_id VARCHAR (100)

und jetzt ist es: @id id NURLESE-

Da ich nichts in den Code in dieser Prozedur geändert hat, der Fehler kommt von Abschnitten wie: WHERE ai.ID = @id

Etwas sieht nicht richtig aus, wie @id ist nicht mehr der gleiche Datentyp wie ai.id daher der Vergleich ist nicht mehr gültig, aber ich weiß nicht, wie es zu korrigieren ist, oder wo.

So um sicherzustellen, dass dies richtig ist, ich am Ende mit

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) 

Innerhalb dieses Verfahrens gibt es 4 WHERE-Bedingungen, die ich nicht geändert habe, noch verändert, und die mir Fehler geben, die nicht lassen Sie mich die gespeicherte Prozedur aktualisieren:

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

Mein Verständnis ist, dass am Ende, ich in der Lage sein wird, die folgenden von einem neuen Abfragefenster zu tun:

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 

Ich bin mir sicher, dass ich etwas hier oben vermasselt habe. Ich versuche wirklich, es richtig zu machen. Vielen Dank für Ihre Geduld und Hilfe.

+0

Vielen Dank objectNotFound, es ist ein bisschen verwirrend, wie ich die Änderungen in meinem Code implementieren soll Aber ich werde es versuchen. –

+0

@erasmocarlos es ist ziemlich einfach vorwärts ... die letzten 3 Aussagen in dem Beispiel, das ich kopiere/klebte, sind außerhalb des SP. Ich werde den Beitrag bearbeiten, um das zu klären. – objectNotFound

+0

der erste Abschnitt Schritt 2, warum ruft die Einfügung Daten aus einer Tabelle namens Location, und dann auf den letzten drei Anweisungen in der Einfügeanweisung, die TVP wird mit Daten aus einer anderen Tabelle aufgefüllt. –

0

Ich bin Anfänger, aber ich denke, das wird Ihnen helfen, es zu versuchen.

erstellen benutzerdefinierte Funktion

< --step 1: ->

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

jetzt < --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 

und nennen es durch Array

+0

Hallo abcool und danke für deine Hilfe. Was mich verwirrt ist, dass update_product_xml_tvp, war bereits eine gespeicherte Prozedur. Das ist die Prozedur, die, wenn Sie bemerken, ich auf meinem Code mit dem Cursor verwendet habe, aber die cursoer Leistung ist zu langsam. –

+0

Ich hatte die gleiche Sache, paar Monate zurück, wo ich mehrere Wert auf 2 Tabelle mehrere Male bei einmaligem Einfügen einfügen müssen. so, bis jetzt habe ich keinen langsamen oder irgendeinen fehler davon tatsächlich ich mochte es. Also, was ich schlage vor, Sie kopieren Sie Ihren Code und erstellen Sie sichern und löschen Sie die Prozedur und/(oder neue erstellen) Tabelle Typ und Vorgehensweise wie oben und sagen Sie mir, von welcher Plattform Sie diese Prozedur aufrufen? damit ich einen Hinweis geben kann, wenn ich kann – abcool