【问题标题】:Oracle: Inserting a row using values from existing table and new valuesOracle:使用现有表中的值和新值插入行
【发布时间】:2015-08-01 08:56:22
【问题描述】:

我在将一行拆分成两个单独的行时遇到了困难。

我的测试架构是:

CREATE TABLE T
    (id int, 
     old varchar2(24), 
     new varchar2(24))
;

其中 old 和 new 是需要拆分的字符串,示例行:

  INTO T (id, old, new)
     VALUES (14, 'L-D / T-E', 'L-E / T-E')
  INTO T (id, old, new)
     VALUES (14, 'L-D / T-E', 'L-D / T-D')
  INTO T (id, old, new)
     VALUES (12, 'L-D / T-E', 'L-E / T-D')

在此示例中,“L”在第 1 行发生了变化,“T”在第 2 行发生了变化,并且两者都在第 3 行发生了变化

表格是:

ID  OLD         NEW
14  L-D / T-E   L-E / T-E
14  L-D / T-E   L-D / T-D
12  L-D / T-E   L-E / T-D

我正在尝试拆分这些,以便生成的表将针对每个重大更改具有单独的行,这样结果将如下所示:

ID  OLD     NEW
1   L-D     L-E  //for existing row 1
2   T-E     T-D  //for existing row 2
//then two rows for existing row 3
3   L-D     L-E 
4   T-E     T-D

插入这些行后,我想删除现有的行。

我已经设置了一个 sqlfiddle:http://sqlfiddle.com/#!4/0213a/1 - 请记住,我在工作时会更新它,所以它在任何给定点看起来都像是火车残骸。

感谢您的帮助。

已编辑更新:

我正在尝试这个,但获得的数据比我需要的多,我认为 where 子句有问题:

drop table t;
CREATE TABLE T
(id int, 
 old varchar2(24), 
 new varchar2(24))
;

INSERT ALL

  INTO T (id, old, new)
     VALUES (12, 'L-D / T-E', 'L-E / T-E')
  INTO T (id, old, new)
     VALUES (13, 'L-D / T-E', 'L-D / T-D')
  INTO T (id, old, new)
     VALUES (14, 'L-D / T-E', 'L-E / T-D')



SELECT * FROM dual
;

SELECT * FROM T;

--insert into t (id, old, new) values (1,'dasdsad', 'asdasd');

BEGIN
INSERT INTO t (id,old, new) 

  WITH DATA AS
      (SELECT id,OLD, new
      FROM t
      WHERE 
      --multiple changes
      --(SUBSTR(OLD,3,1) <> SUBSTR(NEW, 3,1)
      --AND SUBSTR(OLD, 9)    <> SUBSTR(NEW, 9))
      --OR
      (--row 2
      (SUBSTR(OLD,3,1) = SUBSTR(NEW, 3,1)
      AND SUBSTR(OLD, 9)    <> SUBSTR(NEW, 9))
      )
      OR
      (--row 1
      (SUBSTR(OLD,3,1) <> SUBSTR(NEW, 3,1)
      AND SUBSTR(OLD, 9) = SUBSTR(NEW, 9))
      )
      )

    SELECT id, trim(regexp_substr(OLD, '[^/]+', 1, LEVEL)) OLD,  
           trim(regexp_substr(NEW, '[^/]+', 1, LEVEL)) NEW
    FROM DATA
      CONNECT BY LEVEL <= regexp_count(old, '/')+1;




END;
 /

输出:

    12  L-D / T-E   L-E / T-E
13  L-D / T-E   L-D / T-D
14  L-D / T-E   L-E / T-D
12  L-D L-E
12  T-E T-E
13  T-E T-D
13  L-D L-D
12  T-E T-E
13  T-E T-D

第 12 行被定位了 3 次,而应该只是一次。

【问题讨论】:

  • 分割字符串的逻辑没有问题,获得额外行的唯一原因是循环循环不受 connect by 子句限制。我给出的示例仅适用于 1 行。当您将它应用于具有多行的表时,您需要按照我在这里解释的方式 lalitkumarb.wordpress.com/2015/03/04/split-comma-delimited-strings-in-a-table-using-oracle -sql/

标签: sql string oracle split


【解决方案1】:

应该是简单的方法:

  • 使用 SUBSTR 标识要拆分的行
  • 使用 REGEXP_SUBSTR 分割行

识别要拆分的行:

SUBSTR(OLD,3,1) <> SUBSTR(NEW, 3,1)
   AND 
SUBSTR(OLD, 9)  <> SUBSTR(NEW, 9)

要拆分行看看:

例如,

SQL> WITH DATA AS
  2    (SELECT OLD
  3    FROM t
  4    WHERE SUBSTR(OLD,3,1) <> SUBSTR(NEW, 3,1)
  5    AND SUBSTR(OLD, 9)    <> SUBSTR(NEW, 9)
  6    )
  7  SELECT trim(regexp_substr(OLD, '[^/]+', 1, LEVEL)) OLD
  8  FROM data
  9    CONNECT BY LEVEL <= regexp_count(OLD, '/')+1;

OLD
------------------------
L-D
T-E

SQL>

现在您需要做的就是INSERT 使用上面的 SELECT 语句和 DELETE 我演示的旧行 here

【讨论】:

  • 这样我就可以看到这里发生了什么:所以,我们通过使用子字符串使用“with data as”创建一个数据子集,这个子集称为数据? - 然后我们从“LEVEL”是正则表达式匹配名称的那个子集中进行选择? Connect by 是匹配器吗?我不完全理解正在发生的一切,但我有一个更好的主意。你介意看看sqlfiddle.com/#!4/0213a/25 并告诉我我做错了什么吗?谢谢。
  • 您介意看看更新后的帖子吗?
  • @SteveGreen,拆分字符串的逻辑没有问题,您获得额外行的唯一原因是在 connect by 子句中不受限制的循环循环。我给出的示例仅适用于 1 行。当您将它应用于具有多行的表时,您需要按照我在这里解释的方式 lalitkumarb.wordpress.com/2015/03/04/split-comma-delimited-strings-in-a-table-using-oracle -sql/
猜你喜欢
  • 2020-12-25
  • 1970-01-01
  • 2020-09-24
  • 2021-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-30
  • 2013-12-01
相关资源
最近更新 更多