繁体   English   中英

将类型作为参数传递给 Oracle 函数

[英]Pass type as parameter to Oracle function

我正在尝试在 Oracle 中编写一个可以接受类型作为参数的函数。

我环顾四周,但找不到任何示例,所以我想知道是否有可能。

这是我想要实现的简化版本:

create function a_function
    ( text_in in varchar2, type_in in type ) -- can this be done?
    return type_in
is
    val_out type_in;
begin
    val_out := cast(text_in as type_in);
return val_out;
end;

然后上面应该被称为:

a_function('2021-01-20', date)
a_function('111', number)

像许多其他编程语言一样,您可以重载函数。 但是,您必须将它们放入 PACKAGE 中。 它不能作为独立功能工作。 会是这样:

CREATE OR REPLACE PACKAGE a_functions AS

FUNCTION a_function (val_in IN NUMBER) 
    RETURN NUMBER;

FUNCTION a_function (val_in IN DATE) 
    RETURN NUMBER;

FUNCTION a_function (val_in IN VARCHAR2) 
    RETURN NUMBER;
END a_functions;



CREATE OR REPLACE PACKAGE BODY a_functions AS

FUNCTION a_function (val_in IN NUMBER) 
    RETURN NUMBER IS 
BEGIN
    RETURN 1;
END;

FUNCTION a_function (val_in IN DATE) 
    RETURN NUMBER IS 
BEGIN
    RETURN 1;
END;

FUNCTION a_function (val_in IN VARCHAR2) 
    RETURN NUMBER is 
begin
    return 3;
end;

END a_functions;

正确调用它们,例如使用a_functions.a_function(123)a_functions.a_function(SYSDATE)a_functions.a_function(DATE '2020-01-20')

我能想到的最通用的方法是使用 anydata 类型。

因此,您需要的功能将与此类似

create or replace function let_us_use_anydata(p_any_data in anydata, p_data_type in varchar2) return anydata
is
  l_varchar varchar2(1000);
  l_number number;
  l_date date;

  res anydata;
begin 
  if p_data_type = 'SYS.NUMBER' then
    l_number := anydata.AccessNumber(p_any_data);
    l_number := l_number + 1000; -- do any number stuff
    res := anydata.ConvertNumber(l_number); -- put it back to the output
  elsif p_data_type = 'SYS.VARCHAR2' then
    l_varchar := anydata.AccessVarchar2(p_any_data);
    l_varchar := l_varchar || ' Hi there!'; -- do anything you can do with a string
    res := anydata.ConvertVarchar2(l_varchar);
  elsif p_data_type = 'SYS.DATE' then
    l_date := anydata.AccessDate(p_any_data);
    l_date := l_date - 1; --  any date operations 
    res := anydata.ConvertDate(l_date);
  end if;

  return res;
end;

使用这个功能就像

声明虚拟的任何数据;

  procedure any_data_output(p_anydata anydata)
  is
  begin
    case anydata.GetTypeName(dummy)
    when 'SYS.VARCHAR2' then
      dbms_output.put_line('VARCHAR2: ' || anydata.AccessVarchar2(dummy));
    when 'SYS.NUMBER' then
      dbms_output.put_line('NUMBER: ' || anydata.AccessNumber(dummy));
    when 'SYS.DATE' then
      dbms_output.put_line('DATE: ' || to_char(anydata.AccessDate(dummy), 'dd.mm.yyyy hh24:mi:ss'));
    end case;
  end;

begin
  dummy := let_us_use_anydata(anydata.ConvertNumber(12), 'SYS.NUMBER');
  any_data_output(dummy);
  dummy := let_us_use_anydata(anydata.ConvertVarchar2('Hello.'), 'SYS.VARCHAR2');
  any_data_output(dummy);
  dummy := let_us_use_anydata(anydata.ConvertDate(sysdate), 'SYS.DATE');   
    any_data_output(dummy);
end;

所以输出是

NUMBER: 1012
VARCHAR2: Hello. Hi there!
DATE: 21.01.2020 08:37:50

请注意,匿名块中有一个使用 anydata 的过程。 这是为了显示您还可以动态检测数据类型,而无需在单独的参数中指定它。

你可以使用任何你希望的数据类型,我只是选择了这三个,因为它们是最受欢迎的。

无论如何,这是一个非常有趣的案例。 谢谢

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM