通过分隔符将CLOB拆分为多个VARCHAR2列

时间:2019-05-05 09:26:19

标签: sql oracle split

我有一个带有列的表:

  • f_name-Varchar
  • f_content-CLOB

表1

f_name     f_content
test1.txt  YL*1**50*1~
           RX*1~
           LR*2~
test2.txt  YL*1**49*1~
           EE*1~
           WW*2~

f_content超过4000个字符,有时超过10000个字符。

是否可以创建3个Varchar2列,并在每列中最多拆分4000个字符,直到最近的~才能覆盖整个CLOB?

输出为:

f_name     f_content       f_content_varchar1    f_content_varchar2    f_content_varchar3
test1.txt  YL*1**50*1~     YL*1**50*1~           RX*1~                  LR*2~
           RX*1~
           LR*2~
test2.txt  YL*1**49*1~      YL*1**49*1~         EE*1~                   WW*2~
           EE*1~
           WW*2~
  

请注意-我想将其分为3列,但只结束到最后〜,因此,例如,如果某行在字符4003上以〜结尾,则不应将最后一行添加到varchar列中,并始终考虑前一行以〜结尾。

一个例子是:

YL*1**50*1~
RX*1~
LR*2~

假设以4000个字符结尾

"YL*1**50*1~
RX*1~
LR"

然后在varchar column1中,它应该存储:

"YL*1**50*1~
RX*1~"

并且在varchar column2中,它应该存储:

"LR*2~"

2 个答案:

答案 0 :(得分:0)

如果可以使用CURSOR操纵多行,则以下脚本可以通过提供提示来帮助您。请注意,我考虑了20、40和60的终点。

重要提示:请先在测试数据库上测试此脚本

重要提示:在SELECT语句上添加必要的WHERE条件。否则,将选择所有记录

DECLARE @NAME NVARCHAR(MAX)
DECLARE @F_NAME NVARCHAR(MAX)

DECLARE @CUT_1 INT
DECLARE @CUT_2 INT


DECLARE db_cursor CURSOR FOR 
SELECT f_name,f_content 
FROM your_table 
--WHERE Plese add conditions to pick only columns you wants to adjust 

OPEN db_cursor  
FETCH NEXT FROM db_cursor INTO @F_NAME,@NAME  

WHILE @@FETCH_STATUS = 0  
BEGIN  

    DECLARE @A TABLE (POS INT)
    DECLARE @POS INT
    DECLARE @OLDPOS INT
    SELECT @OLDPOS=0        

    SELECT @POS=PATINDEX('%~%',@name) 
    WHILE @POS > 0 AND @OLDPOS <> @POS
     BEGIN
       INSERT INTO @A VALUES (@POS)
       SELECT @OLDPOS=@POS
       SELECT @POS=PATINDEX('%~%',SUBSTRING(@NAME,@POS + 1,LEN(@NAME))) + @POS
    END

    SELECT @CUT_1 = ISNULL(MAX([pos]),4000) from @a where pos <= 4000
    SELECT @CUT_2 = ISNULL(MAX([pos]),@CUT_1+4000) from @a where pos > @CUT_1 AND pos <= @CUT_1+4000


    UPDATE your_table
    SET [f_content_varchar1] = SUBSTRING(@Name,1,@CUT_1),
        [f_content_varchar2] = SUBSTRING(@Name,@CUT_1+1,@CUT_2-@CUT_1),
        [f_content_varchar3] = SUBSTRING(@Name,@CUT_2+1,12000-@CUT_2) 
    WHERE f_name = @F_NAME

    DELETE FROM @A
    SET @POS = NULL
    SET @OLDPOS = NULL
    SET @OLDPOS = NULL


    FETCH NEXT FROM db_cursor INTO  @F_NAME,@NAME 
END 

CLOSE db_cursor  
DEALLOCATE db_cursor 

答案 1 :(得分:0)

如果仅关心前4000个字符,则将值转换为varchar2(),然后使用正则表达式:

select t1.*,
       regexp_substr(f_content_str, '[^~]+[~]', 1, 1) as part1,
       regexp_substr(f_content_str, '[^~]+[~]', 1, 2) as part2,
       regexp_substr(f_content_str, '[^~]+[~]', 1, 3) as part3
from (select t1.*,
             dbms_lob.substr(t1.f_content, 4000, 1)  as f_content_str
      from t
     ) t;