[sql] 커서를 사용하지 않고 각 행에 대한 SQL 호출 저장 프로 시저

커서 사용 하지 않고 행의 열이 sp에 대한 입력 매개 변수 인 테이블의 각 행에 대해 저장 프로 시저를 어떻게 호출 할 수 있습니까?



답변

일반적으로 말하면 항상 세트 기반 접근 방식을 찾습니다 (때로는 스키마 변경 비용을 희생).

그러나이 스 니펫은 그 자리에 있습니다 ..

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


답변

예를 들어, AdventureWorks Sales.Customer샘플 테이블을 사용하여 CustomerID로 테이블을 주문 하고 WHILE 루프를 사용하여 해당 고객을 반복하십시오.

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

ORDER BY어떤 열에 어떤 종류의 열을 정의 할 수 있다면 어떤 테이블에서도 작동합니다 .


답변

DECLARE @SQL varchar(max)=''

-- MyTable has fields fld1 & fld2

Select @SQL = @SQL + 'exec myproc ' + convert(varchar(10),fld1) + ','
                   + convert(varchar(10),fld2) + ';'
From MyTable

EXEC (@SQL)

좋아, 그런 코드를 프로덕션에 넣지 않을 것이지만 요구 사항을 충족시킵니다.


답변

마크의 대답은 좋다 (I 방법으로 해결할 수 있다면 그것에 대해 언급 것!)
그냥 내가 그래서는 루프를 변경하는 것이 더 나은 수 있음을 지적 줄 알았는데 SELECT나만에 필요한 실제 경우에 (한 번 존재 이 작업 SELECT은 매우 복잡했으며 두 번 작성하면 유지 관리 문제가 위험했습니다.

-- define the last customer ID handled
DECLARE @LastCustomerID INT
SET @LastCustomerID = 0
-- define the customer ID to be handled now
DECLARE @CustomerIDToHandle INT
SET @CustomerIDToHandle = 1

-- as long as we have customers......    
WHILE @LastCustomerID <> @CustomerIDToHandle
BEGIN
  SET @LastCustomerId = @CustomerIDToHandle
  -- select the next customer to handle    
  SELECT TOP 1 @CustomerIDToHandle = CustomerID
  FROM Sales.Customer
  WHERE CustomerID > @LastCustomerId
  ORDER BY CustomerID

  IF @CustomerIDToHandle <> @LastCustomerID
  BEGIN
      -- call your sproc
  END

END


답변

스토어드 프로 시저를 테이블을 리턴하는 함수로 변환 할 수 있으면 교차 적용을 사용할 수 있습니다.

예를 들어, 고객 테이블이 있고 주문 합계를 계산하려는 경우 CustomerID를 가져 와서 합계를 리턴하는 함수를 작성하려고합니다.

그리고 당신은 이것을 할 수 있습니다 :

SELECT CustomerID, CustomerSum.Total

FROM Customers
CROSS APPLY ufn_ComputeCustomerTotal(Customers.CustomerID) AS CustomerSum

기능은 다음과 같습니다.

CREATE FUNCTION ComputeCustomerTotal
(
    @CustomerID INT
)
RETURNS TABLE
AS
RETURN
(
    SELECT SUM(CustomerOrder.Amount) AS Total FROM CustomerOrder WHERE CustomerID = @CustomerID
)

분명히 위의 예는 단일 쿼리에서 사용자 정의 함수없이 수행 될 수 있습니다.

단점은 함수가 매우 제한되어 있다는 것입니다. 저장 프로 시저의 많은 기능은 사용자 정의 함수에서 사용할 수 없으며 저장 프로 시저를 함수로 변환하는 것이 항상 작동하지는 않습니다.


답변

허용 된 답변을 사용하지만 다른 가능성은 테이블 변수를 사용하여 번호가 매겨진 값 세트 (이 경우 테이블의 ID 필드)를 보유하고 행 번호를 기준으로 테이블에 JOIN을 사용하여 반복합니다. 루프 내에서 필요한 조치를 검색하십시오.

DECLARE @RowCnt int; SET @RowCnt = 0 -- Loop Counter

-- Use a table variable to hold numbered rows containg MyTable's ID values
DECLARE @tblLoop TABLE (RowNum int IDENTITY (1, 1) Primary key NOT NULL,
     ID INT )
INSERT INTO @tblLoop (ID)  SELECT ID FROM MyTable

  -- Vars to use within the loop
  DECLARE @Code NVarChar(10); DECLARE @Name NVarChar(100);

WHILE @RowCnt < (SELECT COUNT(RowNum) FROM @tblLoop)
BEGIN
    SET @RowCnt = @RowCnt + 1
    -- Do what you want here with the data stored in tblLoop for the given RowNum
    SELECT @Code=Code, @Name=LongName
      FROM MyTable INNER JOIN @tblLoop tL on MyTable.ID=tL.ID
      WHERE tl.RowNum=@RowCnt
    PRINT Convert(NVarChar(10),@RowCnt) +' '+ @Code +' '+ @Name
END


답변

SQL Server 2005 이후 버전에서는 CROSS APPLY 및 테이블 반환 함수를 사용 하여이 작업을 수행 할 수 있습니다 .

명확히하기 위해 저장 프로 시저를 테이블 값 함수로 변환 할 수있는 경우를 언급하고 있습니다.