暂无图片
ORACLE 一道SQL题
我来答
分享
Thomas
2022-10-21
ORACLE 一道SQL题

dba_db_links有字段host, 其内容类似以下:

(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 135.12.5.55)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = 135.12.5.56)(PORT = 1521))
)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = TESTMDB)
)
)

这里举的是连RAC的设置,所以有两个IP,如果连单实例,那就是一个IP。

要写个SQL,从host字段中提取出IP地址和服务名两项,查询结果像这样:

host                                                       service_bane

------------------------------------------------------------

135.12.5.55/135.12.5.56                         TESTMDB

host项,如只有一个IP,就显示该IP(单实例时),如有多个IP,IP之间用/分隔。

这个SQL怎么写? 

我来答
添加附件
收藏
分享
问题补充
5条回答
默认
最新
virvle

使用如下命令,请自行替换下文件名

cat test.log|grep HOST|awk -F '=' '{print $4}'|awk -F ')' '{print $1}'|awk '{print $1}'|sed ":a;N;s/\n/\//g;ta"   
复制
暂无图片 评论
暂无图片 有用 0
打赏 0
Thomas

兄弟,是写SQL,不是在OS层面操作

暂无图片 评论
暂无图片 有用 0
打赏 0
virvle

– 粗暴拼接,若是还有,更改instr函数中出现的位置 instr(‘字符串’,‘查找字符’,‘开始位置’,‘第几次出现’)

select REPLACE(substr(a,instr(a,'HOST')+7,(instr(a,'PORT')-2)-(instr(a,'HOST')+7))||'/'||
substr(a,instr(a,'HOST',1,2)+7,(instr(a,'PORT',1,2)-2)-(instr(a,'HOST',1,2)+7))||'/'||
substr(a,instr(a,'HOST',1,3)+7,(instr(a,'PORT',1,3)-2)-(instr(a,'HOST',1,3)+7))||'/'||
substr(a,instr(a,'HOST',1,4)+7,(instr(a,'PORT',1,4)-2)-(instr(a,'HOST',1,4)+7)),'//','')
 from test
复制

使用到的测试表:
新建测试表,包含一个字段,并插入你给定的字符串

create  table test(a varchar2(1000));
复制
暂无图片 评论
暂无图片 有用 0
打赏 0
DarkAthena

如果都是IP的话,就正则直接找IP

with t as (select '(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 135.12.5.55)(PORT = 1521)) (ADDRESS = (PROTOCOL = TCP)(HOST = 135.12.5.56)(PORT = 1521)) ) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = TESTMDB) ) )' str from dual) select listagg(regexp_substr(str, '(\d+\.\d+.\d+.\d+)', 1, level),'/') from t connect by level <= regexp_count(str, '(\d+\.\d+.\d+.\d+)');
复制

image.png


带域名的

with t as (select '(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 135.12.5.55)(PORT = 1521)) (ADDRESS = (PROTOCOL = TCP)(HOST = 135.12.5.56)(PORT = 1521)) (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521)) ) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = TESTMDB) ) )' str from dual) select listagg(regexp_substr(str,'(HOST\s*=\s*)(.*?)(\))',1,level,'i',2),'/') from t connect by level <= regexp_count(str,'(HOST\s*=\s*)(.*?)(\))') ;
复制

image.png

暂无图片 评论
暂无图片 有用 0
打赏 0
Thomas

DarkAthena, 试了你的SQL,似乎在listagg后要加winthin group (order by ...)才行吧:

with t as
(select '(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 135.12.5.55)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = 135.12.5.56)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = TESTMDB)
)
)' str
from dual)
select listagg(regexp_substr(str,'(HOST\s*=\s*)(.*?)(\))',1,level,'i',2),'/') within group(order by null)
from t
connect by level <= regexp_count(str,'(HOST\s*=\s*)(.*?)(\))')
;

暂无图片 评论
暂无图片 有用 0
打赏 0
DarkAthena
2022-10-23
oracle18c开始,可以不用加within group了
回答交流
Markdown


请输入正文
提交
问题信息
请登录之后查看
邀请回答
暂无人订阅该标签,敬请期待~~
暂无图片墨值悬赏