以下示例将创建存储过程、存储过程的预订和 DB2 Everyplace 应用程序来使用存储过程。示例应用程序的目的是让移动用户能够通过使用 DB2 Everyplace 远程存储过程调用来检查帐户余额, 并在储蓄帐户和支票帐户间转钱。有关如何在“DB2 通用数据库”中创建存储过程的信息,请查看《DB2 通用数据库应用程序开发指南》。
创建数据源
本示例使用名为 MYSAMPLE 的 DB2 数据库。您需要人工创建 MYSAMPLE 数据库。要创建 MYSAMPLE 数据库,在 DB2 命令提示符处输入下列语句:
CREATE table db2e.MYACCOUNT ( Name char(16), Saving int, Checking int) INSERT into db2e.MYACCOUNT values('Michael', 5000, 5000) INSERT into db2e.MYACCOUNT values('Frank', 5000, 5000)
创建数据库后,应创建存储过程来修改数据库中的数据。
创建存储过程
本示例使用名为 MYPROC() 的存储过程。这个过程采用 5 个参数:帐户名称、选项、转移金额、储蓄余额和支票余额。以下列表标识每个参数的用途:
帐户名称:用来标识帐户的输入参数。 选项:确定进行什么操作的输入参数。以下有三个选项: 1:检查余额。 2:从储蓄帐户向支票帐户转钱。 3:从支票帐户向储蓄帐户转钱。 转移金额:要在支票帐户和储蓄帐户之间转移的金额的输入参数。 储蓄余额:返回储蓄帐户的余额的输出参数。 支票余额:返回支票帐户的余额的输出参数。
以下代码构建存储过程:
SQL_API_RC SQL_API_FN myProc(char * szName, int * nCmd, int * nAmount, int * nSaving, int * nChecking) { SQLHENV henv; SQLHDBC hdbc; SQLHSTMT hstmt; SQLRETURN rc; int nRetSize; SQLCHAR str1[]="select saving, checking from db2e.myaccount where name = ?"; SQLCHAR str2[]="update db2e.myaccount set saving=saving - ?, checking=checking + ? where name=?"; SQLCHAR str3[]="update db2e.myaccount set saving=saving + ?, checking=checking - ? where name=?"; //**************************************************************** //* Prepare connection and statement //**************************************************************** rc = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); //checkerror rc = SQLAllocHandle( SQL_HANDLE_DBC, henv, &hdbc); //checkerror rc = SQLSetConnectAttr(hdbc, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF, SQL_NTS); //checkerror rc = SQLConnect(hdbc, NULL, SQL_NTS, NULL, SQL_NTS, NULL, SQL_NTS); //checkerror rc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt); //checkerror //**************************************************************** //* Update account //**************************************************************** if ( *nCmd == 2 || *nCmd == 3 ){ if ( *nCmd == 2 ){ //Transfer from saving to checking rc = SQLPrepare(hstmt, str2, SQL_NTS); //checkerror } if ( *nCmd == 3 ){ //Transfer from checking to saving rc = SQLPrepare(hstmt, str3, SQL_NTS); //checkerror } rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, (SQLPOINTER)nAmount, 0, NULL ); //checkerror rc = SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, (SQLPOINTER)nAmount, 0, NULL ); //checkerror rc = SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, (SQLPOINTER)szName, 0, NULL ); //checkerror rc = SQLExecute(hstmt); //checkerror } //**************************************************************** //* Retrieve account balance //**************************************************************** rc = SQLPrepare(hstmt, str1, SQL_NTS); //checkerror rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, (SQLPOINTER)szName, 0, NULL); //checkerror rc = SQLExecute(hstmt); //checkerror if ( rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO ) { while ( (rc = SQLFetch(hstmt) ) == SQL_SUCCESS ){ rc = SQLGetData( hstmt, (SQLSMALLINT)1, SQL_C_LONG, nSaving, sizeof(int) , &nRetSize ) ; //checkerror rc = SQLGetData( hstmt, (SQLSMALLINT)2, SQL_C_LONG, nChecking, sizeof(int) , &nRetSize ) ; //checkerror } } //**************************************************************** //* Clean up //**************************************************************** rc = SQLEndTran( SQL_HANDLE_DBC, hdbc, SQL_COMMIT ); SQLFreeHandle(SQL_HANDLE_STMT, hstmt); SQLDisconnect(hdbc); SQLFreeHandle(SQL_HANDLE_DBC, hdbc); SQLFreeHandle(SQL_HANDLE_ENV, henv); return (0); }
在 Win32 平台上,将存储过程构建成动态链接库(mydll.dll)后,将其复制至 \SQLLIB\function 目录。然后,注册存储过程。
DB2 CONNECT TO MYSAMPLE
CREATE PROCEDURE db2e.MYPROC (IN szName CHAR(16), IN nCmd INTEGER, IN nAmount INTEGER, OUT nSaving INTEGER, OUT nChecking INTEGER ) DYNAMIC RESULT SETS 1 LANGUAGE C PARAMETER STYLE GENERAL NO DBINFO FENCED MODIFIES SQL DATA PROGRAM TYPE SUB EXTERNAL NAME 'mydll!myProc'@
要运行脚本,输入下列命令:
db2 -td@ -vf regscript.scr
现在配置存储过程 db2e.MYPROC。然后,使用“移动设备管理中心”创建预订。
创建 AgentAdapter 预订
dbname=mysample;procname=db2e.MYPROCdbname 是存储过程使用的数据库。procname 是存储过程的名称。
创建 AgentAdapter 预订后,再创建用户、组和预订集。
创建 DB2 Everyplace 应用程序来使用远程查询和存储过程适配器
此样本使用 DB2 Everyplace Win32 控制台应用程序来测试远程查询和存储过程适配器。样本应用程序称为 myclient.exe。样本应用程序使用下面三个参数:
帐户名称:标识要访问的帐户。 选项:标识要执行的操作。有下面几个选项: 1:检查余额。2:从储蓄帐户向支票帐户转钱。3:从支票帐户向储蓄帐户转钱。 金额:要在支票帐户和储蓄帐户之间转移的金额。
例如,要从 Michael 的储蓄帐户向支票帐户转移 $1000,输入以下命令:
myclient.exe Michael 2 1000
返回以下响应:
Saving = 4000 Checking = 6000
样本应用程序代码
下一节包含样本应用程序的代码。此代码需要一个连接字符串来表示 SQLConnect() 函数以连接至远程数据源。连接字符串的格式为:
http://IPAddr:port/db2e/servlet/com.ibm.mobileservices.adapter.agent.AgentServlet?DB=mysample
其中 IPAddr:port 是服务器的 IP 地址和端口号。例如:
http://192.168.0.11:8080/db2e/servlet/ com.ibm.mobileservices.adapter.agent.AgentServlet?DB=mysample
int main(int argc, char * argv[]) { SQLHENV henv; SQLHDBC hdbc; SQLHSTMT hstmt; SQLRETURN rc; SQLCHAR strSQL[] = "CALL db2e.MYPROC(?,?,?,?,?)"; int nInd4, nInd5; int nSaving = 0, nChecking =0 ; int nCmd =0, nAmount=0; SQLCHAR strConnect[254]; //**************************************************************** //* Check input parameters //**************************************************************** if ( argc < 4 ){ printf("\nUsage : myClient AccountName Cmd Amount"); printf("\n cmd 1 : query balance"); printf("\n cmd 2 : Transfer from Saving to Checking"); printf("\n cmd 3 : Trnasfer from Checking to Saving"); return (99); } nCmd = atoi(argv[2]); nAmount = atoi(argv[3]); //**************************************************************** //* Allocate handles //**************************************************************** rc = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); //checkerror rc = SQLAllocHandle( SQL_HANDLE_DBC, henv, &hdbc); //checkerror if (argc == 5){ strcpy(strConnect,"http://"); strcat(strConnect,argv[4]); strcat(strConnect,"/db2e/servlet/com.ibm.mobileservices.adapter.agent.AgentServlet?DB=mysample"); }else{ strcpy(strConnect,"http://127.0.0.1:8080/db2e/servlet/com.ibm.mobileservices .adapter.agent.AgentServlet?DB=mysample"); } //**************************************************************** //* Connect to remote database //**************************************************************** rc = SQLConnect(hdbc, strConnect, SQL_NTS, "userex", SQL_NTS, "userex", SQL_NTS ); //checkerror rc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt); //checkerror //**************************************************************** //* Prepare, Bind , and Execute the statement //**************************************************************** rc = SQLPrepare(hstmt,strSQL, SQL_NTS); //checkerror rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 0, 0, (SQLPOINTER)argv[1], 0, NULL ); //checkerror rc = SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, (SQLPOINTER)&nCmd, sizeof(int), NULL); //checkerror rc = SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, (SQLPOINTER)&nAmount, sizeof(int), NULL ); //checkerror rc = SQLBindParameter(hstmt, 4, SQL_PARAM_OUTPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, (SQLPOINTER)&nSaving, sizeof(int), &nInd4 ); //checkerror rc = SQLBindParameter(hstmt, 5, SQL_PARAM_OUTPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, (SQLPOINTER)&nChecking, sizeof(int), &nInd5 ); //checkerror rc = SQLExecute(hstmt); //checkerror //**************************************************************** //* Print the balance //**************************************************************** printf("\nSaving = %d",nSaving); printf("\nChecking = %d",nChecking); SQLFreeHandle(SQL_HANDLE_STMT, hstmt); SQLDisconnect(hdbc); SQLFreeHandle(SQL_HANDLE_DBC, hdbc); SQLFreeHandle(SQL_HANDLE_ENV, henv); return 0; }
编译完样本应用程序后,测试远程查询和存储过程适配器应用程序。