복붙노트

[SQL] T-SQL에서 테이블 변수를 통해 할 수 있습니까 루프?

SQL

T-SQL에서 테이블 변수를 통해 할 수 있습니까 루프?

T-SQL에서 테이블 변수를 통해 루프 어쨌든이 있나요?

DECLARE @table1 TABLE ( col1 int )  
INSERT into @table1 SELECT col1 FROM table2

나는뿐만 아니라 커서를 사용하지만, 커서는 테이블 변수보다 유연성이 보인다.

DECLARE cursor1 CURSOR  
    FOR SELECT col1 FROM table2  
OPEN cursor1  
FETCH NEXT FROM cursor1

나는 커서와 동일한 방식으로 테이블 변수를 사용할 수 있도록하고 싶습니다. 그런 식으로 나는 절차의 한 부분에 테이블 변수에 대한 몇 가지 쿼리를 실행 한 다음 나중에 테이블 변수의 각 행에 대해 몇 가지 코드를 실행할 수 있습니다.

어떤 도움도 대단히 감사합니다.

해결법

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

    1.테이블 변수에 ID를 추가하고 INSERT-SELECT의 @@ ROWCOUNT 1에서 쉽게 루프를 않습니다.

    테이블 변수에 ID를 추가하고 INSERT-SELECT의 @@ ROWCOUNT 1에서 쉽게 루프를 않습니다.

    이 시도:

    DECLARE @RowsToProcess  int
    DECLARE @CurrentRow     int
    DECLARE @SelectCol1     int
    
    DECLARE @table1 TABLE (RowID int not null primary key identity(1,1), col1 int )  
    INSERT into @table1 (col1) SELECT col1 FROM table2
    SET @RowsToProcess=@@ROWCOUNT
    
    SET @CurrentRow=0
    WHILE @CurrentRow<@RowsToProcess
    BEGIN
        SET @CurrentRow=@CurrentRow+1
        SELECT 
            @SelectCol1=col1
            FROM @table1
            WHERE RowID=@CurrentRow
    
        --do your thing here--
    
    END
    
  2. ==============================

    2.

    DECLARE @table1 TABLE (
        idx int identity(1,1),
        col1 int )
    
    DECLARE @counter int
    
    SET @counter = 1
    
    WHILE(@counter < SELECT MAX(idx) FROM @table1)
    BEGIN
        DECLARE @colVar INT
    
        SELECT @colVar = col1 FROM @table1 WHERE idx = @counter
    
        -- Do your work here
    
        SET @counter = @counter + 1
    END
    

    믿거 나 말거나,이 실제로 커서를 사용하는 것보다 더 효율적이고 성능이 좋은 것입니다.

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

    3.당신은 하나 개의 변수를 삭제하려면 내 두 센트 .. KM.의 대답에서, 당신은 카운트 업 대신 @RowsToProcess에 카운트 다운을 할 수 있습니다.

    당신은 하나 개의 변수를 삭제하려면 내 두 센트 .. KM.의 대답에서, 당신은 카운트 업 대신 @RowsToProcess에 카운트 다운을 할 수 있습니다.

    DECLARE @RowsToProcess  int;
    
    DECLARE @table1 TABLE (RowID int not null primary key identity(1,1), col1 int )  
    INSERT into @table1 (col1) SELECT col1 FROM table2
    SET @RowsToProcess = @@ROWCOUNT 
    
    WHILE @RowsToProcess > 0 -- Countdown
    BEGIN
        SELECT *
            FROM @table1
            WHERE RowID=@RowsToProcess
    
        --do your thing here--
    
        SET @RowsToProcess = @RowsToProcess - 1; -- Countdown
    END
    
  4. ==============================

    4.당신은 루프 테이블 변수를 통해 할 수 또는 당신은 그것을 통해 커서 수 있습니다. 발음 Reebar 수단 행별로 괴로운 - 행 - 이것은 우리가 일반적으로 RBAR을 부르는 것이다.

    당신은 루프 테이블 변수를 통해 할 수 또는 당신은 그것을 통해 커서 수 있습니다. 발음 Reebar 수단 행별로 괴로운 - 행 - 이것은 우리가 일반적으로 RBAR을 부르는 것이다.

    나는 귀하의 질문에 SET 기반의 답을 찾는 제안 (우리가 도울 수)과 가능한 한 rbars에서 벗어나 것이다.

  5. ==============================

    5.이 데모 같이 :

    이 데모 같이 :

    DECLARE @vTable TABLE (IdRow int not null primary key identity(1,1),ValueRow int);
    
    -------Initialize---------
    insert into @vTable select 345;
    insert into @vTable select 795;
    insert into @vTable select 565;
    ---------------------------
    
    DECLARE @cnt int = 1;
    DECLARE @max int = (SELECT MAX(IdRow) FROM @vTable);
    
    WHILE @cnt <= @max
    BEGIN
        DECLARE @tempValueRow int = (Select ValueRow FROM @vTable WHERE IdRow = @cnt);
    
        ---work demo----
        print '@tempValueRow:' + convert(varchar(10),@tempValueRow);
        print '@cnt:' + convert(varchar(10),@cnt);
        print'';
        --------------
    
        set @cnt = @cnt+1;
    END
    

    idRow없이 버전, 사용 ROW_NUMBER

        DECLARE @vTable TABLE (ValueRow int);
    -------Initialize---------
    insert into @vTable select 345;
    insert into @vTable select 795;
    insert into @vTable select 565;
    ---------------------------
    
    DECLARE @cnt int = 1;
    DECLARE @max int = (select count(*) from @vTable);
    
    WHILE @cnt <= @max
    BEGIN
        DECLARE @tempValueRow int = (
            select ValueRow 
            from (select ValueRow
                , ROW_NUMBER() OVER(ORDER BY (select 1)) as RowId 
                from @vTable
            ) T1 
        where t1.RowId = @cnt
        );
    
        ---work demo----
        print '@tempValueRow:' + convert(varchar(10),@tempValueRow);
        print '@cnt:' + convert(varchar(10),@cnt);
        print'';
        --------------
    
        set @cnt = @cnt+1;
    END
    
  6. ==============================

    6.여기 내 변형입니다. 꽤 많은 단지 다른 모든처럼,하지만 난 단지 루프를 관리하는 하나 개의 변수를 사용합니다.

    여기 내 변형입니다. 꽤 많은 단지 다른 모든처럼,하지만 난 단지 루프를 관리하는 하나 개의 변수를 사용합니다.

    DECLARE
      @LoopId  int
     ,@MyData  varchar(100)
    
    DECLARE @CheckThese TABLE
     (
       LoopId  int  not null  identity(1,1)
      ,MyData  varchar(100)  not null
     )
    
    
    INSERT @CheckThese (MyData)
     select MyData from MyTable
     order by DoesItMatter
    
    SET @LoopId = @@rowcount
    
    WHILE @LoopId > 0
     BEGIN
        SELECT @MyData = MyData
         from @CheckThese
         where LoopId = @LoopId
    
        --  Do whatever
    
        SET @LoopId = @LoopId - 1
     END
    

    라즈 더의 포인트는 관련이 - 당신이있는 경우에만 루프를 수행합니다.

  7. ==============================

    7.여기 저스틴과 비슷한 또 다른 대답은,하지만 신원 또는 집계, 단지 주 (독특한) 키가 필요하지 않습니다.

    여기 저스틴과 비슷한 또 다른 대답은,하지만 신원 또는 집계, 단지 주 (독특한) 키가 필요하지 않습니다.

    declare @table1 table(dataKey int, dataCol1 varchar(20), dataCol2 datetime)
    declare @dataKey int
    while exists select 'x' from @table1
    begin
        select top 1 @dataKey = dataKey 
        from @table1 
        order by /*whatever you want:*/ dataCol2 desc
    
        -- do processing
    
        delete from @table1 where dataKey = @dataKey
    end
    
  8. ==============================

    8.나는 WHILE 구조에 대해 알고하지 않았다.

    나는 WHILE 구조에 대해 알고하지 않았다.

    테이블 변수와 함께 WHILE 구조는, 그러나, 당신은 여전히 ​​효과적이다 FETCH 행 IDENTITY를 기반으로 변수에 행을 선택해야한다는 점에서, 커서를 사용하여 비슷합니다.

    WHERE 뭔가 다음과 같이 사용하는 사이에 어떤 차이가 있나요?

    DECLARE @table1 TABLE ( col1 int )  
    INSERT into @table1 SELECT col1 FROM table2
    
    DECLARE cursor1 CURSOR  
        FOR @table1
    OPEN cursor1  
    FETCH NEXT FROM cursor1
    

    그도 가능 모르겠어요. 나는이 작업을 수행해야 할 수도 있습니다 가정 :

    DECLARE cursor1 CURSOR  
        FOR SELECT col1 FROM @table1
    OPEN cursor1  
    FETCH NEXT FROM cursor1
    

    도와 주셔서 감사합니다!

  9. ==============================

    9.여기에 동일한 솔루션의 내 버전은 ...

    여기에 동일한 솔루션의 내 버전은 ...

        declare @id int
    
            SELECT @id = min(fPat.PatientID)
            FROM tbPatients fPat
            WHERE (fPat.InsNotes is not null AND DataLength(fPat.InsNotes)>0)
    
    while @id is not null
    begin
        SELECT fPat.PatientID, fPat.InsNotes
        FROM tbPatients fPat
        WHERE (fPat.InsNotes is not null AND DataLength(fPat.InsNotes)>0) AND fPat.PatientID=@id
    
        SELECT @id = min(fPat.PatientID)
        FROM tbPatients fPat
        WHERE (fPat.InsNotes is not null AND DataLength(fPat.InsNotes)>0)AND fPat.PatientID>@id
    
    end
    
  10. ==============================

    10.테이블 변수와 오름차순으로 인쇄를 통해 저장 프로 시저 루프를 따라. 이 예는 while 루프를 사용하고 있습니다.

    테이블 변수와 오름차순으로 인쇄를 통해 저장 프로 시저 루프를 따라. 이 예는 while 루프를 사용하고 있습니다.

    CREATE PROCEDURE PrintSequenceSeries 
        -- Add the parameters for the stored procedure here
        @ComaSeperatedSequenceSeries nVarchar(MAX)  
    AS
    BEGIN
        -- SET NOCOUNT ON added to prevent extra result sets from
        -- interfering with SELECT statements.
        SET NOCOUNT ON;
    
        DECLARE @SERIES_COUNT AS INTEGER
        SELECT @SERIES_COUNT = COUNT(*) FROM PARSE_COMMA_DELIMITED_INTEGER(@ComaSeperatedSequenceSeries, ',')  --- ORDER BY ITEM DESC
    
        DECLARE @CURR_COUNT AS INTEGER
        SET @CURR_COUNT = 1
    
        DECLARE @SQL AS NVARCHAR(MAX)
    
        WHILE @CURR_COUNT <= @SERIES_COUNT
        BEGIN
            SET @SQL = 'SELECT TOP 1 T.* FROM ' + 
                '(SELECT TOP ' + CONVERT(VARCHAR(20), @CURR_COUNT) + ' * FROM PARSE_COMMA_DELIMITED_INTEGER( ''' + @ComaSeperatedSequenceSeries + ''' , '','') ORDER BY ITEM ASC) AS T ' +
                'ORDER BY T.ITEM DESC '
            PRINT @SQL 
            EXEC SP_EXECUTESQL @SQL 
            SET @CURR_COUNT = @CURR_COUNT + 1
        END;
    

    문이 실행을 저장 프로 시저에 따라 :

    EXEC  PrintSequenceSeries '11,2,33,14,5,60,17,98,9,10'
    

    SQL 쿼리 창에 표시되는 결과는 다음과 같습니다 :

    반환 TABLE 변수는 아래 도시 된 바와 같이 그 기능 PARSE_COMMA_DELIMITED_INTEGER () :

    CREATE FUNCTION [dbo].[parse_comma_delimited_integer]
            (
                @LIST       VARCHAR(8000), 
                @DELIMITER  VARCHAR(10) = ',
                '
            )
    
            -- TABLE VARIABLE THAT WILL CONTAIN VALUES
            RETURNS @TABLEVALUES TABLE 
            (
                ITEM INT
            )
            AS
            BEGIN 
                DECLARE @ITEM VARCHAR(255)
    
                /* LOOP OVER THE COMMADELIMITED LIST */
                WHILE (DATALENGTH(@LIST) > 0)
                    BEGIN 
                        IF CHARINDEX(@DELIMITER,@LIST) > 0
                            BEGIN
                                SELECT @ITEM = SUBSTRING(@LIST,1,(CHARINDEX(@DELIMITER, @LIST)-1))
                                SELECT @LIST =  SUBSTRING(@LIST,(CHARINDEX(@DELIMITER, @LIST) +
                                DATALENGTH(@DELIMITER)),DATALENGTH(@LIST))
                            END
                        ELSE
                            BEGIN
                                SELECT @ITEM = @LIST
                                SELECT @LIST = NULL
                            END
    
                        -- INSERT EACH ITEM INTO TEMP TABLE
                        INSERT @TABLEVALUES 
                        (
                            ITEM
                        )
                        SELECT ITEM = CONVERT(INT, @ITEM) 
                    END
            RETURN
            END
    
  11. from https://stackoverflow.com/questions/1578198/can-i-loop-through-a-table-variable-in-t-sql by cc-by-sa and MIT license