복붙노트

[SQL] 각 행은 쿼리에 의해 반환에 대해 한 번 어떻게 저장 프로 시저를 실행합니까?

SQL

각 행은 쿼리에 의해 반환에 대해 한 번 어떻게 저장 프로 시저를 실행합니까?

내가 저장 프로 시저를 그 어떤 방법으로 변경합니다 사용자 데이터가. 나는 그것을 user_id를 통과하고 그것의 일을한다. 나는 테이블에 쿼리를 실행하려면 다음 각 user_id를 위해 그 USER_ID에 한 번 저장 프로 시저를 실행 찾을

어떻게 이것에 대한 쿼리를 작성합니다?

해결법

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

    1.커서를 사용

    커서를 사용

    ADDENDUM : MS SQL 커서 예]

    declare @field1 int
    declare @field2 int
    declare cur CURSOR LOCAL for
        select field1, field2 from sometable where someotherfield is null
    
    open cur
    
    fetch next from cur into @field1, @field2
    
    while @@FETCH_STATUS = 0 BEGIN
    
        --execute your sproc on each row
        exec uspYourSproc @field1, @field2
    
        fetch next from cur into @field1, @field2
    END
    
    close cur
    deallocate cur
    

    MS SQL에서, 여기에 예를 들어 기사입니다

    참고 커서는 집합 기반 작업보다 느린, 그러나 빠른 수동 동안-루프에 비해 것을; 이 SO 질문에 자세한 내용은

    부칙 2 : 먼저 임시 테이블로 끌어와 임시 테이블 위에 커서를 실행, 더 몇 가지 기록에 비해 처리 될 경우; 이 테이블 잠금으로 확대에서 SQL을 방지하고 작업 속도가 향상됩니다

    부칙 3 : 당신이 당신의 저장 프로 시저가 각 사용자의 ID로하고있다이든 인라인 단일 SQL UPDATE 문으로 모든 일을 실행할 수 있는지 물론, 그 최적의 것

  2. ==============================

    2.당신이 루프 필요하면 방법을 변경하려고!

    당신이 루프 필요하면 방법을 변경하려고!

    부모 저장 프로 시저 내에서, 당신이 처리해야하는 데이터가 포함 된 #temp 테이블을 만들 수 있습니다. 아이 저장 프로 시저를 호출합니다 #temp 테이블을 볼 수 있습니다 당신은 희망이 전체 데이터 세트 및 커서 또는 루프없이 작업을 처리 할 수 ​​있습니다.

    이건 정말 저장 프로 시저이 아이가 무엇을하고 있는지에 따라 달라집니다. 당신이 UPDATE-ING 경우, 수있는 #temp 테이블에 가입하고 루프없이 모두에게 하나 개의 문장에서 일을 "에서 업데이트". 동일은 INSERT 및 삭제를 위해 수행 할 수 있습니다. 당신이 IF를 여러 업데이트를 할 필요가 있다면 당신은 #temp 테이블과 사용 CASE 문이나 WHERE 조건에서 여러 UPDATE에 사람들을 변환 할 수 있습니다.

    루핑의 사고 방식을 잃는 데이터베이스 시도에서 작업 할 때, 그것은 진짜 성능 드레인 / 잠금 차단의 원인과 처리 속도가 느려집니다. 사방 루프 당신이 경우 시스템은 매우 잘 확장되지 않으며, 사용자가 느린 새로 고침에 대해 불평 시작할 때 속도가 매우 힘들 것입니다.

    당신은 루프에서 전화를하려면이 절차의 내용을 게시, 나는 10 배 9 아웃 내기 할 것이다, 당신은 행 집합에 대한 작업에 쓸 수 있습니다.

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

    3.이 대체 같은 무언가가 당신의 테이블과 필드 이름을 위해 필요합니다.

    이 대체 같은 무언가가 당신의 테이블과 필드 이름을 위해 필요합니다.

    Declare @TableUsers Table (User_ID, MyRowCount Int Identity(1,1)
    Declare @i Int, @MaxI Int, @UserID nVarchar(50)
    
    Insert into @TableUser
    Select User_ID
    From Users 
    Where (My Criteria)
    Select @MaxI = @@RowCount, @i = 1
    
    While @i <= @MaxI
    Begin
    Select @UserID = UserID from @TableUsers Where MyRowCount = @i
    Exec prMyStoredProc @UserID
    Select
    
     @i = @i + 1, @UserID = null
    End
    
  4. ==============================

    4.당신은 동적 쿼리와 함께 할 수 있습니다.

    당신은 동적 쿼리와 함께 할 수 있습니다.

    declare @cadena varchar(max) = ''
    select @cadena = @cadena + 'exec spAPI ' + ltrim(id) + ';'
    from sysobjects;
    exec(@cadena);
    
  5. ==============================

    5.이것은 저장 프로 시저가하고있는 어떤 복제 사용자 정의 함수와 함께 할 수 있습니까?

    이것은 저장 프로 시저가하고있는 어떤 복제 사용자 정의 함수와 함께 할 수 있습니까?

    SELECT udfMyFunction(user_id), someOtherField, etc FROM MyTable WHERE WhateverCondition
    

    udfMyFunction 함수가 어디 있는지 그 사용자 ID에 소요하고 당신이 그것으로 할 필요가 무엇이든 수행합니다.

    조금 더 배경에 대한 http://www.sqlteam.com/article/user-defined-functions를 참조하십시오

    나는 커서 정말 가능하면 피해야한다고 동의합니다. 그리고 그것은 일반적으로 가능하다!

    (물론, 내 대답의 전제는 당신이 아니라 당신은 실제 데이터를 변경하지있는 SP의 출력을 얻기에와 있음을 관심이 있다는 것을. 나는 원래의 질문에서 조금 모호한 "특정 방식으로 변경합니다 사용자 데이터"를 찾아, 그래서 가능한 솔루션이 제공하는 거라고 생각했다. 완전히 당신이 무슨 일을하는지에 따라 달라집니다!)

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

    6.테이블 변수 또는 임시 테이블을 사용합니다.

    테이블 변수 또는 임시 테이블을 사용합니다.

    앞서 언급 한 바와 같이, 커서는 최후의 수단이다. 그것은 자원, 문제의 잠금 장치를 많이 사용하고 방금 제대로 SQL을 사용하는 방법을 이해하지 않는 징후 일 수도 대부분 때문이다.

    (당신은 많은 데이터로 작업하는 경우 또는 메모리에 짧은 대신 임시 테이블을 사용)과 같은 테이블 변수를 만듭니다 :

    DECLARE @menus AS TABLE (
        id INT IDENTITY(1,1),
        parent NVARCHAR(128),
        child NVARCHAR(128));
    

    ID는 중요하다.

    예를 들어, 좋은 데이터와 부모와 자식 교체 관련된 식별자 또는 데이터의 전체 세트에 동작한다.

    예컨대 테이블에 데이터를 삽입합니다 :

    INSERT INTO @menus (parent, child) 
      VALUES ('Some name',  'Child name');
    ...
    INSERT INTO @menus (parent,child) 
      VALUES ('Some other name', 'Some other child name');
    

    몇 가지 변수를 선언 :

    DECLARE @id INT = 1;
    DECLARE @parentName NVARCHAR(128);
    DECLARE @childName NVARCHAR(128);
    

    그리고 마지막으로, 테이블의 데이터에 잠시 루프를 만들 :

    WHILE @id IS NOT NULL
    BEGIN
        SELECT @parentName = parent,
               @childName = child 
            FROM @menus WHERE id = @id;
    
        EXEC myProcedure @parent=@parentName, @child=@childName;
    
        SELECT @id = MIN(id) FROM @menus WHERE id > @id;
    END
    

    임시 테이블에서 첫 번째 선택 페치 데이터입니다. 두 번째 선택 갱신합니다 @id. 행이 선택하지 않은 경우 MIN은 널 (null)을 반환합니다.

    다른 방법은 반복되는 테이블을 행 하였지만, SELECT TOP 1 임시 테이블에서 선택 행을 삭제 :

    WHILE EXISTS(SELECT 1 FROM @menuIDs) 
    BEGIN
        SELECT TOP 1 @menuID = menuID FROM @menuIDs;
    
        EXEC myProcedure @menuID=@menuID;
    
        DELETE FROM @menuIDs WHERE menuID = @menuID;
    END;
    
  7. ==============================

    7.데이브 링콘의 동적 쿼리 방법처럼 나는 그것이 커서를 사용하고 작고 쉽게하지 않는 한. 공유 당신에게 데이브 감사드립니다.

    데이브 링콘의 동적 쿼리 방법처럼 나는 그것이 커서를 사용하고 작고 쉽게하지 않는 한. 공유 당신에게 데이브 감사드립니다.

    그러나 푸른 SQL에서 쿼리에 "별개"내 요구에, 나는 다음과 같은 코드를 수정했습니다 :

    Declare @SQL nvarchar(max);
    -- Set SQL Variable
    -- Prepare exec command for each distinctive tenantid found in Machines 
    SELECT @SQL = (Select distinct 'exec dbo.sp_S2_Laser_to_cache ' + 
                  convert(varchar(8),tenantid) + ';' 
                  from Dim_Machine
                  where iscurrent = 1
                  FOR XML PATH(''))
    
    --for debugging print the sql 
    print @SQL;
    
    --execute the generated sql script
    exec sp_executesql @SQL;
    

    나는이 사람을 도움이되기를 바랍니다 ...

  8. from https://stackoverflow.com/questions/886293/how-do-i-execute-a-stored-procedure-once-for-each-row-returned-by-query by cc-by-sa and MIT license