【问题标题】:array or list into Oracle using cfprocparam使用 cfprocparam 将数组或列表放入 Oracle
【发布时间】:2011-02-21 10:49:08
【问题描述】:

我有一个要通过存储过程插入到表中的值列表。 我想我会将一个数组传递给 oracle 并循环遍历该数组,但我不知道如何将一个数组传递给 Oracle。我会传递一个列表,但我看不到如何使用 PL/SQL 将其转换为数组(我对 PL/SQL 还很陌生)。我是不是走错了路?

使用 Oracle 9i 和 CF8。

编辑

也许我想错了?我确定我在这里没有做任何新的事情...... 我想我会将列表转换为关联数组,然后循环该数组,因为 Oracle 似乎不适用于列表(在我有限的观察中)。

我正在尝试添加产品,然后为管理团队添加记录。
-- 产品表

产品名称 = 'foo' 产品描述 = '酒吧' ... ... 等等

-- managementteam 表只有产品的 id 和从下拉列表中选择的用户的 id。

用户 ID 通过类似“1,3,6,20”的列表传入

我应该如何将记录添加到管理团队表中?


这是我的代码明智的地方

理论上,我将列表“1,2,3,4”传递给 inserts.addProduct。
inserts.addProduct 应该调用 tools.listToArray 并返回一个数组。
inserts.addProduct 重新创建一个带有 * delim 的列表作为测试。
创建或替换包工具为

  TYPE array_type is TABLE OF VARCHAR2(225) INDEX BY BINARY_INTEGER;

  FUNCTION listToArray(in_list IN VARCHAR,
                     in_delim IN VARCHAR2 DEFAULT ',') 
  RETURN array_type;

END tools;



CREATE OR REPLACE PACKAGE BODY tools
AS

FUNCTION listToArray(in_list IN VARCHAR,
                         in_delim IN VARCHAR2 DEFAULT ',') 
    RETURN array_type

    IS
    l_token_count BINARY_INTEGER := 0;
    -- l_token_tbl type_array; 
    i pls_integer;
    l_start_pos INTEGER := 1;
    l_end_pos INTEGER :=1;
    p_parsed_table array_type;

    BEGIN -- original work by John Spencer  
       WHILE l_end_pos <> 0 LOOP
          l_end_pos := instr(in_list,in_delim,l_start_pos);
          IF l_end_pos <> 0 THEN
             l_token_count  := l_token_count  + 1;
             p_parsed_table(l_token_count ) :=
                      substr(in_list,l_start_pos,l_end_pos - l_start_pos);
             l_start_pos := l_end_pos + 1;
          END IF;
       END LOOP;
       IF l_token_count = 0 THEN /* We haven't parsed anything so */ 
          l_token_count := 1;
          p_parsed_table(l_token_count) := in_list;
       ELSE  /* We need to get the last token */ 
          l_token_count := l_token_count + 1;
          p_parsed_table(l_token_count) := substr(in_list,l_start_pos);
       END If;
       RETURN p_parsed_table;
    END listToArray;  -- Procedure

END tools;



CREATE OR REPLACE PACKAGE inserts AS
    TYPE array_type is TABLE OF VARCHAR2(225) INDEX BY BINARY_INTEGER;

    PROCEDURE addProduct (inList         IN  VARCHAR2,
                          outList        OUT VARCHAR2
                         );

END inserts;  




CREATE OR REPLACE PACKAGE BODY inserts                      

    AS
    PROCEDURE addProduct (inList         IN  VARCHAR2,
                          outList        OUT VARCHAR2
                         )
    IS
    i NUMBER;
    localArray array_type := tools.listToArray(inList);
    BEGIN       
       outList := '';
       FOR i IN localArray.first .. localArray.last LOOP
          outList := outList || '*' ||localArray(i); -- return a string just to test this mess 
       END LOOP;

    END addProduct;

END inserts;

我目前在 localArray array_type := tools.listToArray(inList); 上收到错误“PLS-00382:表达式类型错误”;


最终的工作代码(非常感谢!)

--创建sql类型集合

CREATE OR REPLACE TYPE array_type is TABLE OF VARCHAR2(225);
/



CREATE OR REPLACE PACKAGE tools AS

  FUNCTION listToArray(in_list IN VARCHAR,
                     in_delim IN VARCHAR2 DEFAULT ',') 
  RETURN array_type;

END tools;   
/



CREATE OR REPLACE PACKAGE BODY tools
AS

    FUNCTION listToArray(in_list IN VARCHAR,
                         in_delim IN VARCHAR2 DEFAULT ',') 
    RETURN array_type

    IS
    l_token_count BINARY_INTEGER := 0;
    i pls_integer;
    l_start_pos INTEGER := 1;
    l_end_pos INTEGER :=1;
    p_parsed_table array_type := array_type();

    BEGIN
       WHILE l_end_pos <> 0 LOOP
          l_end_pos := instr(in_list,in_delim,l_start_pos);
          IF l_end_pos <> 0 THEN
             p_parsed_table.extend(1);
             l_token_count  := l_token_count  + 1;
             p_parsed_table(l_token_count ) :=
                      substr(in_list,l_start_pos,l_end_pos - l_start_pos);
             l_start_pos := l_end_pos + 1;
          END IF;

       END LOOP;
       p_parsed_table.extend(1);
       IF l_token_count = 0 THEN /* We haven't parsed anything so */ 
          l_token_count := 1;
          p_parsed_table(l_token_count) := in_list;
       ELSE  /* We need to get the last token */ 
          l_token_count := l_token_count + 1;
          p_parsed_table(l_token_count) := substr(in_list,l_start_pos);
       END If;
       RETURN p_parsed_table;
    END listToArray;  -- Procedure

END tools;
/



CREATE OR REPLACE PACKAGE inserts AS

    PROCEDURE addProduct (inList  IN  VARCHAR2,
                             outList OUT VARCHAR2
                         );

END inserts;
/




CREATE OR REPLACE PACKAGE BODY inserts
AS
    PROCEDURE addProduct (inList  IN  VARCHAR2,
                          outList OUT VARCHAR2
                         )
    IS
    i NUMBER;
    mylist VARCHAR(100);
    localArray array_type := array_type();

    BEGIN     
    localArray := tools.listToArray(inList);
       mylist := '';
       FOR i IN localArray.first .. localArray.last LOOP
          mylist := mylist || localArray(i) || '*';
       END LOOP;
       aList := mylist;
    END addProduct;

END inserts;  
/

【问题讨论】:

    标签: oracle stored-procedures coldfusion tokenize cfstoredproc


    【解决方案1】:

    PL/SQL 从 Oracle 8.0 开始就支持数组。它们曾经被称为 PL/SQL 表,这让每个人都感到困惑,所以现在它们被称为集合。 Find out more.

    问题是,它们被实现为用户定义的类型(即对象)。我对ColdFusion documents 的阅读表明cfprocparam 仅支持“原始”数据类型(数字、varchar2 等)。所以不支持UDT。

    我不确定你的意思是什么:

    我会传递一个列表,但我不知道如何传递 使用列表将其变成 使用 PL/SQL 的数组

    如果您的意思是要传递逗号分隔值的字符串 ....

    "Fox in socks, Mr Knox, Sam-I-Am, The Lorax"
    

    那么我有一个解决方法给你。 Oracle 不提供内置的 Tokenizer。但很久以前,John Spencer 在 OTN 论坛上发布了一个适用于 Oracle 9i 的手动解决方案。 Find it here.

    编辑

    但是...甲骨文讨厌我

    不要绝望。自从 John 发布该消息以来,OTN 论坛已经升级了几次,并且格式似乎已经在某处损坏了代码。有几个以前没有的编译错误。

    我重写了 John 的代码,包括一个新函数。主要区别在于嵌套表被声明为 SQL 类型而不是 PL/SQL 类型。

    create or replace type tok_tbl as table of varchar2(225) 
    /
    
    create or replace package parser is
    
        function my_parse(
              p_str_to_search in varchar2
                , p_delimiter in varchar2 default ',')
              return tok_tbl;
    
        procedure my_parse(
              p_str_to_search in varchar2
              , p_delimiter in varchar2 default ','
              , p_parsed_table out tok_tbl);
    
    end parser;
    /
    

    如您所见,函数只是过程的包装器。

    create or replace package body parser is
    
        procedure my_parse ( p_str_to_search in varchar2
                              , p_delimiter in varchar2 default ','
                              , p_parsed_table out tok_tbl)
        is
            l_token_count binary_integer := 0;
            l_token_tbl tok_tbl := tok_tbl();
            i pls_integer;
            l_start_pos integer := 1;
            l_end_pos integer :=1;   
        begin
    
            while l_end_pos != 0
            loop
                l_end_pos := instr(p_str_to_search,p_delimiter,l_start_pos);
    
                if l_end_pos  != 0 then
                    l_token_count := l_token_count + 1;
                    l_token_tbl.extend();
                    l_token_tbl(l_token_count ) :=
                        substr(p_str_to_search,l_start_pos,l_end_pos - l_start_pos);
                    l_start_pos := l_end_pos + 1;
                end if;
            end loop;
    
            l_token_tbl.extend();
            if l_token_count = 0 then /* we haven't parsed anything so */
                l_token_count := 1;
                l_token_tbl(l_token_count) := p_str_to_search;
            else /* we need to get the last token */
                l_token_count := l_token_count + 1;
                l_token_tbl(l_token_count) := substr(p_str_to_search,l_start_pos);
            end if;
            p_parsed_table := l_token_tbl;
        end my_parse;
    
        function my_parse ( p_str_to_search in varchar2
                                , p_delimiter in varchar2 default ',')
                              return tok_tbl
        is
            rv tok_tbl;
        begin
            my_parse(p_str_to_search, p_delimiter, rv);
            return rv;
        end my_parse;
    
    end parser;
    /
    

    在 SQL 中声明类型的好处是我们可以像这样在 FROM 子句中使用它:

    SQL> insert into t23
      2  select trim(column_value)
      3  from table(parser.my_parse('Fox in socks, Mr Knox, Sam-I-Am, The Lorax'))
      4  /
    
    4 rows created.
    
    SQL> select * from t23
      2  /
    
    TXT
    ------------------------------------------------------------------------------
    Fox in socks
    Mr Knox
    Sam-I-Am
    The Lorax
    
    SQL> 
    

    【讨论】:

    • @APC - 我相信还有非原始类型,如 cf_sql_array 和 cf_sql_struct。您知道其中任何一个(java.sql.Types.Array 或 Struct)是否适用于 jdbc 中的 Oracle 数组?由于我不与 Oracle 合作,我一直对此感到好奇;)
    • 苏普利。不,他们不工作。这是我尝试的第一件事,但是:[Macromedia][Oracle JDBC Driver]此驱动程序不支持指定的 SQL 类型。
    • @Travis - 那太容易了,对吧? ;) 显然,Adobe 的驱动程序不支持它们。 (虽然我很好奇这些类型是否适用于任何 Oracle 驱动程序......有什么想法@APC)?
    • @Leigh - Oracle 提供自己的等价物 - oracle.sql.ARRAYoracle.sql.STRUCT。如果普通 Java 类与 PL/SQL 集合一起使用,我怀疑他们会为此烦恼。
    • @APC 我想这就是我要找的。我正在尝试将其转换为函数并从我的过程中调用它,但是...... Oracle 讨厌我。
    猜你喜欢
    • 2021-08-04
    • 1970-01-01
    • 1970-01-01
    • 2020-06-27
    • 1970-01-01
    • 1970-01-01
    • 2020-09-29
    • 1970-01-01
    • 2018-09-13
    相关资源
    最近更新 更多