如何编写一个PL / SQL函数:
这是我到目前为止所写的内容:
create or replace function test_reverse
(p_input in pls_integer)
return pls_integer
is
p_num pls_integer := 0;
p_in_num pls_integer := 0;
p_out_num pls_integer := 0;
begin
p_num := p_input;
loop
exit when p_num p_in_num := mod(p_num,10);
p_out_num := (p_out_num * 10) + p_in_num;
p_num := trunc(p_num / 10);
end loop;
return p_out_num;
end;
答案 0 :(得分:1)
问题是将1234变成4321.字符串-y解决方案(诚然使用未记录的内置函数)本身就是简单的:to_number(reverse(to_char(1234)))
。坚持使用数值数据类型更加麻烦。我的解决方案非常具有程序性:毫无疑问,存在更优雅的解决方案。
无论如何,要将1234变为4321,我们需要生成1 + 20 + 300 + 4000.我的解决方案依次隔离每个值并乘以适当的10的幂。要隔离值,我们将trunc()
与负值一起使用。这会将小数点左侧的数字向下舍入。因此,trunc(1234,-3)
生成1000
。要将其转换为所需的值,我们将乘以10乘以-3的幂。因此1000 * 10(-3) = 1
。
该函数遍历数字。将1000转换为1后,我们计算余数1234 - 1000 = 234
。所以现在我们需要隔离200并将其转换为20;这是trunc(234, -2)
和power(200, -1)
。因此,我们可以将偏移量递增到trunc()
递减1,将指数递增到power()
递增2。
这是一个工作函数(非常松散地基于你发布的函数):
create or replace function test_reverse
(p_input in pls_integer)
return pls_integer
is
p_out_num pls_integer := 0;
offset pls_integer;
tgt pls_integer;
rmdr pls_integer;
exp pls_integer;
begin
rmdr := p_input;
offset := length(p_input)-1;
exp := -offset;
loop
tgt := trunc(rmdr, -offset);
p_out_num := p_out_num + (tgt * power(10, exp));
exp := exp + 2;
rmdr := rmdr - tgt;
exit when offset = 0;
offset := offset-1;
end loop;
return p_out_num;
end test_reverse;
/
这是a LiveSQL demo (free Oracle Technet account required, alas)。这并不具备参数验证功能,但它足够简单:
create or replace function test_reverse
(p_input in pls_integer)
return pls_integer
is
p_out_num pls_integer := 0;
offset pls_integer;
tgt pls_integer;
rmdr pls_integer;
exp pls_integer;
begin
if p_input <= 0 then
raise_application_error(-20001
'invalid input: ' || || ' must be greater than zero.'
);
end if;
rmdr := p_input;
....
答案 1 :(得分:1)
我喜欢使用modulo函数作为op建议:
CREATE OR REPLACE FUNCTION test_reverse (
p_input IN PLS_INTEGER
) RETURN PLS_INTEGER
IS
remain PLS_INTEGER := p_input;
retval PLS_INTEGER := 0;
BEGIN
IF p_input < 1 THEN
raise_application_error(-20001,'error: input must me greater than 0');
END IF;
LOOP
retval := retval * 10 + MOD(remain,10);
remain := trunc(remain / 10);
EXIT WHEN remain = 0;
END LOOP;
RETURN retval;
END;
/
这也避免了使用length()函数,这种函数对我的品味感觉有些“细长”,即使它对数字有效。