oracle触发器+存储过程发送http请求

您所在的位置:网站首页 oracle触发器性能 oracle触发器+存储过程发送http请求

oracle触发器+存储过程发送http请求

2023-08-23 03:53| 来源: 网络整理| 查看: 265

 背景

项目遇到这样一个需求:  由于数据库是第三方系统的Oracle数据库,我们需要时刻同步该数据库中的告警记录表,并在我平台中存储或通知。鉴于这样的需求,考虑通过oracle 的 触发器加存储过程实现发送http请求的方案实现。

方案

1、在Oracle中编写存储过程,实现调用http接口。

2、在Oracle中编写触发器,实现告警表的行变化触发存储过程。

3、我们项目提供一个http接口供存储过程调用,并实现进一步定制操作。

实现 1、创建存储过程

直接上代码

在oracle 的sql执行窗口中执行  存储过程创建命令 

create or replace PROCEDURE "PRO_POSTREQ" ( guid in varchar2,res out varchar2) as begin DECLARE req UTL_HTTP.REQ; resp UTL_HTTP.RESP; value VARCHAR2(1024); -- URL to post to v_url VARCHAR2(4000) := 'http://127.0.0.1:8902/api/service/getservicestatus?uid='||guid; v_param VARCHAR2(4000) := '1'; v_param_length NUMBER := LENGTHB(v_param); BEGIN DBMS_OUTPUT.ENABLE (buffer_size=>null); req := UTL_HTTP.BEGIN_REQUEST (url=> v_url, method => 'POST'); UTL_HTTP.SET_BODY_CHARSET('UTF-8'); UTL_HTTP.SET_HEADER (r => req, name => 'Content-Type', value => 'application/x-www-form-urlencoded'); UTL_HTTP.SET_HEADER(req, 'Keep-Alive', ' timeout=1'); UTL_HTTP.SET_HEADER (r => req, name => 'Content-Length', value => v_param_length); UTL_HTTP.WRITE_RAW (r => req, data => UTL_RAW.CAST_TO_RAW(v_param)); resp := UTL_HTTP.GET_RESPONSE(req); LOOP UTL_HTTP.READ_LINE(resp, value, TRUE); DBMS_OUTPUT.PUT_LINE(value); END LOOP; UTL_HTTP.END_RESPONSE(resp); EXCEPTION WHEN UTL_HTTP.END_OF_BODY THEN UTL_HTTP.END_RESPONSE(resp); END; end PRO_POSTREQ; 2. 创建触发器

执行 存储过程创建命令

create or replace TRIGGER "TR_AFTER_INSERT_EMPLOYEE" after insert or update on TEST for each row declare res varchar2(2000); begin --PRO_POSTREQ(RTRIM(:new.SRVTRANSDATETIME),RTRIM(:new.CARDNO),RTRIM(:new.MID),RTRIM(:new.TRANAMT),RTRIM(:new.CARDKIND),RTRIM(:new.SRVSTAN)); PRO_POSTREQ(:new.Name,res); END TR_BEFORE_INSERT_EMPLOYEE;

解释:

1. => 是 Oracle 中调用 存储过程的时候,  指定 参数名进行调用。:= 是赋值语句。 = 是if的判断语句。

2.触发器中的【:new】是 oracle PL/ sql的关键字。

NEW关键字在什么情况下使用? ------最佳解决方案-------------------- oracle默认的 用old代表老数据 new代表新数据 不过二者在使用时是有限制的 insert时 只有new 没有old  delete时 只有old 没有new update时 二者都可用 ————————————————

3. 定义存储过程时,参数中 in/out 代表输出/输出参数。 varchar/varchar2不用指定参数长度。

4. 触发器中res 的类型是varchar,此时就需要定义长度。

5. 触发器和存储过程可以调试,F5 插入断点,点击 运行即可进行步进调试。

调试与断点

6.触发器中少了 for each row会抛出  NEW 或 OLD 引用不允许在表级触发器中错误

3. 增加访问控制权限

在调试和调用存储过程的访问http接口时 提示 HTTP 请求失败,网络访问被访问控制列表 (ACL) 拒绝。可执行如下代码:YONGHU是我当前的用户,一定要大写,不然会提示  ACL 无效:无法解析的主用户。

--添加acl和权限控制(sql语句执行的方式来执行) begin dbms_network_acl_admin.create_acl ( -- 创建访问控制文件(ACL) acl => 'utl_http.xml', -- 文件名称 description => 'HTTP Access', -- 描述 principal => 'YONGHU', -- 授权或者取消授权账号,大小写敏感 is_grant => TRUE, -- 授权还是取消授权 privilege => 'connect', -- 授权或者取消授权的权限列表 start_date => null, -- 起始日期 end_date => null -- 结束日期 ); dbms_network_acl_admin.add_privilege ( -- 添加访问权限列表项 acl => 'utl_http.xml', -- 刚才创建的acl名称 principal => 'YONGHU', -- 授权或取消授权用户 is_grant => TRUE, -- 与上同 privilege => 'resolve', -- 权限列表 start_date => null, end_date => null ); dbms_network_acl_admin.assign_acl ( -- 该段命令意思是允许访问acl名为utl_http.xml下授权的用户,使用oracle网络访问包,所允许访问的目的主机,及其端口范围。 acl => 'utl_http.xml', host => '127.0.0.1', -- ip地址或者域名,填写https://localhost:9000/hello与https://localhost:9000/是会报host无效的 -- 且建议使用ip地址或者使用域名,若用localhost,当oracle不是安装在本机上的情况下,会出现问题 lower_port => 8902, -- 允许访问的起始端口号 upper_port => Null -- 允许访问的截止端口号 ); commit; end; 4. 插入数据测试 insert into test (id,name,value) values(1,'张三','zhangsan'); insert into test (id,name,value) values(1,'李四','lisi'); insert into test (id,name,value) values(1,'王五','wangwu');

这样就成功收到 存储过程的http接口调用啦

参考链接:

通过oracle触发器调用存储过程发送http请求

Oracle触发器中的NEW和Old关键字说明

 

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3