ajm*_*d04 2 sql plsql oracle11g
我有一个表,其中一列具有逗号分隔值,(例如:经度,纬度,经度1,纬度1等).
现在我需要交换像(纬度,经度,纬度1,经度1等)的值.
至于试用目的:我创建了一个表如下:
CREATE TABLE string_table
(
slno NUMBER,
old_string VARCHAR2(50),
new_string VARCHAR2(50)
);
/
INSERT INTO STRING_TABLE (SLNO, OLD_STRING)
VALUES (1, '1,2,3,4,5,6');
INSERT INTO STRING_TABLE (SLNO, OLD_STRING)
VALUES (2, '1,2,3,4,5');
INSERT INTO STRING_TABLE (SLNO, OLD_STRING)
VALUES (3, 'a,b,c,d,e,f');
INSERT INTO STRING_TABLE (SLNO, OLD_STRING)
VALUES (4, 'a,b,c,d,e');
COMMIT;
/
Run Code Online (Sandbox Code Playgroud)
现在表格如下:
slno old_string new_string
----- ----------------------
1 1,2,3,4,5,6
2 1,2,3,4,5
3 a,b,c,d,e,f
4 a,b,c,d,e
Run Code Online (Sandbox Code Playgroud)
我需要将交换的值更新为new_string列,结果应如下所示:
slno old_string new_string
----- ----------------------
1 1,2,3,4,5,6 2,1,4,3,6,5
2 1,2,3,4,5 2,1,4,3,5
3 a,b,c,d,e,f b,a,d,c,f,e
4 a,b,c,d,e b,a,d,c,e
Run Code Online (Sandbox Code Playgroud)
到目前为止我所做的是使用如下所示的使用COLLECTION的PL/SQL代码,并且工作正常:
SET serveroutput ON
DECLARE
TYPE my_type IS TABLE OF VARCHAR2(50);
my_obj my_type := my_type();
l_temp_var VARCHAR2(50);
l_string VARCHAR2(200);
BEGIN
FOR i IN
( SELECT slno, old_string FROM string_table
)
loop
FOR j IN
(SELECT regexp_substr(i.old_string,'[^,]+',1, LEVEL) val
FROM dual
CONNECT BY regexp_substr(i.old_string, '[^,]+', 1, LEVEL) IS NOT NULL
)
loop
my_obj.EXTEND;
my_obj(my_obj.LAST) := j.val;
IF mod(my_obj.count,2)= 0 THEN
l_temp_var := my_obj(my_obj.LAST -1);
my_obj(my_obj.LAST-1) := my_obj(my_obj.LAST) ;
my_obj(my_obj.LAST):= l_temp_var;
END IF;
END LOOP;
FOR i IN my_obj.FIRST..my_obj.LAST
loop
l_string := l_string||my_obj(i)||',';
END loop;
l_string := substr(l_string , 1, length(l_string)-1);
update string_table
SET new_string = l_string
WHERE slno = i.slno;
l_string := NULL;
my_obj := my_type();
END loop;
COMMIT;
END;
/
Run Code Online (Sandbox Code Playgroud)
我认为这个解决方案非常冗长,是否还有其他好/短/简单方法来交换预期结果的值?
在此先感谢;)
您可以使用该connect by
语法将逗号分隔的列表拆分为单独的元素,并以不同的顺序将它们重新组合在一起,所有这些都使用纯SQL.两个稍微棘手的位是交换对,这可以通过将每个位置向上或向下调整一个来完成,具体取决于它是奇数还是偶数; 并将此语法同时应用于多行数据,这可以通过使用确定性函数的技巧来完成:
select slno, old_string,
listagg(item, ',') within group (order by new_pos) as new_string
from (
select slno, old_string, regexp_substr(old_string, '[^,]+', 1, level) as item,
case when mod(level, 2) = 1 then level + 1
else level - 1 end as new_pos
from string_table
connect by level <= regexp_count(old_string, '[^,]+')
and prior slno = slno
and prior sys_guid() is not null
)
group by slno, old_string;
SLNO OLD_STRING NEW_STRING
---------- -------------------- --------------------
1 1,2,3,4,5,6 2,1,4,3,6,5
2 1,2,3,4,5 2,1,4,3,5
3 a,b,c,d,e,f b,a,d,c,f,e
4 a,b,c,d,e b,a,d,c,e
Run Code Online (Sandbox Code Playgroud)
然后,您可以将其用作a的using
子句merge
来更新原始表:
merge into string_table st
using (
select slno, old_string,
listagg(item, ',') within group (order by new_pos) as new_string
from (
select slno, old_string,
regexp_substr(old_string, '[^,]+', 1, level) as item,
case when mod(level, 2) = 1 then level + 1
else level - 1 end as new_pos
from string_table
connect by level <= regexp_count(old_string, '[^,]+')
and prior slno = slno
and prior sys_guid() is not null
)
group by slno, old_string
) tmp
on (tmp.slno = st.slno)
when matched then
update set st.new_string = tmp.new_string;
select * from string_table order by slno;
SLNO OLD_STRING NEW_STRING
---------- -------------------- --------------------
1 1,2,3,4,5,6 2,1,4,3,6,5
2 1,2,3,4,5 2,1,4,3,5
3 a,b,c,d,e,f b,a,d,c,f,e
4 a,b,c,d,e b,a,d,c,e
Run Code Online (Sandbox Code Playgroud)
SQL Fiddle包括内部查询产生的内容.
如果你需要更普遍地使用它,你可以创建一个函数:
create or replace function swap_pairs (p_old_string varchar2)
return varchar2 as
l_new_string string_table.new_string%type;
begin
select listagg(item, ',') within group (order by new_pos)
into l_new_string
from (
select regexp_substr(p_old_string, '[^,]+', 1, level) as item,
case when mod(level, 2) = 1 then level + 1
else level - 1 end as new_pos
from dual
connect by level <= regexp_count(p_old_string, '[^,]+')
);
return l_new_string;
end;
/
update string_table set new_string = swap_pairs(old_string);
Run Code Online (Sandbox Code Playgroud)
当然,首先在列中存储逗号分隔值并不是一个好主意; 如果您有多对,则每个值应该是子表中的自己的列.如果您要添加新列,我真的会认真考虑改进数据模型.有时你会被你所拥有的东西困住,即使你可以将数据分开,这种技术对于进行一次性练习也很有用.
归档时间: |
|
查看次数: |
697 次 |
最近记录: |