sql - 向 Oracle 添加许多 (UDF) 验证函数 - 哪种方法运行速度最快

标签 sql oracle validation plsql

我必须将大约 50 多个验证函数转移到 Oracle 中。我正在寻找运行速度最快的方法,但如果可能的话,也想解决 bool 值问题。它们的返回对象都需要相同,以便应用程序能够以一致的方式对结果使用react,并提醒用户或显示我们可能需要的任何弹出窗口、消息。我为此创建了一个 valObj ,但还不确定这是否是最好的方法。返回格式可以更改,因为对其使用react的前端尚未开发。最后它将包含许多不同的验证函数,从整数、数字、电话、电子邮件、IPv4、IPv6 等等......这就是我到目前为止所拥有的......

/***
This is the validation object.
It stores 1 for valid, 0 for not valid and some helper text that can be relayed back to the user.
***/
create or replace type valObj as object (
    result number(1),
    resultText varchar(32000)
);

/***
Coming from ColdFusion this seems clean to me but the function
will end up being a couple thousand lines long.
***/
create or replace function isValid(v in varchar2, format in varchar2)
return valObj
is
  test number;
begin
if format = 'number' then
    begin
        test := to_number(v);
        return valObj(1,null);
        exception when VALUE_ERROR then return valObj(0,'Invalid number. Valid formats are: 12345, 12345.67, -12345, etc...');
    end;
elsif format = 'integer' then
    null; --TO DO
elsif format = 'email' then
    null; --TO DO
elsif format = 'IPv4' then
    null; --TO DO
elsif format = 'IPv6' then
    null; --TO DO
end if;
--dozens of others to follow....
end;
/

/* Example Usage in SQL */
select isValid('blah','number') from dual; -- returns: (0, Invalid number. Valid formats are: 12345, 12345.67, -12345, etc...)
select isValid('blah','number').result from dual; -- returns: 0
select isValid('blah','number').resulttext from dual; -- returns: Valid formats are: 12345, 12345.67, -12345, etc...
select isValid(1234567890.123,'number') from dual; -- returns: 1,{null}
select isValid(1234567890.123,'number').result from dual; -- returns: 1
select isValid(1234567890.123,'number').resulttext from dual; -- returns: {null}

/* Example Usage in PL/SQL */
declare
temp valObj;
begin
    temp := isValid('blah','number');
    if (temp.result = 0) then
        dbms_output.put_line(temp.resulttext);
    else
        dbms_output.put_line('Valid');
    end if;
end;
/

我的问题是:

  1. 在 PL/SQL 中使用它时,我希望能够进行 boolean 检查,如下所示:if (temp.result) then 但我不能找出一种方法,因为这在 SQL 中行不通。我应该向 valObj 添加第三个 bool 属性还是有其他我不知道的方法?
  2. 这些验证函数最终可能会在大循环中被调用。知道了这一点,这是完成这些验证的最有效方法吗?

如果有任何帮助,我将不胜感激。谢谢!

更新:我忘记了成员函数。感谢@Brian McGinity 提醒我。所以我想使用这种方法,因为它将类型及其函数封装在一起。 此方法与独立函数之间是否有速度差异?这会像独立函数一样被编译和存储吗?

create or replace type isValid as object (
    result     number(1),
    resulttext varchar2(32000),
    constructor function isValid(v varchar, format varchar) return self as result );
/

create or replace type body isValid as
    constructor function isValid(v varchar, format varchar) return self as result as
        test number;
    begin
        if format = 'number' then
            begin
                test := to_number(v);
                self.result := 1;
                self.resulttext := null;
                return;
                exception when VALUE_ERROR then
                    self.result := 0;
                    self.resulttext := 'Invalid number. Valid formats are: 12345, 12345.67, -12345, etc...';
                    return;
            end;
        elsif format = 'phone' then
            null; --TO DO
        end if;
        --and many others...
    end;
end;
/

/* Example Usage in SQL */
select isValid('a','number') from dual;

/* Example Usage in PL/SQL */
declare
begin
    if (isValid('a','number').result = 1) then
        null;
    end if;
end;
/

测试结果:

/* Test isValid (the object member function), this took 7 seconds to run */
declare
begin
    for i in 1 .. 2000000 loop
        if (isValid('blah','number').result = 1) then
            null;
        end if;
    end loop;
end;

/* Test isValid2 (the stand-alone function), this took 16 seconds to run */
declare
begin
    for i in 1 .. 2000000 loop
        if (isValid2('blah','number').result = 1) then
            null;
        end if;
    end loop;
end;

isValidisValid2 执行完全相同的代码,它们只是运行此行 test := to_number(v); 然后执行如果失败则抛出异常并返回结果。这看起来是一个有效的测试吗?对象成员函数方法实际上比独立函数更快???

最佳答案

如果将其设置为 DETERMINISTIC 并且数据高度重复,则独立函数会更快。在我的机器上,此设置将运行时间从 9 秒减少到 0.1 秒。由于我不明白的原因,设置不会提高对象函数的性能。

create or replace function isValid2(v in varchar2, format in varchar2)
return valObj
deterministic --<< Hit the turbo button!
is
  test number;
begin
if format = 'number' then
    begin
        test := to_number(v);
        return valObj(1,null);
        exception when VALUE_ERROR then return valObj(0,'Invalid number. Valid formats are: 12345, 12345.67, -12345, etc...');
    end;
end if;
end;
/

关于sql - 向 Oracle 添加许多 (UDF) 验证函数 - 哪种方法运行速度最快,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21893989/

相关文章:

sql - 在 Microsoft SQL Server 2000 中模拟 MySQL LIMIT 子句

Oracle 无法将数据插入 varchar2(4000 char) 列

php - isset() 只返回 true

ruby-on-rails - Rails 控制台 sql 查询只返回 true

仅当特定值不存在时,SQL 才选择默认值

php - 验证用户输入的质量

javascript - 浏览器验证消息最小/最大

mysql - MySQL 中的 Oracle 序列等效项

php - php、mysql 排序 asc desc

sql - IPv4 地址的 PostgreSQL 字段数据类型