Sql 在多数据库环境中使用返回自定义类型的函数

Sql 在多数据库环境中使用返回自定义类型的函数,sql,database,oracle,function,plsql,Sql,Database,Oracle,Function,Plsql,我得到了一个简单的utils包,其中包含将分隔字符串转换为自定义表的函数。它是有用的。定义如下: create or replace type StringArray as table of varchar2(60); create or replace PACKAGE utils IS FUNCTION Explode(p_Seperator IN VARCHAR2,p_String IN VARCHAR2) RETURN Stringarray; END utils; create

我得到了一个简单的utils包,其中包含将分隔字符串转换为自定义表的函数。它是有用的。定义如下:

create or replace type StringArray as table of varchar2(60);

create or replace PACKAGE utils
IS
  FUNCTION Explode(p_Seperator IN VARCHAR2,p_String IN VARCHAR2) RETURN Stringarray;
END utils;

create or replace PACKAGE BODY utils
IS
    FUNCTION Explode(p_Seperator IN VARCHAR2,p_String IN VARCHAR2) RETURN Stringarray
    AS
      v_String LONG DEFAULT p_String || p_Seperator;
      v_Data Stringarray := Stringarray();
      n NUMBER;
    BEGIN
      LOOP
      EXIT WHEN v_String IS NULL;
      n := Instr(v_String, p_Seperator);
      v_Data.Extend;
      v_Data(v_Data.Count) := Ltrim(Rtrim(SUBSTR(v_String, 1, n - 1)));
      v_String := SUBSTR(v_String, n + 1);
      END LOOP;
      RETURN v_Data;
    END Explode;
END utils;
UPDATE
  T@A 
SET
    field = 'TEST'
WHERE
  key IN (SELECT COLUMN_VALUE FROM table(utils.explode(',','1,2,3')))
;
UPDATE
  T@A 
SET
    field = 'TEST'
WHERE
  key IN (SELECT COLUMN_VALUE FROM table(utils.explode@A(',','1,2,3')))
;
并使用示例:

SELECT COLUMN_VALUE as letter FROM table(utils.explode(',','a,b,c,d'))
我曾经成功地使用过它。现在,我需要在许多数据库环境中使用它,问题就从这里开始了。 让我们考虑数据库A和表B的数据库A,数据库B是DBLink @,我们的任务是从数据库B中更新数据库A中的表T,并且键是逗号分隔的字符串,例如:‘a,b,c,d’,因此使用我们的Uptry.Buffe函数是很方便的。 为了方便起见,我们可以在两个数据库中定义类型和包

当我尝试使用数据库B中的函数时,如下所示:

create or replace type StringArray as table of varchar2(60);

create or replace PACKAGE utils
IS
  FUNCTION Explode(p_Seperator IN VARCHAR2,p_String IN VARCHAR2) RETURN Stringarray;
END utils;

create or replace PACKAGE BODY utils
IS
    FUNCTION Explode(p_Seperator IN VARCHAR2,p_String IN VARCHAR2) RETURN Stringarray
    AS
      v_String LONG DEFAULT p_String || p_Seperator;
      v_Data Stringarray := Stringarray();
      n NUMBER;
    BEGIN
      LOOP
      EXIT WHEN v_String IS NULL;
      n := Instr(v_String, p_Seperator);
      v_Data.Extend;
      v_Data(v_Data.Count) := Ltrim(Rtrim(SUBSTR(v_String, 1, n - 1)));
      v_String := SUBSTR(v_String, n + 1);
      END LOOP;
      RETURN v_Data;
    END Explode;
END utils;
UPDATE
  T@A 
SET
    field = 'TEST'
WHERE
  key IN (SELECT COLUMN_VALUE FROM table(utils.explode(',','1,2,3')))
;
UPDATE
  T@A 
SET
    field = 'TEST'
WHERE
  key IN (SELECT COLUMN_VALUE FROM table(utils.explode@A(',','1,2,3')))
;
我得到一个错误:

SQL Error: ORA-22804:  "remote operations not permitted on object tables or user-defined type columns"
22804. 00000 -  "remote operations not permitted on object tables or user-defined type columns"
*Cause:    An attempt was made to perform queries or DML operations on
       remote object
       tables or on remote table columns whose type is one of object,
       REF, nested table or VARRAY.
SQL Error: ORA-30626:"function/procedure parameters of remote object types are not supported"
30626. 00000 -  "function/procedure parameters of remote object types are not supported"
*Cause:    
*Action:
当我想从数据库调用函数时,如下所示:

create or replace type StringArray as table of varchar2(60);

create or replace PACKAGE utils
IS
  FUNCTION Explode(p_Seperator IN VARCHAR2,p_String IN VARCHAR2) RETURN Stringarray;
END utils;

create or replace PACKAGE BODY utils
IS
    FUNCTION Explode(p_Seperator IN VARCHAR2,p_String IN VARCHAR2) RETURN Stringarray
    AS
      v_String LONG DEFAULT p_String || p_Seperator;
      v_Data Stringarray := Stringarray();
      n NUMBER;
    BEGIN
      LOOP
      EXIT WHEN v_String IS NULL;
      n := Instr(v_String, p_Seperator);
      v_Data.Extend;
      v_Data(v_Data.Count) := Ltrim(Rtrim(SUBSTR(v_String, 1, n - 1)));
      v_String := SUBSTR(v_String, n + 1);
      END LOOP;
      RETURN v_Data;
    END Explode;
END utils;
UPDATE
  T@A 
SET
    field = 'TEST'
WHERE
  key IN (SELECT COLUMN_VALUE FROM table(utils.explode(',','1,2,3')))
;
UPDATE
  T@A 
SET
    field = 'TEST'
WHERE
  key IN (SELECT COLUMN_VALUE FROM table(utils.explode@A(',','1,2,3')))
;
我得到一个错误:

SQL Error: ORA-22804:  "remote operations not permitted on object tables or user-defined type columns"
22804. 00000 -  "remote operations not permitted on object tables or user-defined type columns"
*Cause:    An attempt was made to perform queries or DML operations on
       remote object
       tables or on remote table columns whose type is one of object,
       REF, nested table or VARRAY.
SQL Error: ORA-30626:"function/procedure parameters of remote object types are not supported"
30626. 00000 -  "function/procedure parameters of remote object types are not supported"
*Cause:    
*Action:
这是我的问题

我知道我可以在数据库A中创建自定义过程,并将其作为字符串发送,然后在内部使用explode函数进行更新。 或者我可以照汤姆的建议去做

但是我在很多地方使用这种技术,有不同的表和不同的字段。这个爆炸功能是一个干净、简单、通用的工具

这就是为什么我不是在寻找一个一次性的解决方案,它涉及到为每个用例创建自定义对象,而是更通用的解决方案

更抽象地说,我的问题是在plsql中的数据库之间发送值集合(或数组或表)

谁能帮我一下吗?:)

[编辑]
没人能帮我吗?甚至不发表评论?

有一段时间我希望这能解决你的问题,但不幸的是,唯一的工作方法(我和你一起来的,当然你也是)不是那么优雅,但至少能完成工作:

insert into global_temporary_explode (select column_value as letter from table(utils.explode(',','1,2,3')));


重新“编辑”:我仍在考虑解决您的问题。:-)哦,听到这是件好事。我正在失去希望开发正在进行中,所以我们制作了一些变通方法,但它们不够优雅。这就是为什么一些解决方案仍然会很受欢迎。谢谢你们的研究,说实话,我并没有想到临时表。这肯定是比多个循环更优雅的解决方案我对你的答案进行了测试并投了赞成票,因为它确实起到了应有的作用。但这并不是我想要的。例如,当我想在同一个会话中更新多个表时,我需要在每个表之后清除temp table,如果我想在一个语句中多次在远程查询where子句中使用explode,事情就会变得复杂,等等。。。所以请理解,我不会接受它是正确的(至少现在不会)。