ProC实例-Linux下的Oracle Pro*C应用程序实例

xiaoxiao2021-02-28  97

最近帮做的一个数据库实验,过程中觉得网上 Pro*C 的资源和实例不多,于是想记录一下。

简单说下 Pro*C 程序简单原理:编写一个后缀名为 .pc 的源代码,内容是正常的 C 代码嵌入 Pro*C 语句,然后预编译成后缀名为 .c 的文件,再编译为 exe 可执行文件。

如Linux下执行命令:

precompiledimensxcn1:pgirard> chmod 700 precompile dimensxcn1:pgirard> chmod 700 compile dimensxcn1:pgirard> ./precompile Pro*C/C++: Release 8.1.7.0.0 - Production on Sat Mar 8 17:48:12 2008 (c) Copyright 2000 Oracle Corporation.  All rights reserved.  System default option values taken from: /disk/disk1/oracle/OraHome1/precomp/adg dimensxcn1:pgirard> ./compile  dimensxcn1:pgirard> ./user_tec

预编译语句:

proc INAME=user_tec.pc CODE=ANSI_C SQLCHECK=semantics mode=oracle userid=user/password char_map=charz

编译语句:

gcc user_tec.c -o user_tec -include /$ORACLE_HOME/precomp/public/sqlca.h -lclntsh -B$ORACLE_HOME/lib/ -B$ORACLE_HOME/lib 所谓嵌入 简单来说就是,在即将进行 SQL 语句时声明 EXEC SQL ,在 SQL 语句结束时声明 EXEC END,并将 select 结果通过 INTO :变量, :变量, :变量   的形式放入 C 语言变量中。从而使查询结果能够在 C 代码中进行显示,或者操作后再次调用嵌入的 SQL 更新数据库。

值得注意的是,通过 C 语言变量接收 SELECT 语句返回的结果有两种形式,一种是刚才说到的 INTO :[已经声明好的C变量],但这种方法有局限性,只有在结果集为一行时有效,若结果集为多行则会报错,这是需要通过一个 cursor (游标)对结果集进行遍历,如 user_tec.pc 中的函数。

话不多说,对于 Pro*C 略有掌握的可以直接看代码,看不懂的可以往下拉看下题目大意。

采购部门管理员界面:

/* user_pds.pc Pro*C Programe for Pruchasing Department Supervisor By Mr.Zhangweijian date:June 6, 2017 */ #include<stdio.h> #include<stdlib.h> void sql_error(); void do_connect(); int print_menu(); void modresp();//给定一个part_id,修改其关联的agent void quant();//给定一个agent号和一个日期,输出这个采购商所关联的,订单日期在这个日期以前的订单数量和订单总价值 int main() { EXEC SQL WHENEVER SQLERROR do sql_error("Error at connect"); do_connect(); while(1) { switch(print_menu()) { case 1: modresp(); break; case 2: quant(); break; case 3: puts("\nAu revoir Sayonara Bye bye,Ni Hao"); exit(0); default: puts("\n====>Enter a digit from the menu please?"); break; } } EXEC SQL COMMIT WORK RELEASE; exit(0); } void sql_error(char *msg) { char ora_msg[512]; int buf_len,msg_len; EXEC SQL WHENEVER SQLERROR continue; printf("\n%s\n",msg); buf_len=sizeof(ora_msg); sqlglm(ora_msg, &buf_len, &msg_len); printf("\n%.*s\n",msg_len, ora_msg); EXEC SQL ROLLBACK RELEASE; exit(1); } void do_connect() { char *uid = "ora00067/AbB7dP"; EXEC SQL CONNECT :uid; printf("Connected to Oracle schema\n"); } int print_menu() { int choice; printf("\t user_pds"); printf("\n\tChoose a transaction by entering a number\n"); printf("\t***********************************\n"); printf("\t(1)MODRESPON\n"); printf("\t(2)QUANT\n"); printf("\t(3)QUIT\n"); printf("Enter your choice?"); scanf("%d", &choice); return choice; } /* **************************************************************************************************** * Function to change the responsibility of a given part(part_id) from a agent to another agent * **************************************************************************************************** */ void modresp() { int id,num, tstcode; for(;;) { printf("Enter the part id to change (0 to quit)?"); scanf("%d", id); if(id==0) { printf("End of this transaction\n"); return; } printf("Part number: %d\n", id); printf("Enter the emp_num to change(0 to quit)?"); scanf("%d", num); if(num==0) { printf("End of this transaction\n"); return; } printf("Part number: %d\n", num); EXEC SQL EXECUTE DECLARE procedure mod_agent(id IN integer, num IN integer, stat OUT integer) is BEGIN stat := 1; update responsible set emp_number=num where part_number=id; if SQL%NOTFOUND then stat:=0; end if; END; BEGIN mod_agent(:id, :num, :tstcode); END; END-EXEC; if(tstcode==0) printf("Record not found\n"); else printf("Modification done\n"); } return; } /* **************************************************************************************************** * Function to Display the number of purchase orders done by a given agent (emp_num) * and the total value of these purchase orders since a given date * **************************************************************************************************** */ void quant() { char des1[16]; char des2[16]; char date[10]; int my_empnum, none=1; char my_podate[16]; for(;;) { printf("Number of the Agent(0 to quit)?"); scanf("%d", &my_empnum); if(my_empnum == 0) { EXEC SQL COMMIT; printf("End of this transaction\n"); break; } printf("Agent Number: %d\n", my_empnum); printf("Date of po_date(yyyyMMdd, 0 to quit)?"); scanf("%s", my_podate); if(strcmp(my_podate,"0")==0) { EXEC SQL COMMIT; printf("End of this transaction\n"); break; } printf("Date: %s\n", my_podate); EXEC SQL EXECUTE BEGIN SELECT count(po_number) INTO :des1 FROM pa_task WHERE emp_num=:my_empnum; EXCEPTION WHEN NO_DATA_FOUND THEN :none:=0; END; END-EXEC; if(none==0) { printf("Record not found\n"); none=1; } else { EXEC SQL EXECUTE BEGIN SELECT sum(purchase_order.total) INTO :des2 FROM pa_task,purchase_order WHERE pa_task.emp_num=:my_empnum and purchase_order.po_number=pa_task.po_number and purchase_order.po_date>:my_podate; EXCEPTION WHEN NO_DATA_FOUND THEN :none:=0; END; END-EXEC; if(none==0) { printf("Record not found\n"); none=1; } else { printf("**********Result**********\n"); printf(" count(po_number)\n"); printf("-----------------\n"); printf("\t%s\n", des1); printf("sum(purchase_order.total)\n"); printf("------------------------\n"); printf("\t%s\n", des2); } } EXEC SQL COMMIT; } return; }

技术人员界面:

/* user_tec.pc Pro*C Programe for Technician By Mr.Zhangweijian date:June 6, 2017 */ #include<stdio.h> #include<stdlib.h> void sql_error(); void do_connect(); int print_menu(); void lispart();//给定一个part_id,显示这个part的具体信息 void explosion();//给定一个part_id,显示这个part相关联的component void implosion();//给定一个componentid,显示这个component相关联的part int main() { EXEC SQL WHENEVER SQLERROR do sql_error("Error at connect"); do_connect(); while(1) { switch(print_menu()) { case 1: lispart(); break; case 2: explosion(); break; case 3: implosion(); break; case 4: puts("\nAu revoir Sayonara Bye bye,Ni Hao"); exit(0); default: puts("\n====>Enter a digit from the menu please?"); break; } } EXEC SQL COMMIT WORK RELEASE; exit(0); } int print_menu() { int choice; printf("\t user_tec"); printf("\n\tChoose a transaction by entering a number\n"); printf("\t***********************************\n"); printf("\t(1)LISPART\n"); printf("\t(2)EXPLOSION\n"); printf("\t(3)IMPLOSION\n"); printf("\t(4)QUIT\n"); printf("Enter your choice?"); scanf("%d", &choice); return choice; } /* ****************************************************************************************** * Function to display the contents of a given part * ****************************************************************************************** */ void lispart() { int des1; char des2[16]; char des3[16]; int des4; int des5; int des6; int des7; int my_partid, none=1; for(;;) { printf("Number of the part(0 to quit)?"); scanf("%d", &my_partid); if(my_partid == 0) { EXEC SQL COMMIT; printf("End of this transaction\n"); break; } printf("Part Number: %d\n", my_partid); EXEC SQL DECLARE c1 CURSOR FOR SELECT part_id,part_name,unit,unit_price,stock_qty,order_qty,min_qty FROM part WHERE part_id = :my_partid; EXEC SQL OPEN c1; EXEC SQL WHENEVER NOT FOUND DO break; while(1) { EXEC SQL FETCH c1 INTO :des1, :des2, :des3, :des4, :des5 ,:des6, des7; printf("**********Result**********\n"); printf(" part_id part_name unit unit_price stock_qty order_qty min_qty\n"); printf("---------- ------------ ------- ------------ ------------ ------------- --------\n"); printf("\t%d\t%s\t%s\t%d\t%d\t%d\t%d\n", des1, des2, des3, des4, des5, des6, des7); } EXEC SQL CLOSE c1; EXEC SQL COMMIT; } return; } /* ****************************************************************************************** * Function to display all components of a given part(part_id) * ****************************************************************************************** */ void explosion() { int des1; char des2[16]; int des3; int my_partid, none=1; for(;;) { printf("Number of the part(0 to quit)?"); scanf("%d", &my_partid); if(my_partid == 0) { EXEC SQL COMMIT; printf("End of this transaction\n"); break; } printf("Part Number: %d\n", my_partid); EXEC SQL DECLARE c1 CURSOR FOR SELECT part_id,part_name,componentid FROM part_tec,comp_tec WHERE comp_tec.partid = :my_partid AND comp_tec.partid=part_tec.part_id; EXEC SQL OPEN c1; EXEC SQL WHENEVER NOT FOUND DO break; while(1) { EXEC SQL FETCH c1 INTO :des1, :des2, :des3; printf("**********Result**********\n"); printf(" part_id part_name componentid\n"); printf("---------- ------------ ---------------\n"); printf("\t%d\t%s\t%d\n", des1, des2, des3); } EXEC SQL CLOSE c1; EXEC SQL COMMIT; } return; } /* ****************************************************************************************** * Function to display all parts where a given part(part_id) is a component * ****************************************************************************************** */ void implosion() { char des1[16]; char des2[16]; char des3[16]; int my_partid, none=1; for(;;) { printf("Number of the part(0 to quit)?"); scanf("%d", &my_partid); if(my_partid == 0) { EXEC SQL COMMIT; printf("End of this transaction\n"); break; } printf("Part Number: %d\n", my_partid); EXEC SQL DECLARE c1 CURSOR FOR SELECT componentid,part_id,part_name FROM part_tec,comp_tec WHERE comp_tec.componentid = :my_partid AND comp_tec.partid=part_tec.part_id; EXEC SQL OPEN c1; EXEC SQL WHENEVER NOT FOUND DO break; while(1) { EXEC SQL FETCH c1 INTO :des1, :des2, :des3; printf("**********Result**********\n"); printf(" componentid part_id part_name\n"); printf("------------ ------------- ---------------\n"); printf("\t%s\t%s\t%s\n", des1, des2, des3); } EXEC SQL CLOSE c1; EXEC SQL COMMIT; } return; }

题目大意:

用 ProC 写 5 个用户程序,这 5 个用户程序分别有不同权限,可以对数据库(Linux下的MySQL)进行不同操作。5个角色有技术人员、采购商、仓库管理员等。

每个ProC程序有一个简单的用户界面如下:

然后可以根据提示进行操作:

在任何输入的时候输入0则为退出。

数据库具体的几个表结构如下:

建表的sql语句,其中视图不用理会:

表之间的部门关系如下:

一个采购商pa_agent通过关联表responsible关联一个part。

多个同类part组成一个product(可以理解为多个同学组成一个班,同学都是属于学生种类)。

一种product由一个供应商supplier供应。

一个订单purchase_order由一个采购商pa_agent发出给一个供应商supplier,订单与采购商通过关联表pa_task关联。

订单的发出人,供应人,购买product数量,总价,状态,保存在detail表中。

写得不是太好,但从我学习历程来看,重点难点应该是 Pro*C 程序 SQL 嵌入以及预编译、编译那部分。

实践能力强的小伙伴不妨建一个简单的表,写一个简单查询的 Pro*C 程序。

转载请注明原文地址: https://www.6miu.com/read-30538.html

最新回复(0)