Ошибка при преобразовании функции из оракула в SQL Server - PullRequest
0 голосов
/ 31 декабря 2010

Я мигрирую функцию из 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 ]

1 голос
/ 31 декабря 2010

С CREATE FUNCTION

Операции курсора, ссылающиеся на локальные курсоры, которые объявлены, открыты, закрыты и освобождены в функции.Допускаются только операторы FETCH, которые присваивают значения локальным переменным с помощью предложения INTO;Операторы FETCH, которые возвращают данные клиенту, недопустимы

Это означает, что это неправильно

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 локальным переменным.

Пожалуйста, опишите, что вы хотите сделать с примерами данных: я уверен, что это простой SELECT с CASE

Редактировать: вам не нужен CURSOR, если мой pl / sql не way выкл

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
0 голосов
/ 31 декабря 2010

Попробуйте изменить эти две строки

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...