Oracle之存储过程和ADO.NET的结合
在利用WCF服务模式实现数据层和数据库交换中,输入参数和输出参数也是要注意的一部分,这次主要是记录在一个输入参数和一个数组形式的输出参数的存储过程如何与ADO.NET实现数据信息交互。
C#实现的底层服务,代码如下:
/// <summary> /// 撤销合并账单 /// </summary> /// <param name="tgtBillId">目标账单</param> /// <returns>撤销之后生成的账单</returns> public string [] RestoreBill( string tgtBillId) { List< string > billIds = new List< string >(); P2Logger.Debug( "SettlementBill" , "RestoreBill begin..." ); using (OracleConnection cnn = ConnectionExpert.GetConnection()) { OracleCommand updCmd = cnn.CreateCommand(); updCmd.CommandType = CommandType.StoredProcedure; updCmd.CommandText = "FMS_SETTLEMENT.p_restroe_bill" ; int [] bindSize = new int [500]; string [] tblData = new string [500]; for ( int ii = 0; ii < 500; ii++) { tblData[ii] = ii.ToString(); //数值 bindSize[ii] = 500; //数值的大小 } updCmd.Parameters.Add( "VA_BILL_ID" , OracleDbType.Varchar2, 2048); updCmd.Parameters[ "VA_BILL_ID" ].Direction = ParameterDirection.Output; updCmd.Parameters[ "VA_BILL_ID" ].CollectionType = OracleCollectionType.PLSQLAssociativeArray; updCmd.Parameters[ "VA_BILL_ID" ].Size = 500; updCmd.Parameters[ "VA_BILL_ID" ].ArrayBindSize = bindSize; updCmd.Parameters.Add( "vv_bill_id" , OracleDbType.Varchar2).Value = tgtBillId; OracleTransaction tran = cnn.BeginTransaction(); try { ConnectionExpert.ExecuteNonQuery(updCmd); tran.Commit(); foreach ( string item in (Oracle.DataAccess.Types.OracleString[])updCmd.Parameters[ "VA_BILL_ID" ].Value) { billIds.Add(item); } P2Logger.Info( "SettlementBill" , "RestoreBill success!" ); return billIds.ToArray(); } catch (Exception ex) { tran.Rollback(); P2Logger.Debug( "SettlementBill" , ex.Message); P2Logger.Debug( "SettlementBill" , ex.StackTrace); FreightException fe = new FreightException(FreightException.E_DATABASE, "合并账单失败。" ); throw new FaultException<FreightException>(fe, fe.Message); } } } |
相关的数据库存储过程如下所示;
----恢复账单 PROCEDURE p_restroe_bill (va_bill_id OUT str_array, vv_bill_id VARCHAR2) AS vr_new_bill fi_acc_bill%ROWTYPE; CURSOR c IS SELECT bill_id FROM fi_acc_bill; --第一行数据 BEGIN ---查询被合并的账单编号 SELECT DISTINCT b.bill_id BULK COLLECT INTO va_bill_id FROM fi_acc_fee_bak b, fi_acc_fee f WHERE b.fee_id = f.fee_id AND f.bill_id = vv_bill_id; ---循环处理被合并账单编号 FOR i IN 1 .. va_bill_id. COUNT LOOP ---从备份账单表移动到账单表 INSERT INTO fi_acc_bill (bill_id, job_id, job_type, confirm_flag, confirm_time, confirm_oper, cust_id, pay_period, bill_type, direction, inv_num, invoice_rise, currency, amount, verify_balance, fx_amount, fiscal_period, blunt_flag, fx_rate, firm, bank_acc, dept_id, book_flag, book_date, remark, create_by, create_date, verify_time, pay_id, security, profit_loses, verify_count, inv_cargo, inv_fee, inv_unit_price, inv_quantity, inv_currency, inv_amount, inv_currency_convert, inv_amout_convert, inv_remark, inv_oper, inv_require, inv_vessel, inv_voyage, inv_mblno, inv_hblno, inv_loading, inv_discharge, inv_etd, prefix) SELECT bill_id, job_id, job_type, confirm_flag, confirm_time, confirm_oper, cust_id, pay_period, bill_type, direction, inv_num, invoice_rise, currency, amount, verify_balance, fx_amount, fiscal_period, blunt_flag, fx_rate, firm, bank_acc, dept_id, book_flag, book_date, remark, create_by, create_date, verify_time, pay_id, security, profit_loses, verify_count, inv_cargo, inv_fee, inv_unit_price, inv_quantity, inv_currency, inv_amount, inv_currency_convert, inv_amout_convert, inv_remark, inv_oper, inv_require, inv_vessel, inv_voyage, inv_mblno, inv_hblno, inv_loading, inv_discharge, inv_etd, prefix FROM fi_acc_bill_bak WHERE bill_id = va_bill_id (i); ----拆分账单费用的账单编号 UPDATE fi_acc_fee f SET f.bill_id = ( SELECT bill_id FROM fi_acc_fee_bak b WHERE f.fee_id = b.fee_id) WHERE f.fee_id IN ( SELECT fee_id FROM fi_acc_fee_bak b WHERE bill_id = va_bill_id (i)); ----拆分费用的账单编号 UPDATE fe_fee f SET f.bill_id = ( SELECT bill_id FROM fi_acc_fee_bak b WHERE f.fee_id = b.fee_id) WHERE f.fee_id IN ( SELECT fee_id FROM fi_acc_fee_bak b WHERE bill_id = va_bill_id (i)); ---删除备份账单费用表(从表) DELETE fi_acc_fee_bak b WHERE bill_id = va_bill_id (i); ---删除备份账单表(主表) DELETE fi_acc_bill_bak WHERE bill_id = va_bill_id (i); END LOOP; ---更新指定账单编号的金额 UPDATE fi_acc_bill SET pay_period = fms_const.pay_period_singlejob, amount = ( SELECT ROUND ( SUM (f.amount), 2) FROM fe_fee f, fi_acc_fee i WHERE i.bill_id = vv_bill_id AND f.fee_id = i.fee_id) WHERE bill_id = vv_bill_id; ---更新指定账单编号的外币金额 UPDATE fi_acc_bill SET pay_period = fms_const.pay_period_singlejob, fx_amount = ( SELECT ROUND ( SUM (f.fx_amout), 2) FROM fe_fee f, fi_acc_fee i WHERE i.bill_id = vv_bill_id AND f.fee_id = i.fee_id) WHERE bill_id = vv_bill_id; ---更新指定账单编号的核销余额 UPDATE fi_acc_bill SET pay_period = fms_const.pay_period_singlejob, verify_balance = ( SELECT ROUND ( SUM (f.verify_balance), 2) FROM fe_fee f, fi_acc_fee i WHERE i.bill_id = vv_bill_id AND f.fee_id = i.fee_id) WHERE bill_id = vv_bill_id; -- DELETE fi_acc_fee_bak -- WHERE bill_id IN -- (SELECT DISTINCT b.bill_id -- FROM fi_acc_fee_bak b, fi_acc_fee f -- WHERE b.fee_id = f.fee_id AND f.bill_id = vv_bill_id); -- --改变账单付款周期状态:月结改为单票 -- UPDATE fi_acc_bill -- SET pay_period = fms_const.pay_period_singlejob -- WHERE bill_id = vv_bill_id; -- -- ---根据账单编号查询被合并的账单编号 -- SELECT bill_id -- INTO v_content -- FROM fi_acc_fee_bak -- WHERE fee_id IN (SELECT fee_id -- FROM fi_acc_fee -- WHERE bill_id = vv_bill_id); -- -- -- -- IF va_bill_id.COUNT > 0 -- THEN -- FOR i IN 1 .. va_bill_id.COUNT -- LOOP -- ---循环把查询出被合并的账单编号添加到FI_ACC_BILL表中,将每条账单的付款周期改为单票 -- SELECT * -- INTO vr_new_bill -- FROM fi_acc_bill_bak -- WHERE bill_id = va_bill_id (i); -- -- ---向备份账单表添加源账单数据 -- INSERT INTO fi_acc_bill (bill_id, -- job_id, -- job_type, -- confirm_flag, -- confirm_time, -- confirm_oper, -- cust_id, -- pay_period, -- bill_type, -- direction, -- inv_num, -- invoice_rise, -- currency, -- amount, -- verify_balance, -- fx_amount, -- fiscal_period, -- blunt_flag, -- fx_rate, -- firm, -- bank_acc, -- dept_id, -- book_flag, -- book_date, -- remark, -- create_by, -- create_date, -- verify_time, -- pay_id, -- security, -- profit_loses, -- verify_count, -- inv_cargo, -- inv_fee, -- inv_unit_price, -- inv_quantity, -- inv_currency, -- inv_amount, -- inv_currency_convert, -- inv_amout_convert, -- inv_remark, -- inv_oper, -- inv_require, -- inv_vessel, -- inv_voyage, -- inv_mblno, -- inv_hblno, -- inv_loading, -- inv_discharge, -- inv_etd, -- prefix) -- SELECT bill_id, -- job_id, -- job_type, -- confirm_flag, -- confirm_time, -- confirm_oper, -- cust_id, -- pay_period, -- bill_type, -- direction, -- inv_num, -- invoice_rise, -- currency, -- amount, -- verify_balance, -- fx_amount, -- fiscal_period, -- blunt_flag, -- fx_rate, -- firm, -- bank_acc, -- dept_id, -- book_flag, -- book_date, -- remark, -- create_by, -- create_date, -- verify_time, -- pay_id, -- security, -- profit_loses, -- verify_count, -- inv_cargo, -- inv_fee, -- inv_unit_price, -- inv_quantity, -- inv_currency, -- inv_amount, -- inv_currency_convert, -- inv_amout_convert, -- inv_remark, -- inv_oper, -- inv_require, -- inv_vessel, -- inv_voyage, -- inv_mblno, -- inv_hblno, -- inv_loading, -- inv_discharge, -- inv_etd, -- prefix -- FROM fi_acc_bill_bak -- WHERE bill_id = va_bill_id (i); -- -- -------并减去每个被合并账单的本位币金额、外币金额、核销余额 -- ---更新账单表 -- UPDATE fi_acc_bill -- SET amount = amount - vr_new_bill.amount, -- verify_balance = -- verify_balance - vr_new_bill.verify_balance, -- fx_amount = fx_amount - vr_new_bill.fx_amount -- WHERE bill_id = vv_bill_id; -- -- --更新FI_ACC_FEE和FE_FEE中对应的BILL_ID -- ---根据从备份费用表FI_ACC_FEE_BAK中查询所得的BILL_ID ,然后查询出Fee_ID -- UPDATE fi_acc_fee -- SET bill_id = va_bill_id (i) -- WHERE fee_id = (SELECT fee_id -- FROM fi_acc_fee_bak -- WHERE bill_id = va_bill_id (i)); -- -- UPDATE fe_fee -- SET bill_id = va_bill_id (i) -- WHERE fee_id = (SELECT fee_id -- FROM fi_acc_fee_bak -- WHERE bill_id = va_bill_id (i)); -- -- --删除备份账单费用FI_ACC_FEE中被合并的数据信息 -- DELETE FROM fi_acc_fee_bak -- WHERE fee_id = (SELECT fee_id -- FROM fi_acc_fee_bak -- WHERE bill_id = va_bill_id (i)); -- -- --删除备份账单表FI_ACC_BILL中被合并的数据信息 -- DELETE FROM fi_acc_bill_bak -- WHERE bill_id = va_bill_id (i); -- END LOOP; -- -- NULL; -- END IF; END ; |
一些相关PL/SQL查询语句,鉴之勉之:)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | /* Formatted on 2012/3/23 11:24:36 (QP5 v5.149.1003.31008) */ SELECT * FROM mat_inventory WHERE (quot_id || loc_id) IN ( SELECT (quot_id || loc_id) FROM ( SELECT quot_id, loc_id, ROWNUM rn FROM ( SELECT quot_id, loc_id FROM mat_inventory ORDER BY quot_id ASC )) WHERE rn = 5); --固定数组 declare type type_array is varray(10) of varchar2(20); var_array type_array:=type_array( 'ggs' , 'jjh' , 'wsb' , 'csl' , 'dd' , 'bb' ); . begin for i in 1..var_array. count loop dbms_output.put_line(var_array(i)); end loop; end ; --可变数组 declare type type_array is table of varchar2(20) index by binary_integer; var_array type_array; begin var_array(1):= 'aa' ; var_array(2):= 'bb' ; for i in 1..var_array. count loop dbms_output.put_line( var_array(i)); end loop; end ; --可变数组取表 declare begin end ; create or replace procedure proc_stock(n number) as var_stock_code varchar2(10); var_stock_price number; begin for i in 1..n loop var_stock_code:= lpad(STR1 =>i ,LEN =>6 ,PAD => '0' ) ; var_stock_price:=trunc(dbms_random.value*100)+1; --dbms_output.put_line(var_stock_code); --dbms_output.put_line(var_stock_price); insert into t_stock (stockcode,stockprice) values (var_stock_code,var_stock_price); commit ; end loop; end ; declare begin proc_stock(1000000); end ; --用游标访问 14.578秒 13.5 13.8 declare cursor cur is select * from t_stock; row_stock t_stock%rowtype; begin open cur; loop fetch cur into row_stock; exit when cur%notfound; null ; end loop; close cur; end ; --用数组实现 4.813 1.953 2 declare type type_array is table of t_stock%rowtype index by binary_integer; var_array type_array; begin select * bulk collect into var_array from t_stock; for i in 1..var_array. count loop null ; end loop; end ; --访问自定义表 declare type type_record is record( username varchar2(20), sex varchar2(2) ); type_record_user type_record; type type_array is table of type_record_user%type index by binary_integer; var_array type_array; begin select username,sex bulk collect into var_array from tuser; for i in 1..var_array. count loop dbms_output.put_line(var_array(i).username); dbms_output.put_line(var_array(i).sex); end loop; end ; |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY