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

Sql server 将函数从oracle转换为SQL Server时出错,sql-server,tsql,plsql,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 numbe

我正在将一个函数从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

试着换一下这两行

SELECT @v_katsayi  = 0 

SELECT @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

引用本地的游标操作 已声明、已打开、, 已关闭,并在 作用仅获取 使用为局部变量赋值 允许使用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
您没有将光标输出指定给局部变量

请描述一下你想对样本数据做什么:我相信这是一个简单的案例选择

编辑:您不需要游标,除非我的pl/sql太差了


只是分配变量的不同方式。完全不正确我同意,只是分配变量的方式不同,但是在函数中,你还能在哪里看到返回数据的SELECT子句呢?我看到SQL解析器有时会这样做,将赋值SELECT视为返回值的SELECT…是的,我也看到了。祝你新年快乐也祝你新年快乐。谢谢你的帮助,在我复制了你的解决方案后,现在它给出了多部分标识符c.MT_ORAN无法绑定错误。我能做什么?我修改了光标以处理MT_ORAN字段,检查上面修改的代码。很抱歉,我错过了那一行。你希望光标中有多少行?为什么不添加原始的plsql代码?我编辑并添加了原始的plsql代码。我想你是对的。我想让我们困惑的是一个错误的迁移无数据异常。
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
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