热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

背景项目遇到这样一个需求:由于数据库是第三方系统的Oracle数据库,我们需要时刻同步该数据库中的告警记录表,并在我平台中存储或通知。鉴
 背景

项目遇到这样一个需求:  由于数据库是第三方系统的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) asbeginDECLAREreq UTL_HTTP.REQ;resp UTL_HTTP.RESP;value VARCHAR2(1024); -- URL to post tov_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);BEGINDBMS_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);LOOPUTL_HTTP.READ_LINE(resp, value, TRUE);DBMS_OUTPUT.PUT_LINE(value);END LOOP;UTL_HTTP.END_RESPONSE(resp);EXCEPTIONWHEN UTL_HTTP.END_OF_BODY THENUTL_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 rowdeclare 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语句执行的方式来执行)begindbms_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关键字说明

 

 


推荐阅读
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 本文介绍了django中视图函数的使用方法,包括如何接收Web请求并返回Web响应,以及如何处理GET请求和POST请求。同时还介绍了urls.py和views.py文件的配置方式。 ... [详细]
  • 解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法
    本文介绍了解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法,包括检查location配置是否正确、pass_proxy是否需要加“/”等。同时,还介绍了修改nginx的error.log日志级别为debug,以便查看详细日志信息。 ... [详细]
  • 延迟注入工具(python)的SQL脚本
    本文介绍了一个延迟注入工具(python)的SQL脚本,包括使用urllib2、time、socket、threading、requests等模块实现延迟注入的方法。该工具可以通过构造特定的URL来进行注入测试,并通过延迟时间来判断注入是否成功。 ... [详细]
  • 网络请求模块选择——axios框架的基本使用和封装
    本文介绍了选择网络请求模块axios的原因,以及axios框架的基本使用和封装方法。包括发送并发请求的演示,全局配置的设置,创建axios实例的方法,拦截器的使用,以及如何封装和请求响应劫持等内容。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • springmvc学习笔记(十):控制器业务方法中通过注解实现封装Javabean接收表单提交的数据
    本文介绍了在springmvc学习笔记系列的第十篇中,控制器的业务方法中如何通过注解实现封装Javabean来接收表单提交的数据。同时还讨论了当有多个注册表单且字段完全相同时,如何将其交给同一个控制器处理。 ... [详细]
  • 导出功能protectedvoidbtnExport(objectsender,EventArgse){用来打开下载窗口stringfileName中 ... [详细]
  • 本文讨论了如何在codeigniter中识别来自angularjs的请求,并提供了两种方法的代码示例。作者尝试了$this->input->is_ajax_request()和自定义函数is_ajax(),但都没有成功。最后,作者展示了一个ajax请求的示例代码。 ... [详细]
  • PDO MySQL
    PDOMySQL如果文章有成千上万篇,该怎样保存?数据保存有多种方式,比如单机文件、单机数据库(SQLite)、网络数据库(MySQL、MariaDB)等等。根据项目来选择,做We ... [详细]
  • 欢乐的票圈重构之旅——RecyclerView的头尾布局增加
    项目重构的Git地址:https:github.comrazerdpFriendCircletreemain-dev项目同步更新的文集:http:www.jianshu.comno ... [详细]
author-avatar
拍友2502911223
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有