복붙노트

[SQL] SQL - 전화는 각 레코드에 대해 저장 프로 시저

SQL

SQL - 전화는 각 레코드에 대해 저장 프로 시저

나는 선택 성명의 각 레코드에 대해 저장 프로 시저를 호출 할 수있는 방법을 찾고 있어요.

SELECT @SomeIds = (
    SELECT spro.Id 
    FROM SomeTable as spro
    INNER JOIN [Address] addr ON addr.Id = spro.Id 
    INNER JOIN City cty ON cty.CityId = addr.CityId
    WHERE cty.CityId = @CityId
)


WHILE @SomeIds  IS NOT NULL
BEGIN
    EXEC UpdateComputedFullText @SomeIds
END

위의 이러한 것은 물론 작동하지 않습니다,하지만 그런 일을 할 수있는 방법은 무엇입니까?

해결법

  1. ==============================

    1.당신은 그것을 위해 커서를 사용해야합니다.

    당신은 그것을 위해 커서를 사용해야합니다.

    DECLARE @oneid int -- or the appropriate type
    
    DECLARE the_cursor CURSOR FAST_FORWARD
    FOR SELECT spro.Id  
        FROM SomeTable as spro 
            INNER JOIN [Address] addr ON addr.Id = spro.Id  
            INNER JOIN City cty ON cty.CityId = addr.CityId 
        WHERE cty.CityId = @CityId
    
    OPEN the_cursor
    FETCH NEXT FROM the_cursor INTO @oneid
    
    WHILE @@FETCH_STATUS = 0
    BEGIN
        EXEC UpdateComputedFullText @oneid
    
        FETCH NEXT FROM the_cursor INTO @oneid
    END
    
    CLOSE the_cursor
    DEALLOCATE the_cursor
    
  2. ==============================

    2.놀란 아무도 당신에게 최신 답을주지 않았다. 커서는 나쁜. 당신이 원하는 것은 CROSS이 적용 사용 후 테이블 반환 함수 (TVF)로 SP의 논리를 이동하는 것입니다

    놀란 아무도 당신에게 최신 답을주지 않았다. 커서는 나쁜. 당신이 원하는 것은 CROSS이 적용 사용 후 테이블 반환 함수 (TVF)로 SP의 논리를 이동하는 것입니다

    여기에 내가 어제 쓴 쿼리가 (적용 단지 CROSS 보면, 세부 사항에없는 체류 할). 십자가는 테이블의 조합을 만들어 적용 할 수 있습니다. 이 조합의 각 요소는 select 문의 행 항목에 매개 변수화 된 TVF에서 생성됩니다.

    SELECT supt.hostname,supt.scriptname, COUNT(*)
    FROM Event_Pagehit eph
        INNER JOIN Symboltable_urlpair supf
        ON eph.fromPagePair=supf.id
        INNER JOIN Symboltable_urlpair supt
        ON supt.id=eph.toPagePair
    CROSS APPLY dbo.TDFCompanyFormationsUrlClassification(supf.hostname,supf.scriptname) as x
    CROSS APPLY dbo.TDFCompanyFormationsUrlClassification(supt.hostname,supt.scriptname) as y
    WHERE x.isCompanyFormations=1
    AND y.isCompanyFormations=0
    GROUP BY supt.hostname,supt.scriptname
    ORDER BY COUNT(*) desc
    

    그들이 또는 가입 조항에서 당겨 테이블 것처럼 나는 x와 y를 사용할 수 있습니다. 나는 TVF없이 쿼리를 작성해야한다면 그것은 백 개 라인의 몇 가지에 걸쳐 것이다.

    노트 :

    당신은 SP를 다시 작성할 수없는 경우 당신은 테이블 반환 함수에서 결과 테이블에 저장 프로 시저의 결과를 삽입 할 수 있어야한다. 그렇지 않으면 나는이 경우 가정 누군가가 말했다 그래서하지 않는 한 -이 일을 적이없는, 때로는 다른 SQL 서버 구조는주의 사항이 있습니다.

  3. ==============================

    3.각 행을 통해 다음으로 반복 임시 테이블 변수로 ID를 넣고 : (당신은 상당히 느려집니다 커서를 사용할 필요가 없습니다)

    각 행을 통해 다음으로 반복 임시 테이블 변수로 ID를 넣고 : (당신은 상당히 느려집니다 커서를 사용할 필요가 없습니다)

       Declare @Keys Table (key integer Primary Key Not Null)
       Insert @Keys(key)
       SELECT spro.Id  
       FROM SomeTable as spro 
           JOIN [Address] addr ON addr.Id = spro.Id  
           JOIN City cty ON cty.CityId = addr.CityId 
       WHERE cty.CityId = @CityId
       -- -------------------------------------------
       Declare @Key Integer
       While Exists (Select * From @Keys)
         Begin
             Select @Key = Max(Key) From @Keys
             EXEC UpdateComputedFullText @Key
             Delete @Keys Where Key = @Key
         End 
    

    이처럼, 매우 좁은 고유 인덱스에 대해 구동되는 필터 조건 함께 사용하면 삭제 편집 속도가 느린되지 않습니다. 그러나 그것은 쉽게 단지 다음과 같이 루프를함으로써 피할 수있다 :

    Declare @Key Integer = 0
    While Exists (Select * From @Keys
                  Where key > @Key)
     Begin
         Select @Key = Min(Key) From @Keys
                       Where key > @Key
         EXEC UpdateComputedFullText @Key
         -- Delete @Keys Where Key = @Key No Longer necessary 
     End    
    
  4. ==============================

    4.커서없이이 일을보십시오

    커서없이이 일을보십시오

    DECLARE @id int 
    
    SELECT top 1 @id = spro.Id   
        FROM SomeTable as spro  
            INNER JOIN [Address] addr ON addr.Id = spro.Id   
            INNER JOIN City cty ON cty.CityId = addr.CityId  
        WHERE cty.CityId = @CityId
        ORDER BY spro.id
    
    WHILE @@ROWCOUNT > 0 
    BEGIN 
        EXEC UpdateComputedFullText @id 
    
        SELECT top 1 @id = spro.Id   
        FROM SomeTable as spro  
            INNER JOIN [Address] addr ON addr.Id = spro.Id   
            INNER JOIN City cty ON cty.CityId = addr.CityId  
        WHERE cty.CityId = @CityId 
        and spro.id > @id
        ORDER BY spro.id
    END 
    
  5. ==============================

    5.RE 커서 위의 답변은 모두 정확합니다. 그러나, 커서의 코드 실행 내부의 복잡성에 따라, 당신은 더 나은 선택의 여지가 귀하의 언어로이를 삭제하고 데이터베이스에 결과를 삭제하기 전에 코드에서 계산을 수행에서 제공 할 수있다.

    RE 커서 위의 답변은 모두 정확합니다. 그러나, 커서의 코드 실행 내부의 복잡성에 따라, 당신은 더 나은 선택의 여지가 귀하의 언어로이를 삭제하고 데이터베이스에 결과를 삭제하기 전에 코드에서 계산을 수행에서 제공 할 수있다.

    나는 나 자신이 돌아가서 커서 작업을 많이 검토하고, 많은 경우에 성능 향상을 위해 코드에 이러한 전환을 발견했습니다.

  6. ==============================

    6.SQL 서버 커서 예 : 당신은 커서를 사용해야합니다

    SQL 서버 커서 예 : 당신은 커서를 사용해야합니다

    DECLARE @id int
    DECLARE cursor_sample CURSOR FOR  
    SELECT spro.Id 
    FROM SomeTable as spro
        INNER JOIN [Address] addr ON addr.Id = spro.Id 
        INNER JOIN City cty ON cty.CityId = addr.CityId
    WHERE cty.CityId = @CityId
    
    OPEN cursor_sample
    FETCH NEXT FROM cursor_sample INTO @id 
    WHILE @@FETCH_STATUS = 0   
    BEGIN  
        EXEC UpdateComputedFullText @id
        FETCH NEXT FROM cursor_sample INTO @id
    END   
    
    CLOSE cursor_sample
    DEALLOCATE cursor_sample
    
  7. ==============================

    7.당신은 정말 세트 처리를 사용할 수있을 때 행 단위가 처리해야합니까?

    당신은 정말 세트 처리를 사용할 수있을 때 행 단위가 처리해야합니까?

    그런 다음, 임시 테이블에 SELECT의 결과를 넣어 임시 테이블의 내용에 대해 대량 SQL을 수행하기 위해 시저를 호출 할 수 있습니다. 임시 테이블은 T-SQL 범위 지정 규칙에 따라 호출 시저에 사용할 수 있습니다.

  8. ==============================

    8.표준 커서 솔루션은 악에 따라 악이다. 두 개의 동일한 FETCH NEXT 문은 유지 보수 악몽이다.

    표준 커서 솔루션은 악에 따라 악이다. 두 개의 동일한 FETCH NEXT 문은 유지 보수 악몽이다.

    더 나은입니다

    ...declare cursor etc.
    While 1=1
     Fetch ...
     if @@FETCH_STATUS <> 0  BREAK
    ...
    End -- While 
    ..Close cursor etc.
    

    악은 때때로 정당화. 그냥 sp_send_dbmail 또는 다른 저장 프로 시저를 사용하여 알림 이메일을 보내는에 대한 설정 기반의 접근 방식을 고안하려고합니다.

  9. from https://stackoverflow.com/questions/2077948/sql-call-stored-procedure-for-each-record by cc-by-sa and MIT license