【问题标题】:Oracle Procedure - How to insert every combination of records into a table?Oracle 过程 - 如何将每个记录组合插入到表中?
【发布时间】:2014-08-06 20:01:50
【问题描述】:

我正在处理一个 Oracle 程序,该程序需要根据传递给参数的 CustomerID 将客户和产品的每个组合插入到特定表中。

输入:

客户参数(p_customers - 逗号分隔): 即:(1,2,3,4)

订单参数(p_order - 单值)

我必须写入的输出表:

客户 ID、产品 ID

我希望下面的查询能给我一个需要插入的产品列表:

select ProductID from orders where order_id = p_order_id

编写插入语句最有效的方法是什么?

谢谢!

【问题讨论】:

  • 如果p_customer 是逗号分隔的字符串,您发布的查询不会返回任何结果(除非您的客户的customerid 是字符串“1,2,3,4” )。通常,您会传入一个集合而不是逗号分隔的列表。如果您必须接受逗号分隔的列表,您通常会解析该列表以在您的过程中创建集合。在任何一种情况下,您都可以使用该集合进行交叉连接。
  • 不幸的是,我需要接受 p_customer 作为逗号分隔的字符串。我将如何进行交叉连接以进行插入?
  • 那么,您实际上是如何在查询中使用逗号分隔的字符串的呢?正如我所说,您发布的查询无法正常工作。如果您确实有一个有效的查询,这意味着您实际上已经将逗号分隔的列表解析为某种集合,在这种情况下,您可以根据集合的类型使用该集合进行交叉连接您选择了,或者您确实在使用动态 SQL 来构建您发布的 select 查询,这将在多个级别上存在问题。
  • 不了解您的要求。你真的是指CROSS JOIN,也就是笛卡尔连接,这意味着每个组合?如果是所有组合,那么为什么还有“查询......需要插入的产品列表”?您是否希望将几个客户(例如 (1,2,3,4))与 orders 表中相关的每个客户的所有产品交叉?
  • 我在过程的不同部分使用 p_customer 字符串,方法是使用 Oracle 指令一次处理一个客户记录并搜索逗号。

标签: sql oracle stored-procedures procedure


【解决方案1】:

根据您的“伪”代码,尝试这样的事情。我从http://www.oratechinfo.co.uk/delimited_lists_to_collections.html 中窃取了部分内容

假设这些结构:

CREATE TABLE orders (
    orderId    VARCHAR2(100) primary key
  , customerId VARCHAR2(100)
  , productId  VARCHAR2(100)
);

CREATE TABLE output_table (customerId VARCHAR2(100), productId VARCHAR2(100));

代码:

CREATE TYPE varchar_table IS TABLE OF VARCHAR2(100);
/

CREATE OR REPLACE FUNCTION csv_convert(p_list IN VARCHAR2)
  RETURN varchar_table
AS
  l_string       VARCHAR2(32767) := p_list || ',';
  l_comma_index  PLS_INTEGER;
  l_index        PLS_INTEGER := 1;
  l_tab          varchar_table := varchar_table();
BEGIN
  LOOP
    l_comma_index := INSTR(l_string, ',', l_index);
    EXIT WHEN l_comma_index = 0;
    l_tab.EXTEND;
    l_tab(l_tab.COUNT) := SUBSTR(l_string, l_index, l_comma_index - l_index);
    l_index := l_comma_index + 1;
  END LOOP;
  RETURN l_tab;
END csv_convert;
/

新创建的csv_convert函数的简单单元测试:

SELECT * FROM TABLE(csv_convert('1,2,3,4'));

COLUMN_VALUE
------------
1
2
3
4

现在是使用csv_convert 函数的存储过程:

CREATE OR REPLACE PROCEDURE cust_products_process (p_customers IN VARCHAR2)
IS
BEGIN
  INSERT INTO output_table (customerId, productId)
    SELECT customerId, productId
      FROM orders o
      JOIN TABLE(csv_convert(p_customers)) c
        ON (o.customerId = c.column_value);
END;
/

【讨论】:

  • 约书亚 - 谢谢!这段代码看起来就像我需要的那样。我真的很喜欢您使用该函数将 csv 转换为行的方法。感谢您的回复,并将在明天将其添加到现有程序中进行尝试。再次感谢您!
猜你喜欢
  • 2021-12-27
  • 1970-01-01
  • 2016-07-07
  • 2019-12-26
  • 2019-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多