![]() |
SQL Call Stored Procedure for each Row without using a cursor - Printable Version +- 0Day Forums (https://0day.red) +-- Forum: Coding (https://0day.red/Forum-Coding) +--- Forum: Database (https://0day.red/Forum-Database) +---- Forum: Microsoft SQL Server (https://0day.red/Forum-Microsoft-SQL-Server) +---- Thread: SQL Call Stored Procedure for each Row without using a cursor (/Thread-SQL-Call-Stored-Procedure-for-each-Row-without-using-a-cursor) Pages:
1
2
|
SQL Call Stored Procedure for each Row without using a cursor - hypertragically839984 - 07-31-2023 How can one call a stored procedure for each row in a table, where the columns of a row are input parameters to the sp ***without*** using a Cursor? RE: SQL Call Stored Procedure for each Row without using a cursor - mandaaprgqrwi - 07-31-2023 If you don't what to use a cursor I think you'll have to do it externally (get the table, and then run for each statement and each time call the sp) it Is the same as using a cursor, but only outside SQL. Why won't you use a cursor ? RE: SQL Call Stored Procedure for each Row without using a cursor - greyv - 07-31-2023 I usually do it this way when it's a quite a few rows: 1. Select all sproc parameters in a dataset with SQL Management Studio 2. Right-click -> Copy 3. Paste in to excel 4. Create single-row sql statements with a formula like '="EXEC schema.mysproc @param=" & A2' in a new excel column. (Where A2 is your excel column containing the parameter) 5. Copy the list of excel statements into a new query in SQL Management Studio and execute. 6. Done. (On larger datasets i'd use one of the solutions mentioned above though). RE: SQL Call Stored Procedure for each Row without using a cursor - angeline801659 - 07-31-2023 You could do something like this: order your table by e.g. CustomerID (using the AdventureWorks `Sales.Customer` sample table), and iterate over those customers using a WHILE loop: -- define the last customer ID handled DECLARE @LastCustomerID INT SET @LastCustomerID = 0 -- define the customer ID to be handled now DECLARE @CustomerIDToHandle INT -- select the next customer to handle SELECT TOP 1 @CustomerIDToHandle = CustomerID FROM Sales.Customer WHERE CustomerID > @LastCustomerID ORDER BY CustomerID -- as long as we have customers...... WHILE @CustomerIDToHandle IS NOT NULL BEGIN -- call your sproc -- set the last customer handled to the one we just handled SET @LastCustomerID = @CustomerIDToHandle SET @CustomerIDToHandle = NULL -- select the next customer to handle SELECT TOP 1 @CustomerIDToHandle = CustomerID FROM Sales.Customer WHERE CustomerID > @LastCustomerID ORDER BY CustomerID END That should work with any table as long as you can define some kind of an `ORDER BY` on some column. RE: SQL Call Stored Procedure for each Row without using a cursor - fiorazuw - 07-31-2023 If you can turn the stored procedure into a function that returns a table, then you can use cross-apply. For example, say you have a table of customers, and you want to compute the sum of their orders, you would create a function that took a CustomerID and returned the sum. And you could do this: SELECT CustomerID, CustomerSum.Total FROM Customers CROSS APPLY ufn_ComputeCustomerTotal(Customers.CustomerID) AS CustomerSum Where the function would look like: CREATE FUNCTION ComputeCustomerTotal ( @CustomerID INT ) RETURNS TABLE AS RETURN ( SELECT SUM(CustomerOrder.Amount) AS Total FROM CustomerOrder WHERE CustomerID = @CustomerID ) Obviously, the example above could be done without a user defined function in a single query. The drawback is that functions are very limited - many of the features of a stored procedure are not available in a user-defined function, and converting a stored procedure to a function does not always work. RE: SQL Call Stored Procedure for each Row without using a cursor - annexing639706 - 07-31-2023 For SQL Server 2005 onwards, you can do this with [CROSS APPLY][1] and a table-valued function. - [Using CROSS APPLY in SQL Server 2005][2] Just for clarity, I'm referring to those cases where the stored procedure can be converted into a table valued function. [1]: [To see links please register here] [2]:[To see links please register here] RE: SQL Call Stored Procedure for each Row without using a cursor - dace452 - 07-31-2023 This is a variation of n3rds solution above. No sorting by using ORDER BY is needed, as MIN() is used. Remember that CustomerID (or whatever other numerical column you use for progress) must have a unique constraint. Furthermore, to make it as fast as possible CustomerID must be indexed on. -- Declare & init DECLARE @CustomerID INT = (SELECT MIN(CustomerID) FROM Sales.Customer); -- First ID DECLARE @Data1 VARCHAR(200); DECLARE @Data2 VARCHAR(200); -- Iterate over all customers WHILE @CustomerID IS NOT NULL BEGIN -- Get data based on ID SELECT @Data1 = Data1, @Data2 = Data2 FROM Sales.Customer WHERE [ID] = @CustomerID ; -- call your sproc EXEC dbo.YOURSPROC @Data1, @Data2 -- Get next customerId SELECT @CustomerID = MIN(CustomerID) FROM Sales.Customer WHERE CustomerID > @CustomerId END I use this approach on some varchars I need to look over, by putting them in a temporary table first, to give them an ID. RE: SQL Call Stored Procedure for each Row without using a cursor - surrendering364291 - 07-31-2023 DELIMITER // CREATE PROCEDURE setFakeUsers (OUT output VARCHAR(100)) BEGIN -- define the last customer ID handled DECLARE LastGameID INT; DECLARE CurrentGameID INT; DECLARE userID INT; SET @LastGameID = 0; -- define the customer ID to be handled now SET @userID = 0; -- select the next game to handle SELECT @CurrentGameID = id FROM online_games WHERE id > LastGameID ORDER BY id LIMIT 0,1; -- as long as we have customers...... WHILE (@CurrentGameID IS NOT NULL) DO -- call your sproc -- set the last customer handled to the one we just handled SET @LastGameID = @CurrentGameID; SET @CurrentGameID = NULL; -- select the random bot SELECT @userID = userID FROM users WHERE FIND_IN_SET('bot',baseInfo) ORDER BY RAND() LIMIT 0,1; -- update the game UPDATE online_games SET userID = @userID WHERE id = @CurrentGameID; -- select the next game to handle SELECT @CurrentGameID = id FROM online_games WHERE id > LastGameID ORDER BY id LIMIT 0,1; END WHILE; SET output = "done"; END;// CALL setFakeUsers(@status); SELECT @status; RE: SQL Call Stored Procedure for each Row without using a cursor - katinealeitmymw - 07-31-2023 I like to do something similar to this (though it is still very similar to using a cursor) Code: -- Table variable to hold list of things that need looping Note that you don't *need* the identity or the isIterated column on your temp/variable table, i just prefer to do it this way so i don't have to delete the top record from the collection as i iterate through the loop. RE: SQL Call Stored Procedure for each Row without using a cursor - Sirtachymetryfsm - 07-31-2023 Generally speaking I always look for a set based approach (sometimes at the expense of changing the schema). However, this snippet does have its place.. -- Declare & init (2008 syntax) DECLARE @CustomerID INT = 0 -- Iterate over all customers WHILE (1 = 1) BEGIN -- Get next customerId SELECT TOP 1 @CustomerID = CustomerID FROM Sales.Customer WHERE CustomerID > @CustomerId ORDER BY CustomerID -- Exit loop if no more customers IF @@ROWCOUNT = 0 BREAK; -- call your sproc EXEC dbo.YOURSPROC @CustomerId END |