2

我们正在从 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 ...
4

3 回答 3

0

我将您的示例代码翻译成它的 SQL-Server 对应物。如果您想逐行处理,最好的执行方式是 imo 使用 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

它可能无法作为您上面的示例,但我希望这可以为您提供一些进一步的提示。

于 2013-07-04T12:19:58.840 回答
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。

于 2013-03-04T17:56:06.800 回答
0

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

于 2013-03-04T17:22:56.673 回答