T-SQL相当于Oracle的收集方法(第一个,最后一个,下一个)?

时间:2013-03-04 17:17:30

标签: sql sql-server oracle

我们正在从Oracle迁移到SQL Server,并且我正在从填充了BULK COLLECT INTO查询的表变量转换查询。我正在考虑使用游标(肯定对其他建议开放),但在处理查询的Oracle代码中,它使用Table_var.FIRST .NEXT.LAST。这是一些如何使用它们的示例代码。看来第一个/下一个/最后一个是为表var的记录提供索引。

TYPE Pers_DOB_LastInitial IS RECORD (
  Person_ID Person.Person_ID%TYPE,
  DOB Person.Birthdate%TYPE,
  LastInitial VARCHAR2(1)
);

TYPE Dup_Table IS TABLE OF Pers_DOB_LastInitial INDEX BY BINARY_INTEGER;

Dup_Tab Dup_Table;

以及使用这些类型的函数:

FUNCTION Last_In_Group( pStart NUMBER, pDOB Person.Birthdate%TYPE, pLastInitial VARCHAR2 )
     RETURN NUMBER IS
  vResult NUMBER;
BEGIN
  IF pStart = Dup_Tab.LAST THEN
     RETURN pStart;
  END IF;

  vResult := pStart;

  FOR vIndex IN pStart .. Dup_Tab.LAST LOOP
     IF Dup_Tab.EXISTS( vIndex ) THEN
        IF Dup_Tab( vIndex ).DOB = pDOB AND Dup_Tab( vIndex ).LastInitial = pLastInitial THEN
           vResult := vIndex;
        ELSE
           EXIT;
        END IF;
     END IF;
  END LOOP;

  RETURN vResult;
END Last_In_Group;

我不需要为我完成编码,只需要指向正确的方向。我正在考虑使用游标,但我唯一熟悉的只是从T-SQL中的游标中获取下一条记录,并希望查看是否有相同的方法来引用游标(或临时表)的行索引)。


编辑:我刚发现以下内容并正在调查中。绝对愿意接受是否这是一条良好的追求途径,或者游标是否仍然更好。

http://www.sql-server-performance.com/2004/operations-no-cursors/2/

DECLARE @dupTab TABLE (
    person_id numeric(8,0),
    DOB date,
    LastInitial char(1)
)

INSERT @dupTab
SELECT ...

3 个答案:

答案 0 :(得分:0)

不是100%肯定您在问什么,但是您是否在Sql Server 2012中查看了新的LEADLAGFIRST_VALUELAST_VALUE关键字?

答案 1 :(得分:0)

假设您的表名为Dup_Tab,而@DOB和@LastInitial是您传入函数的变量,这可能有用吗?

select PersonID from(
select
 rank = row_number() over (order by DOB DESC, LastInitial DESC),
 PersonID
from dup_tab where DOB=@DOB and LastInitial=@LastInitial
) subgroup 
where rank=1

它只是使用窗口化的Rank()函数为每个记录分配一个基于DOB / LastInitial排序的行号,然后你选择rank = 1的行,给你一组人的最后一条记录特定的DOB和LastInitial。

答案 2 :(得分:0)

我将您的示例代码翻译成了SQL-Server对应代码。如果你想逐行处理,最好的方法就是使用FAST_FORWARD游标。

代码:

    IF  EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[Last_In_Group]') AND xtype in (N'FN', N'IF', N'TF'))
        drop function  Last_In_Group
    go

    create function Last_In_Group(@pStart  int, @pDOB date, @pLastInitial varchar(1))
    returns int
    AS
    BEGIN
        DECLARE @Dup_Tab TABLE(
            Person_ID int,
            DOB date,
            LastInitial varchar(1)
        )
        -- populate the table with some data
        insert @Dup_Tab values
        (1, '31.12.2013', 'P'), (2, '24.12.2013', 'C'), (3, '24.12.2013', 'C')

        declare @vResult int = 0,
                @cDOB date,
                @cLastInitial varchar(1)

        if(@vResult = @pStart) return @pStart
        set @vResult = @pStart

        -- loop over your data with a fast cursor
        declare cur cursor FAST_FORWARD for select DOB, LastInitial from @Dup_Tab
        open cur
        fetch next from cur
        into @cDOB, @cLastInitial

        while @@FETCH_STATUS = 0
        begin
            if(@cDOB = @pDOB and @cLastInitial = @pLastInitial)
                set @vResult += 1
            fetch next from cur
            into @cDOB, @cLastInitial
        end

        return @vResult;
    end
    go

    print dbo.Last_In_Group(1, '24.12.2013', 'C')
    go

它可能无法作为上面的示例,但我希望这会给你一些提示,以便进一步发展。