将函数从oracle转换为SQL Server时出错

时间:2010-12-31 20:15:14

标签: sql-server tsql plsql

我正在将一个函数从Oracle迁移到SQL Server 2008.此函数引发函数中包含的SELECT语句无法将数据作为错误返回给客户端。我该如何解决这个问题?

原始PLSQL代码

CREATE OR REPLACE function f_birim_cevrim_katsayi (p_ID_MAMUL in number, p_ID_BIRIMDEN in number, p_ID_BIRIME in number) 
return number
is

v_katsayi number;

begin

v_katsayi:=0;

if p_ID_BIRIMDEN!=p_ID_BIRIME then

    for c in (
         select * from CR_BIRIM_CEVRIM
         where ID_MAMUL = p_ID_MAMUL
         and (
         (ID_BIRIM = p_ID_BIRIMDEN and ID_BIRIM2 = p_ID_BIRIME)
         OR ( ID_BIRIM2 = p_ID_BIRIMDEN and ID_BIRIM = p_ID_BIRIME) )
         and VALID = 1) 
         loop

         if c.ID_BIRIM=p_ID_BIRIMDEN then
            v_katsayi:=c.MT_ORAN;
         else
            v_katsayi:=1/c.MT_ORAN;
         end if;
    end loop;
else
    v_katsayi:=1;
end if;

return round(v_katsayi,10);

exception 
when others then 
return 0;

end;

T-SQL代码:

If Exists ( SELECT name 
                FROM sysobjects  
                WHERE name = 'f_birim_cevrim_katsayi'
                AND type = 'FN')
        DROP FUNCTION f_birim_cevrim_katsayi
    GO 
    CREATE FUNCTION f_birim_cevrim_katsayi
    (
        @p_ID_MAMUL                               FLOAT ,
        @p_ID_BIRIMDEN                            FLOAT ,
        @p_ID_BIRIME                              FLOAT 
    )
    RETURNS float 
    AS 
        BEGIN


            DECLARE @adv_error INT


            DECLARE @v_katsayi                                FLOAT 
            SELECT @v_katsayi  = 0 
            IF @p_ID_BIRIMDEN != @p_ID_BIRIME 
            BEGIN 


                DECLARE cursor_for_inline_select1 CURSOR LOCAL FOR 
                SELECT *
                FROM  CR_BIRIM_CEVRIM 
                WHERE    ID_MAMUL  = @p_ID_MAMUL
                 AND    ((ID_BIRIM  = @p_ID_BIRIMDEN
                 AND    ID_BIRIM2  = @p_ID_BIRIME)
                 OR (ID_BIRIM2  = @p_ID_BIRIMDEN
                 AND    ID_BIRIM  = @p_ID_BIRIME))
                 AND    VALID  = 1

                OPEN cursor_for_inline_select1 

                FETCH NEXT FROM  cursor_for_inline_select1  
                WHILE (@@FETCH_STATUS <> -1)
                BEGIN
                    IF   c.ID_BIRIM = @p_ID_BIRIMDEN 
                    BEGIN 
                        SELECT @v_katsayi  = c.MT_ORAN 
                    END
                    ELSE
                    BEGIN 
                        SELECT @v_katsayi  = 1/c.MT_ORAN 
                    END

                END
                CLOSE cursor_for_inline_select1
                DEALLOCATE cursor_for_inline_select1

            END
            ELSE
            BEGIN 
                SELECT @v_katsayi  = 1 
            END


     DEALLOCATE cursor_for_inline_select1
            return ROUND(@v_katsayi, 10) 
            GOTO ExitLabel1
            Exception1:

                BEGIN

     DEALLOCATE cursor_for_inline_select1
                return 0 
                            END
            ExitLabel1:

            return ROUND(@v_katsayi, 10) 

        END


    GO

2 个答案:

答案 0 :(得分:1)

来自CREATE FUNCTION

  

引用本地的游标操作   声明,打开的游标,   关闭,并取消分配   功能。只有FETCH语句   使用赋值给局部变量赋值   允许INTO条款;取   将数据返回给的语句   不允许客户

这意味着这是错误的

DECLARE cursor_for_inline_select1 CURSOR LOCAL FOR 
            SELECT *
            FROM  CR_BIRIM_CEVRIM 
            WHERE    ID_MAMUL  = @p_ID_MAMUL
             AND    ((ID_BIRIM  = @p_ID_BIRIMDEN
             AND    ID_BIRIM2  = @p_ID_BIRIME)
             OR (ID_BIRIM2  = @p_ID_BIRIMDEN
             AND    ID_BIRIM  = @p_ID_BIRIME))
             AND    VALID  = 1

您没有将CURSOR输出分配给局部变量。

请描述您想要对样本数据做什么:我确定这是一个带CASE的简单SELECT

编辑:除非我的pl / sql 方式关闭

,否则你不需要CURSOR
CREATE FUNCTION f_birim_cevrim_katsayi (
    @p_ID_MAMUL                               FLOAT ,
    @p_ID_BIRIMDEN                            FLOAT ,
    @p_ID_BIRIME                              FLOAT 
)
RETURNS float 
AS 
BEGIN
    DECLARE @v_katsayi FLOAT;
    IF @p_ID_BIRIMDEN != @p_ID_BIRIME 
    BEGIN 
        SELECT
             @v_katsayi =  CASE
                 WHEN ID_BIRIM = @p_ID_BIRIMDEN THEN c.MT_ORAN 
                 ELSE 1/c.MT_ORAN 
             END
        FROM 
             CR_BIRIM_CEVRIM c
        WHERE
             ID_MAMUL  = @p_ID_MAMUL
             AND    ((ID_BIRIM  = @p_ID_BIRIMDEN
             AND    ID_BIRIM2  = @p_ID_BIRIME)
             OR (ID_BIRIM2  = @p_ID_BIRIMDEN
             AND    ID_BIRIM  = @p_ID_BIRIME))
             AND    VALID  = 1;
    END
    RETURN ROUND(ISNULL(@v_katsayi, 1), 10);
END
GO

答案 1 :(得分:-1)

尝试更改这两行

SELECT @v_katsayi  = 0 

SELECT @v_katsayi  = 1 

SET @v_katsayi  = 0 

SET @v_katsayi  = 1 

错过了其他几个人。无论您使用SELECT来设置变量值,只需更改为SET ...

另外:更改光标以抓取字段并将其放入变量

DECLARE @theID FLOAT
DECLARE @theORAN FLOAT

DECLARE cursor_for_inline_select1 CURSOR LOCAL FOR 
                SELECT id_birim,MT_ORAN  -- Fields name instead of *
                FROM  CR_BIRIM_CEVRIM 
                WHERE    ID_MAMUL  = @p_ID_MAMUL
                 AND    ((ID_BIRIM  = @p_ID_BIRIMDEN
                 AND    ID_BIRIM2  = @p_ID_BIRIME)
                 OR (ID_BIRIM2  = @p_ID_BIRIMDEN
                 AND    ID_BIRIM  = @p_ID_BIRIME))
                 AND    VALID  = 1

                OPEN cursor_for_inline_select1 
                -- Put field value into variable
                FETCH NEXT FROM  cursor_for_inline_select1  INTO @theID,@theORan
                WHILE (@@FETCH_STATUS <> -1)
                BEGIN
                    -- Compare variable rather than field directly
                    IF   @theID = @p_ID_BIRIMDEN 
                    BEGIN 
                        SELECT @v_katsayi  = @theORan 
                    END
                    ELSE
                    BEGIN 
                        SELECT @v_katsayi  = 1/@theORan 
                    END

                END
                CLOSE cursor_for_inline_select1
                DEALLOCATE cursor_for_inline_select1