Sql server 将函数从oracle转换为SQL Server时出错
我正在将一个函数从Oracle迁移到SQL Server 2008。此函数引发函数中包含的SELECT语句,该语句无法将数据作为错误返回给客户端。我怎样才能解决这个问题 原始PLSQL代码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
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