PLSQL函数如果不可用则执行其他操作

时间:2016-10-27 12:08:24

标签: oracle encryption plsql

在我的oracle 11环境中,我声明了以下功能(成功,没有错误)。

create or replace function s2_encrypt(paramToEncrypt in VARCHAR2, encrypt8BYTEKey in RAW)
    return RAW is encryptedReturnValue RAW (2000);
    encryptionMode number := DBMS_CRYPTO.ENCRYPT_AES128 + DBMS_CRYPTO.CHAIN_CBC + DBMS_CRYPTO.PAD_PKCS5;
begin
    encryptedReturnValue := dbms_crypto.encrypt(UTL_I18N.STRING_TO_RAW(paramToEncrypt, 'AL32UTF8'), encryptionMode, encrypt8BYTEKey);
    return encryptedReturnValue;
end;
/

在此处找到:http://anujktyagi.blogspot.ch/2012/12/oracle-using-dbmscrypto-package-for.html

我正在几台服务器上部署它,其中一些服务器只运行Oracle版本8/9 - >在这种情况下,我想只复制值(而不是解密)。

如何扩展上述功能,以便可以在Oracle 10+及更低版本中部署(在以后的情况下只需复制粘贴值而不加密)?

这样的东西
create or replace function s2_encrypt(paramToEncrypt in VARCHAR2, encrypt8BYTEKey in RAW)
    return RAW is encryptedReturnValue RAW (2000);
    encryptionMode number := DBMS_CRYPTO.ENCRYPT_AES128 + DBMS_CRYPTO.CHAIN_CBC + DBMS_CRYPTO.PAD_PKCS5;
begin

...
if !dbms_crypto.encrypt exit ???
...

    encryptedReturnValue := dbms_crypto.encrypt(UTL_I18N.STRING_TO_RAW(paramToEncrypt, 'AL32UTF8'), encryptionMode, encrypt8BYTEKey);
    return encryptedReturnValue;
end;
/

3 个答案:

答案 0 :(得分:1)

您可以使用条件编译 使用包DBMS_DB_VERSION或一些常量

$IF DBMS_DB_VERSION.ver_le_9_1 $THEN
   return paramToEncrypt ;
$ELSE
   encryptedReturnValue := dbms_crypto.encrypt(UTL_I18N.STRING_TO_RAW(paramToEncrypt, 'AL32UTF8'), encryptionMode, encrypt8BYTEKey);
    return encryptedReturnValue;
$END

答案 1 :(得分:1)

最明智的做法是使用两个不同版本的功能 - 一个用于版本8/9,一个用于10个版本。

话虽这么说,以下方法应该工作(未经测试,我无法访问运行Oracle 10或更低版本的任何实例):

  • 检查数据库版本(通过检查DBMS_DB_VERSION存在或解析PRODUCT_COMPONENT_VERSIONV$VERSION的输出 - 最好的知识 - 版本8中已经存在。)
  • 使用动态SQL调用dbms_crypto或返回字符串不变(因为如果直接引用dbms_crypto,您的包将不会在8/9编译)

示例(未经测试):

create or replace function s2_encrypt(paramToEncrypt  in VARCHAR2,
                                      encrypt8BYTEKey in RAW) return RAW is
  encryptedReturnValue RAW(2000);
  objectCount          pls_integer;
begin
  select count(*)
    into objectCount
    from all_objects
   where object_name = 'DBMS_CRYPTO';
  -- Oracle 8/9: return string unchanged
  if objectCount = 0 then
    encryptedReturnValue := paramToEncrypt;
  else
    execute immediate '
          declare
            encryptionMode number := DBMS_CRYPTO.ENCRYPT_AES128 + DBMS_CRYPTO.CHAIN_CBC + DBMS_CRYPTO.PAD_PKCS5;
          begin
            :encryptedReturnValue := dbms_crypto.encrypt(UTL_I18N.STRING_TO_RAW(:paramToEncrypt, ''AL32UTF8''), encryptionMode, :encrypt8BYTEKey);
          end;'
      using out encryptedReturnValue, in paramToEncrypt, in encrypt8BYTEKey;
  end if;
  return encryptedReturnValue;
end;

用法(11g - 8i显然没有UTL_I18N,见评论)

select s2_encrypt(
  'hello world', 
  UTL_I18N.STRING_TO_RAW ('8232E3F8BDE7703C', 'AL32UTF8')) 
from dual;

答案 2 :(得分:0)

您可以使用Oracle 10g第1版中提供的条件编译。

请参阅https://oracle-base.com/articles/10g/conditional-compilation-10gr2

在旧版本中,您可以使用普通的IF-ELSE语句

DECLARE
   v1   VARCHAR2 (10);
   v2   VARCHAR2 (10);
BEGIN
   DBMS_UTILITY.db_version (v1, v2);

   IF SUBSTR (v1, 1, INSTR (v1, '.', 1)-1) < 10 THEN
      returnvalue paramToEncrypt;
    ELSE
      returnValue := dbms_crypto.encrypt(UTL_I18N.STRING_TO_RAW(paramToEncrypt, 'AL32UTF8'), encryptionMode, encrypt8BYTEKey);
    END;
return returnValue; 
END;