用于查询ORACLE DB的分号的Regexp_Substr

时间:2019-02-13 11:09:44

标签: sql regex oracle oracle11g

我已经有了REGEXP_SUBSTR来分割分号,但是问题是,如果两个分号之间没有数据,则下一个数据将被移到前一列。

这是下面的示例。

Oracle DB列中的数据

public function updateProduct(Request $request)
{
    $this->validate($request, [ 
        'image' => 'required|array',
    ]); 
   $oProduct = Product::create([
    //insert data for product table
    )];

   $oProduct->images()->saveMany(collect($request->image)>map(function($image) 
  {
        return new Image([
            'image' => $image
        ]);
    }));

}

Here images() is hasMany relation with Product so that relationship access for 
this.

现在我的查询是

ColumnXYZ
A;;B

执行后在数据下方显示

SELECT REGEXP_SUBSTR(COLUMNXYZ, '[^;]+', 1, 1) as COL1,
       REGEXP_SUBSTR(COLUMNXYZ, '[^;]+', 1, 2) as COL2,
       REGEXP_SUBSTR(COLUMNXYZ, '[^;]+', 1, 3) as COL3,
FROM TABLE T

但是我需要以下格式的输出,因为两个分号之间没有值。

COL1  COL2  COl3
A      B    null

3 个答案:

答案 0 :(得分:0)

  SELECT   ROWNUM AS num_row,
           REGEXP_SUBSTR(REPLACE(REPLACE('A;;B', ';;', '; ;'),';;','; ;'), '[^;]+', 1, LEVEL) AS par_value
  FROM     dual
  CONNECT  BY REGEXP_SUBSTR(REPLACE(REPLACE('A;;B', ';;', '; ;'),';;','; ;'), '[^;]+', 1, LEVEL) IS NOT NULL

或者如果您需要空列:

SELECT  num_row,
        CASE
          WHEN par_value = '#$N#$' THEN NULL
          ELSE par_value
        END as par_value
FROM    (
          SELECT   ROWNUM AS num_row,
                   REGEXP_SUBSTR(REPLACE(REPLACE('A;;B', ';;', ';#$N#$;'),';;','; ;'), '[^;]+', 1, LEVEL) AS par_value
          FROM     dual
          CONNECT  BY
                   REGEXP_SUBSTR(REPLACE(REPLACE('A;;B', ';;', ';#$N#$;'),';;','; ;'), '[^;]+', 1, LEVEL) IS NOT NULL
        )

$ N#$是null的示例值

答案 1 :(得分:0)

这应该有效:

WITH cte AS (
    SELECT 'A;B;C' AS col FROM DUAL UNION
    SELECT 'A;B;' AS col FROM DUAL UNION
    SELECT ';B;C' AS col FROM DUAL UNION
    SELECT 'A;;C' AS col FROM DUAL UNION
    SELECT 'A;;' AS col FROM DUAL UNION
    SELECT ';B;' AS col FROM DUAL UNION
    SELECT ';;C' AS col FROM DUAL UNION
    SELECT ';;' FROM DUAL
)
SELECT col
    , REGEXP_SUBSTR(col, '([^;]*)(;|$)', 1, 1, '', 1) AS col1
    , REGEXP_SUBSTR(col, '([^;]*)(;|$)', 1, 2, '', 1) AS col2
    , REGEXP_SUBSTR(col, '([^;]*)(;|$)', 1, 3, '', 1) AS col3
FROM cte

模式([^;]*)(;|$)匹配零个或多个非分号,后跟分号或字符串结尾。分组用于将每个匹配项转换为两个子匹配项,例如A;变成A;

答案 2 :(得分:0)

您可以将replace'; ;'参数一起使用,然后将trim

with t1 as
(select replace('A;;B',';;','; ;') as str from dual 
),
     t2(col1,col2,col3) as
(
 select regexp_substr(str, '[^;]+', 1, 1),
        trim(regexp_substr(str, '[^;]+', 1, 2)),
        regexp_substr(str, '[^;]+', 1, 3) 
   from t1
)   
select * from t2;

  COL1  COL2  COL3
  ----  ----  ----
  A     null  B

编辑 取决于您的评论:

如果要按行结果,请考虑以下查询:

with t1 as
 (select replace('A;;B',';;','; ;') as str from dual)
   select trim(regexp_substr(str, '[^;]+', 1, level))
       as "Result String"
     from t1
    cross join dual
  connect by level <= length(regexp_replace(str, ';',''));

Result String
-------------
A

B