7. 相关链接

AEAI DP开发平台/ AEAI
ESB集成平台相关介质以及文档资料地址:

 

文档及代码附件下载:http://pan.baidu.com/s/1kVyMVQn

 

http://stackoverflow.com/questions/745538/create-function-through-mysqldb

 

How can I define a multi-statement function or procedure in using the MySQLdb lib in python?

Example:

import MySQLdb

db = MySQLdb.connect(db='service')

c = db.cursor()

c.execute("""DELIMITER //
CREATE FUNCTION trivial_func (radius float) 
    RETURNS FLOAT

    BEGIN
    IF radius > 1 THEN
        RETURN 0.0;
    ELSE
        RETURN 1.0;
    END IF;
END //

DELIMITER ;""")

Which creates the following traceback:

Traceback (most recent call last):
  File "proof.py", line 21, in <module>
    DELIMITER ;""")
  File "build/bdist.macosx-10.5-i386/egg/MySQLdb/cursors.py", line 173, in execute
  File "build/bdist.macosx-10.5-i386/egg/MySQLdb/connections.py", line 35, in defaulterrorhandler
_mysql_exceptions.ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DELIMITER //\nCREATE FUNCTION trivial_func (radius float) \n    RETURNS FLOAT\n\n   ' at line 1")

If I copy the same SQL directly into a mysql shell client, it works as expected

 
 

 

6. 总结说明

  本文介绍了在oracle存储过程中,使用UTL_HTTP工具包,通过创建请求报文以及使用HTTP协议来调用Web
Service,从创建oracle存储过程以及UTL_HTTP相关参数的配置,到通过PL/SQL
Developer测试调用以及sql代码进行调用来详细说明。

  附件为存储过程创建sql、调用sql以及接口程序和相关的数据库文件。

3 Answers

activeoldestvotes

up vote15down voteaccepted

The DELIMITER command is a MySQL shell client builtin, and it’s recognized only by that program (and MySQL Query Browser). It’s not necessary to use DELIMITER if you execute SQL statements directly through an API.

The purpose of DELIMITER is to help you avoid ambiguity about the termination of the CREATE FUNCTION statement, when the statement itself can contain semicolon characters. This is important in the shell client, where by default a semicolon terminates an SQL statement. You need to set the statement terminator to some other character in order to submit the body of a function (or trigger or procedure).

CREATE FUNCTION trivial_func (radius float) 
    RETURNS FLOAT

    BEGIN
    IF radius > 1 THEN
        RETURN 0.0; <-- does this semicolon terminate RETURN or CREATE FUNCTION?
    ELSE
        RETURN 1.0;
    END IF;
END

Since the API typically allows you to submit one SQL statement at a time, there’s no ambiguity — the interface knows that any semicolons inside the body of your function definition don’t terminate the whole CREATE FUNCTION statement. So there’s no need to change the statement terminator with DELIMITER.

 

3. 环境信息

操作系统:Windows7

Oracle:版本为oracle11g

Mysql:版本为mysql5.1

Jdk:  jdk1.6.0_10

   
 本文采用的都是符合SQL92版本的ANSI
SQL标准,所有的主流数据库都采用了SQL92的连接语法。由于这些数据库都出现SQL92标准发布之前,同时存在一些旧的连接语法,如下所示:

5.2.2 创建步骤

1、打开PL/SQL,并打开一个sql窗口

图片 1

 2、将创建存储过程的语句放入其中并执行

 图片 2

  这样一个调用web
service的存储过程样例就创建了,以下为详细的样例sql体

–创建存储过程,定义四个参数,入参:userid,code,name;出参:resmark

CREATE OR REPLACE PROCEDURE pro_test_ws(name in varchar2,resmark out varchar2) IS

–定义四个变量,http请求,http返回,请求报文,返回报文

  http_req    UTL_HTTP.REQ;

  http_Resp   UTL_HTTP.RESP;

  request_env VARCHAR2(32767);

  l_Replyline VARCHAR2(1000);

BEGIN

–开始pl/sql体

  request_env := ‘

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:demo="http://demo.service.wstest.agileai.com/">

   <soapenv:Header/>

   <soapenv:Body>

      <demo:sayHi>

         <!–Optional:–>

         <theGirlName>’|| name ||'</theGirlName>

      </demo:sayHi>

   </soapenv:Body>

</soapenv:Envelope>

‘;

–打印请求报文

dbms_output.put_line(request_env);

–请求WS地址

  http_req    := UTL_HTTP.

                 begin_request(‘http://localhost:6060/cam/services/UserSync?wsdl’,

                               ‘POST’,

                               UTL_HTTP.http_version_1_1);

保持连接状态

      Utl_Http.Set_Persistent_Conn_Support(http_req, TRUE);

–设置编码

      Utl_Http.Set_Header(http_req, ‘Content-Type’, ‘text/xml;charset=utf-8’);

      

      Utl_Http.Set_Header(http_req, ‘SOAPAction’, ”);

–设置字符集

      Utl_Http.Set_Body_Charset(http_req, ‘utf-8’);

–该参数代表我发送的POST报文多长,不可少

      Utl_Http.Set_Header(http_req, ‘Content-Length’, Lengthb(request_env));

      Utl_Http.Write_Line(http_req, request_env);

–赋值http返回

      http_Resp := Utl_Http.Get_Response(http_req);

–将请求报文赋值给 l_Replyline

      Utl_Http.Read_Text(http_Resp, l_Replyline);

      dbms_output.put_line(l_Replyline);

–付给存储过程出参

resmark:=l_Replyline;

END pro_test_ws;

   
 3)SQL92标准可以在各种数据库中通用,而旧的语法在不同的数据中的表现可能略有不同; 

5.2.1 基本语法

  以下为创建存储过程的基本语法

CREATE OR REPLACE PROCEDURE存储过程名 ( –定义参数 )

IS

定义变量

BEGIN

开始PL/SQL体

END

说明PL/SQL体结束

INNER
JOIN account a

5.3.1 使用PL/SQL Developer测试

1) 选中存储过程的名字,右键选择测试,进入测试页面

图片 3

 

2) 添加响应的参数值,F9或者点击按钮开始执行,执行后可以得到看到返回值

图片 4

 

3) 切换到DBMS输出页面,可以看到打印的内容

图片 5

WHERE
e.start_date < ‘2007-01-01’

5.3 调用存储过程

ON a.open_emp_id =
e.emp_id

1. 概述

  最近在ESB项目中,客户在各个系统之间的服务调用大多都是在oracle存储过程中进行的,本文就oracle存储过程调用web
service来进行说明。其他主流数据库,比如mysql和sql
service,调用web
service的方法这里就不做介绍了,本文主要用来介绍oracle存储过程调用Web
Service的方法。

  众所周知,在Web
Service通过HTTP协议发送请求和接收结果时,发送的请求内容和结果内容都采用XML格式封装,并增加了一些特定的HTTP消息头,以说明HTTP消息的内容格式,这些特定的HTTP消息头和XML内容格式就是SOAP协议。SOAP协议是基于HTTP协议的,两者的关系就好比高速公路是基于普通公路改造的,在一条公路上加上隔离栏后就成了高速公路。

  同理,在oracle的存储过程中能不能也通过创建XML格式的报文+HTTP协议来调用Web
Service呢?答案是肯定的,在ORACLE中有一个名叫UTL_HTTP的工具包,我们可以通过这个工具包来实现存储过程调用Web Service。

  上文提到的AEAI
ESB是数通畅联的核心产品之一,可以实现WEB服务开发和WEB服务注册等功能,本文的接口样例,本考虑使用ESB创建的WEB服务,但是由于涉及到的需要介绍的内容和本文主题太远,所以采用了AEAI DP开发平台自带的Web服务样例来说明。有对AEAI
ESB感兴趣的读者可以通过本文最后的相关链接查找了解。

ON a.open_emp_id =
e.emp_id

5.3.2 使用sql代码调用

DECLARE

resmark varchar2(1000);

BEGIN

  pro_test_ws(”小郑’,resmark);

  DBMS_OUTPUT.PUT_LINE(resmark);

END;

1) 打开sql窗口,执行上面的sql语句

图片 6

2) 查看输出信息

图片 7

  1处为存储过程打印的信息,2为调用时打印输出的信息

FROM
branch b

5.2.3 关键点说明

  在存储过程中,使用UTL_HTTP工具包调用web服务时,几个关键方法的使用说明

1. 通过设置请求地址、方式、协议版本,得到http请求对象

http_req    := UTL_HTTP.

                 begin_request(‘ http://localhost:6060/wstest_project/services/HelloWorld?wsdl ‘,

                               ‘POST’,

                               UTL_HTTP.http_version_1_1);

2. 设置协议保持连接状态

Utl_Http.Set_Persistent_Conn_Support(http_req, TRUE);

3. 设置请求编码,SOAPAction
header的值为空串(“”)表示SOAP消息的目的地由HTTP请求的URI标识;无值则表示没有指定这条消息的目的地。

Utl_Http.Set_Header(http_req, ‘Content-Type’, ‘text/xml;charset=utf-8’);

Utl_Http.Set_Header(http_req, ‘SOAPAction’, ”);

4. 设置字符集

Utl_Http.Set_Body_Charset(http_req, ‘utf-8’);

5. 报文长度

Utl_Http.Set_Header(http_req, ‘Content-Length’, Lengthb(request_env));

6. 调用服务,发送报文

Utl_Http.Write_Line(http_req, request_env);

7. 得到返回体

http_Resp := Utl_Http.Get_Response(http_req);

8. 将返回报文赋值给变量

Utl_Http.Read_Text(http_Resp, l_Replyline);

ON
a.open_branch_id = br.branch_id;

2. 预期读者

  • 数通畅联新员工
  • 广大技术爱好者

 

5.1 创建样例接口

  使用AEAI
DP开发平台,创建自带WS服务的应用,如下图:

 图片 8

  选择数据库信息

图片 9

  部署应用后,查看刚刚创建的应用自带的WS服务

图片 10

 

SELECT
emp.emp_id AS emp_id,CONCAT(emp.fname,’ ‘,emp.lname) AS
em,

5. 操作步骤

 

5.2 创建存储过程

INNER
JOIN branch b

4. 名词解释

AEAI ESB:应用集成平台主要作为企业信息系统的“龙骨”来集成各业务系统,一般称之为企业服务总线(Enterprise Service BUS,ESB),在数通畅联软件的产品家族中应用集成平台命名为AEAI ESB。

AEAI DP:AEAI
DP应用开发平台专门用于开发MIS类的Java Web应用,也称Miscdp(Misc Develope
Platform)综合应用开发平台。 AEAI
DP应用开发平台在数通畅联软件产品家族中也作为扩展开发的支撑工具,比如:为AEAI Portal门户平台扩展开发Portlet组件、Web
Service和Http Service;为AEAI
BPM流程集成平台扩展开发业务流程表单及功能等。

存储过程:大型数据库系统中,一组为了完成特定功能的SQL
语句集,存储在数据库中,经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。

UTL_HTTP:oracle中自带的HTTP协议工具包,可以用来发送post请求。

PL/SQL Developer:一个集成开发环境,由Allround Automations公司开发,专门面向Oracle数据库存储的程序单元的开发

4)自连接

FROM
branch b

AND
b.`name` = ‘Woburn Branch’;

 

     —
例子2.查询Woburn支行中所有熟练柜员(在2007年以前入职的柜员)开设的账户

AND
(e.title = ‘Teller’ OR e.title = ‘Head Teller’);

AND
(e.title = ‘Teller’ OR e.title = ‘Head Teller’) ) em

 

结果如图所示:

 

 

 
  图片 11

 

那么更换ON语句的位置呢

例子4.假如执行经理决定举办一次面向银行柜员的象棋比赛,现在要创建所有对弈者的列表

 

   
 SELECT e.emp_id

 

     推荐使用SQL92标准 的连接方式,不推荐使用上面的连接方式,主要原因是:

     FROM employee e JOIN
department 

ON e.assigned_branch_id =
b.branch_id

AND
b.`name` = ‘Woburn Branch’;

WHERE
e.start_date < ‘2007-01-01’

  

 

INNER
JOIN account a

INNER
JOIN employee e

结果如图所示—无改变

 

   
 方式一:

AND
b.`name` = ‘Woburn Branch’;

   
 结果如图所示

ON e.assigned_branch_id =
b.branch_id

ON
a.open_emp_id = em.emp_id

INNER
JOIN account a

而执行过程是数据库服务器负责(我只要结果集*_*)(但是左连接,右连接的问题,还不是很确定,稍后还要进行测试一下)

FROM
employee e INNER JOIN employee emp

SELECT
a.account_id, a.product_cd,a.open_date

‘VS’,
CONCAT(emp.fname,’ ‘,emp.lname) as TEAM_B

   
 

AND
(e.title = ‘Teller’ OR e.title = ‘Head Teller’)

     1)连接条件和过滤条件被分隔到两个子句中(ON子句和WHERE子句),使得查询语句更利于理解;

发表评论

电子邮件地址不会被公开。 必填项已用*标注