如何在 Oracle 数据库中对多行文本进行排序?
How to sort multiline text in Oracle db?
我需要创建一个脚本,如果字段中的文本超过一行,该脚本将对 table B 中所有记录的 A 列中的所有值进行排序(和更新)。
有什么办法吗?我是 Oracle 世界的初学者,非常感谢您的帮助。
Table B
id column A
1 aaa
2 bb \n aa\n dd \n cc
3 bb \n aa
*(\n 为新行)
我需要它
Table B
id column A
1 aaa
2 aa \n bb\n cc \n dd
3 aa \n bb
你可以试试这个,它使用'\n'分隔文本的各个值并对其进行排序。然后按您提到的升序合并它。
with mydata(id,text)
as
(
select 1, replace('aaa','\n',chr(10)) from dual
union all
select 2, replace('bb \n aa\n dd \n cc','\n',chr(10)) from dual
union all
select 3, replace('bb \n aa','\n',chr(10)) from dual
)
SELECT ID,REPLACE(LISTAGG(text_splitted,chr(10)) WITHIN GROUP (ORDER BY trim(text_splitted)),CHR(10),'\n')
FROM
(
SELECT t1.id,
REGEXP_SUBSTR(t1.text, '([^'||chr(10)||'])+', 1, t2.COLUMN_VALUE) text_splitted
FROM mydata t1 CROSS JOIN
TABLE
(
CAST
(
MULTISET
(
SELECT LEVEL
FROM DUAL
CONNECT BY LEVEL <= REGEXP_COUNT(t1.text, '([^'||chr(10)||'])+')
)
AS SYS.odciNumberList
)
) t2
)
GROUP BY ID;
'\n'
- 换行符将在数据库中保存为 CHR(10)
(ASCII
值)。我用同样的方法进行转换。后来用\n来显示。
Oracle 设置:
CREATE TABLE Table_B ( id, column_A ) AS
SELECT 1, 'aaa' FROM DUAL UNION ALL
SELECT 2, 'bb ' || CHR(10) || ' aa' || CHR(10) || ' dd ' || CHR(10) || ' cc' FROM DUAL UNION ALL
SELECT 3, 'bb ' || CHR(10) || ' aa' FROM DUAL;
也用我的 :
CREATE OR REPLACE FUNCTION split_String(
i_str IN VARCHAR2,
i_delim IN VARCHAR2 DEFAULT ','
) RETURN SYS.ODCIVARCHAR2LIST DETERMINISTIC
AS
p_result SYS.ODCIVARCHAR2LIST := SYS.ODCIVARCHAR2LIST();
p_start NUMBER(5) := 1;
p_end NUMBER(5);
c_len CONSTANT NUMBER(5) := LENGTH( i_str );
c_ld CONSTANT NUMBER(5) := LENGTH( i_delim );
BEGIN
IF c_len > 0 THEN
p_end := INSTR( i_str, i_delim, p_start );
WHILE p_end > 0 LOOP
p_result.EXTEND;
p_result( p_result.COUNT ) := SUBSTR( i_str, p_start, p_end - p_start );
p_start := p_end + c_ld;
p_end := INSTR( i_str, i_delim, p_start );
END LOOP;
IF p_start <= c_len + 1 THEN
p_result.EXTEND;
p_result( p_result.COUNT ) := SUBSTR( i_str, p_start, c_len - p_start + 1 );
END IF;
END IF;
RETURN p_result;
END;
/
查询:
SELECT id,
LISTAGG( COLUMN_VALUE, CHR(10) )
WITHIN GROUP ( ORDER BY TRIM(COLUMN_VALUE) )
AS sorted_column_a
FROM Table_B B,
TABLE( split_String( b.column_a, CHR(10) ) ) s
GROUP BY ID
输出
ID SORTED_COLUMN_A
---------- ----------------
1 aaa
2 aa
bb
cc
dd
3 aa
bb
更新
UPDATE TABLE_B b
SET column_a = ( SELECT LISTAGG( COLUMN_VALUE, CHR(10) )
WITHIN GROUP ( ORDER BY TRIM(COLUMN_VALUE) )
FROM TABLE( split_String( b.column_a, CHR(10) ) ) );
我需要创建一个脚本,如果字段中的文本超过一行,该脚本将对 table B 中所有记录的 A 列中的所有值进行排序(和更新)。
有什么办法吗?我是 Oracle 世界的初学者,非常感谢您的帮助。
Table B
id column A
1 aaa
2 bb \n aa\n dd \n cc
3 bb \n aa
*(\n 为新行)
我需要它
Table B
id column A
1 aaa
2 aa \n bb\n cc \n dd
3 aa \n bb
你可以试试这个,它使用'\n'分隔文本的各个值并对其进行排序。然后按您提到的升序合并它。
with mydata(id,text)
as
(
select 1, replace('aaa','\n',chr(10)) from dual
union all
select 2, replace('bb \n aa\n dd \n cc','\n',chr(10)) from dual
union all
select 3, replace('bb \n aa','\n',chr(10)) from dual
)
SELECT ID,REPLACE(LISTAGG(text_splitted,chr(10)) WITHIN GROUP (ORDER BY trim(text_splitted)),CHR(10),'\n')
FROM
(
SELECT t1.id,
REGEXP_SUBSTR(t1.text, '([^'||chr(10)||'])+', 1, t2.COLUMN_VALUE) text_splitted
FROM mydata t1 CROSS JOIN
TABLE
(
CAST
(
MULTISET
(
SELECT LEVEL
FROM DUAL
CONNECT BY LEVEL <= REGEXP_COUNT(t1.text, '([^'||chr(10)||'])+')
)
AS SYS.odciNumberList
)
) t2
)
GROUP BY ID;
'\n'
- 换行符将在数据库中保存为 CHR(10)
(ASCII
值)。我用同样的方法进行转换。后来用\n来显示。
Oracle 设置:
CREATE TABLE Table_B ( id, column_A ) AS
SELECT 1, 'aaa' FROM DUAL UNION ALL
SELECT 2, 'bb ' || CHR(10) || ' aa' || CHR(10) || ' dd ' || CHR(10) || ' cc' FROM DUAL UNION ALL
SELECT 3, 'bb ' || CHR(10) || ' aa' FROM DUAL;
也用我的
CREATE OR REPLACE FUNCTION split_String(
i_str IN VARCHAR2,
i_delim IN VARCHAR2 DEFAULT ','
) RETURN SYS.ODCIVARCHAR2LIST DETERMINISTIC
AS
p_result SYS.ODCIVARCHAR2LIST := SYS.ODCIVARCHAR2LIST();
p_start NUMBER(5) := 1;
p_end NUMBER(5);
c_len CONSTANT NUMBER(5) := LENGTH( i_str );
c_ld CONSTANT NUMBER(5) := LENGTH( i_delim );
BEGIN
IF c_len > 0 THEN
p_end := INSTR( i_str, i_delim, p_start );
WHILE p_end > 0 LOOP
p_result.EXTEND;
p_result( p_result.COUNT ) := SUBSTR( i_str, p_start, p_end - p_start );
p_start := p_end + c_ld;
p_end := INSTR( i_str, i_delim, p_start );
END LOOP;
IF p_start <= c_len + 1 THEN
p_result.EXTEND;
p_result( p_result.COUNT ) := SUBSTR( i_str, p_start, c_len - p_start + 1 );
END IF;
END IF;
RETURN p_result;
END;
/
查询:
SELECT id,
LISTAGG( COLUMN_VALUE, CHR(10) )
WITHIN GROUP ( ORDER BY TRIM(COLUMN_VALUE) )
AS sorted_column_a
FROM Table_B B,
TABLE( split_String( b.column_a, CHR(10) ) ) s
GROUP BY ID
输出
ID SORTED_COLUMN_A
---------- ----------------
1 aaa
2 aa
bb
cc
dd
3 aa
bb
更新
UPDATE TABLE_B b
SET column_a = ( SELECT LISTAGG( COLUMN_VALUE, CHR(10) )
WITHIN GROUP ( ORDER BY TRIM(COLUMN_VALUE) )
FROM TABLE( split_String( b.column_a, CHR(10) ) ) );