我有一个带有列的表:
表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~"
答案 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;