当前位置:   article > 正文

Oracle如何从异库获取数据_如何获取其他用户数据库

如何获取其他用户数据库

常见的处理方法也许是创建创建database link,但dblink会对数据库性能造成影响(且会产生事务),而且不能传输大字段类型(如clob,bclob);

在不使用dblink的情况下如何实现呢?其实可以使用http请求实现,首先搭建一个http服务(post请求/get请求)返回需要的数据(返回数据类型可以是xml/json字符串,便于Oracle(xmltable/jsontable)解析),然后在Oracle语句块中请求对应服务进行操作便可。

HTTP GET方式:

  1. CREATE OR REPLACE FUNCTION FN_HTTP_GET (v_url VARCHAR2)
  2. RETURN VARCHAR2
  3. AS
  4. BEGIN
  5. DECLARE
  6. req UTL_HTTP.REQ;
  7. resp UTL_HTTP.RESP;
  8. v_line VARCHAR2 ( 4000 );
  9. v_text VARCHAR2 ( 4000 );
  10. BEGIN
  11. v_text := '';
  12. BEGIN
  13. req := UTL_HTTP.BEGIN_REQUEST ( url => v_url, method => 'GET' );
  14. UTL_HTTP.SET_BODY_CHARSET('UTF-8');
  15. UTL_HTTP.SET_HEADER(req, 'Content-Type', 'application/x-www-form-urlencoded');
  16. resp := UTL_HTTP.GET_RESPONSE ( req );
  17. LOOP
  18. UTL_HTTP.READ_LINE ( resp, v_line, TRUE );
  19. v_text := v_text || v_line;
  20. END LOOP;
  21. UTL_HTTP.END_RESPONSE( resp );
  22. UTL_HTTP.END_REQUEST( req );
  23. EXCEPTION
  24. WHEN UTL_HTTP.END_OF_BODY THEN
  25. UTL_HTTP.END_RESPONSE ( resp );
  26. WHEN OTHERS THEN
  27. UTL_HTTP.END_RESPONSE(resp);
  28. UTL_HTTP.END_REQUEST(req);
  29. END;
  30. return v_text;
  31. END;
  32. END;

 HTTP POST方式:

  1. CREATE OR REPLACE FUNCTION FN_HTTP_POST (v_url VARCHAR2, v_body VARCHAR2, v_body_type VARCHAR2)
  2. RETURN VARCHAR2
  3. AS
  4. BEGIN
  5. DECLARE
  6. req UTL_HTTP.REQ;
  7. resp UTL_HTTP.RESP;
  8. v_line VARCHAR2 ( 4000 );
  9. v_text VARCHAR2 ( 4000 );
  10. BEGIN
  11. v_text := '';
  12. BEGIN
  13. req := UTL_HTTP.BEGIN_REQUEST ( url => v_url, method => 'POST' );
  14. UTL_HTTP.SET_BODY_CHARSET('UTF-8');
  15. UTL_HTTP.SET_HEADER(req, 'Content-Type', v_body_type);
  16. utl_http.set_header(req, 'Content-Length',lengthb(v_body));
  17. utl_http.write_text(req, v_body);
  18. resp := UTL_HTTP.GET_RESPONSE ( req );
  19. LOOP
  20. UTL_HTTP.READ_LINE ( resp, v_line, TRUE );
  21. v_text := v_text || v_line;
  22. END LOOP;
  23. UTL_HTTP.END_RESPONSE( resp );
  24. UTL_HTTP.END_REQUEST( req );
  25. EXCEPTION
  26. WHEN UTL_HTTP.END_OF_BODY THEN
  27. UTL_HTTP.END_RESPONSE ( resp );
  28. WHEN OTHERS THEN
  29. UTL_HTTP.END_RESPONSE(resp);
  30. UTL_HTTP.END_REQUEST(req);
  31. END;
  32. return v_text;
  33. END;
  34. END;
  1. CREATE OR REPLACE
  2. FUNCTION HTTP_REQUEST(
  3. v_url VARCHAR2,--请求地址
  4. v_param VARCHAR2,--POST 相当于表单提交
  5. v_body clob,--POST body中的参数
  6. v_type varchar2--类型
  7. )return varchar2 is
  8. req UTL_HTTP.REQ;
  9. resp UTL_HTTP.RESP;
  10. v_line VARCHAR2 (4000);
  11. v_text VARCHAR2 (4000);
  12. v_param_length NUMBER ;
  13. v_body_length NUMBER;
  14. buffer VARCHAR2(32767);
  15. offset NUMBER := 1;
  16. amount NUMBER := 32767;
  17. begin
  18. IF V_TYPE='GET' THEN
  19. v_text := '';
  20. req := UTL_HTTP.BEGIN_REQUEST ( url => v_url, method => 'GET' );
  21. UTL_HTTP.SET_BODY_CHARSET('UTF-8');
  22. UTL_HTTP.SET_HEADER(req, 'Content-Type', 'application/x-www-form-urlencoded');
  23. resp := UTL_HTTP.GET_RESPONSE ( req );
  24. UTL_HTTP.READ_LINE ( resp, v_line, TRUE );
  25. v_text := v_text || v_line;
  26. UTL_HTTP.END_RESPONSE( resp );
  27. ELSIF V_TYPE='POST_FORM' THEN
  28. v_param_length := LENGTHB(v_param);
  29. req := UTL_HTTP.BEGIN_REQUEST (url=> v_url, method => 'POST');
  30. UTL_HTTP.SET_BODY_CHARSET('UTF-8');
  31. UTL_HTTP.SET_HEADER (r => req,
  32. name => 'Content-Type',
  33. VALUE => 'application/x-www-form-urlencoded');
  34. UTL_HTTP.SET_HEADER (r => req,
  35. name => 'Content-Length',
  36. VALUE => v_param_length);
  37. UTL_HTTP.WRITE_RAW (r => req,
  38. data => UTL_RAW.CAST_TO_RAW(v_param));
  39. resp := UTL_HTTP.GET_RESPONSE(req);
  40. UTL_HTTP.READ_LINE(resp, v_text, TRUE);
  41. UTL_HTTP.END_RESPONSE(resp);
  42. ELSE
  43. v_body_length := dbms_lob.getlength(v_body);
  44. req := UTL_HTTP.BEGIN_REQUEST (url=> v_url, method => 'POST');
  45. UTL_HTTP.SET_BODY_CHARSET('UTF-8');
  46. UTL_HTTP.SET_HEADER (r => req,
  47. name => 'Content-Type',
  48. VALUE => 'application/json;charset=utf-8');
  49. UTL_HTTP.SET_HEADER (r => req,
  50. name => 'Content-Length',
  51. VALUE => v_body_length);
  52. --分段输出请求参数,这个header设置很重要
  53. UTL_HTTP.SET_HEADER (req, 'Transfer-Encoding', 'chunked');
  54. --分段输出请求参数,避免内容超出长度限制
  55. WHILE (offset < v_body_length) LOOP
  56. dbms_lob.read(v_body, amount, offset, buffer);
  57. UTL_HTTP.WRITE_RAW(r => req, data => UTL_RAW.CAST_TO_RAW(buffer));
  58. offset := offset + amount;
  59. END LOOP;
  60. resp := UTL_HTTP.GET_RESPONSE(req);
  61. UTL_HTTP.READ_LINE(resp, v_text, TRUE);
  62. UTL_HTTP.END_RESPONSE(resp);
  63. END IF;
  64. return v_text;
  65. EXCEPTION
  66. WHEN UTL_HTTP.END_OF_BODY THEN
  67. UTL_HTTP.END_RESPONSE ( resp );
  68. WHEN OTHERS THEN
  69. UTL_HTTP.END_RESPONSE(resp);
  70. UTL_HTTP.END_REQUEST(req);
  71. end;

网络正常,单http调用失败,无法调用时,可能是ACL控制未开启。

  1. select * from dba_network_acls;
  2. Select * From dba_network_acl_privileges ;

dba_network_acls为assign_acl维护进去的
dba_network_acl_privileges为create_acl和add_privilege维护进去的

如果dba_network_acl_privileges中有可用的记录,那么我们可以跳过create_acl这一步,直接使用存在的xml文件来新增权限;如果没有,那么我们就先创建一个acl

  1. --添加acl和权限控制,若已存在访问控制文件(ACL),可不用再创建
  2. begin
  3. dbms_network_acl_admin.create_acl ( -- 创建访问控制文件(ACL)
  4. acl => 'utl_http.xml', -- 文件名称
  5. description => 'HTTP Access', -- 描述
  6. principal => 'YBZNFK', -- 授权或者取消授权账号,大小写敏感
  7. is_grant => TRUE, -- 授权还是取消授权
  8. privilege => 'connect', -- 授权或者取消授权的权限列表
  9. start_date => null, -- 起始日期
  10. end_date => null -- 结束日期
  11. );
  12. --acl中给用户增加一个resolve的权限
  13. dbms_network_acl_admin.add_privilege ( -- 添加访问权限列表项
  14. acl => 'utl_http.xml', -- 刚才创建的acl名称
  15. principal => 'YBZNFK', -- 授权或取消授权用户
  16. is_grant => TRUE, -- 与上同
  17. privilege => 'resolve', -- 权限列表
  18. start_date => null,
  19. end_date => null
  20. );
  21. --acl中添加要访问的目标网址(ip和域名均可),可以指定端口范围
  22. dbms_network_acl_admin.assign_acl ( -- 该段命令意思是允许访问acl名为utl_http.xml下授权的用户,使用oracle网络访问包,所允许访问的目的主机,及其端口范围。
  23. acl => 'utl_http.xml',
  24. host => '*', -- 访问接口服务的ip地址或者域名,*代表所有
  25. lower_port => null, -- 允许访问的起始端口号
  26. upper_port => Null -- 允许访问的截止端口号
  27. );
  28. commit;
  29. end;

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/559798
推荐阅读
相关标签
  

闽ICP备14008679号