Delphi一般使用TADOStoredProc来访问存储过程,TADOStoredProc与TADOQuery都是继承自TCustomADODataSet类,实际上使用TADOQuery来访问存储过程会更灵活一点。
现将使用TADOQuery访问存储过程总结一下:
1. 执行存储过程,不返回结果结合 存储过程脚本: DELIMITER $$
DROP PROCEDURE IF EXISTS p_test1; CREATE PROCEDURE p_test1( iSqn: INT, sName: VARCHAR(40)) BEGIN insert into t1(sqn, name) value(iSqn, sName); END$$
DELIMITER ;
执行存储过程代码: function Exec_Proc1: Boolean; begin result := true; query.close; query.sql.clear; query.sql.add('call p_test1(:sqn, :name)'); query.Parameters[0].value := 1; query.Parameters[1].value := 'test'; try query.ExecSql; except result := false; //写日志什么的处理 end; end;
2. 执行存储过程,返回一个结果集,从结果集中获取数据 存储过程脚本: DELIMITER $$
DROP PROCEDURE IF EXISTS p_test2; CREATE PROCEDURE p_test2( iSqn: INT, sName: VARCHAR(40)) BEGIN select * from t1 where sqn = iSqn and name = sName; END$$
DELIMITER ;
调用存储过程代码: function Exec_Proc2: Boolean; begin result := true; query.close; query.sql.clear; query.sql.add('call p_test2(:sqn, :name)'); query.Parameters[0].value := 1; query.Parameters[1].value := 'test'; try query.open; while not query.eof do begin //读数据 query.next; end; except result := false; //写日志什么的处理 end;
3. 执行存储过程,返回一个结果集,结果集在grid中显示 设置datasource1.dataset = query; 设置grid的datasource为datasource1
存储过程脚本: DELIMITER $$
DROP PROCEDURE IF EXISTS p_test2; CREATE PROCEDURE p_test2( iSqn: INT, sName: VARCHAR(40)) BEGIN select * from t1 where sqn = iSqn and name = sName; END$$
DELIMITER ;
调用存储过程代码: function Exec_Proc2: Boolean; begin result := true; query.close; query.sql.clear; query.sql.add('call p_test2(:sqn, :name)'); query.Parameters[0].value := 1; query.Parameters[1].value := 'test'; try query.open; except result := false; //写日志什么的处理 end;
end;
4. 执行存储过程,返回多个结果集 设置datasource1.dataset = query; 设置grid的datasource为datasource1
存储过程脚本: DELIMITER $$
DROP PROCEDURE IF EXISTS p_test2; CREATE PROCEDURE p_test2( iSqn: INT, sName: VARCHAR(40)) BEGIN select * from t1 where sqn = iSqn and name = sName; select 20 as defineSqn, 'test' as defineName; END$$
DELIMITER ;
调用存储过程代码: function Exec_Proc4: Boolean; var rs: _Recordset; recordCount: Integer; sqn: integer; name: string; begin result := true; query.close; query.sql.clear; query.sql.add('call p_test2(:sqn, :name)'); query.Parameters[0].value := 1; query.Parameters[1].value := 'test'; try query.open;
// 获得第二个结果集中的数据 rs := query.NextRecordset(recordCount); if rs <> nil then begin sqn := rs.Fields[0].value; name := rs.Field[1].value; end;
// 获得第二个结果集,第二个结果集用于grid显示 // 设置query2与grid的关联关系(通过datasource) // rs := query.NextRecordset(recordCount); // query2.recordSet := rs; except result := false; //写日志什么的处理 end;
特别的针对下面的情况: 存储过程脚本:
DELIMITER $$
DROP PROCEDURE IF EXISTS p_test5; CREATE PROCEDURE p_test5( iSqn: INT, sName: VARCHAR(40), OUT value: VARCHAR(20)) BEGIN select * from t1 where sqn = iSqn and name = sName; set value = 'test'; END$$
DELIMITER ;
调用存储过程代码: function Exec_proc5: Boolean; var aValue: string; begin query.close; query.sql.clear; query.sql.add('call p_test5(:sqn, :name, @p)'); query.Parameters[0].value := 1; query.Parameters[1].value := 'test'; try query.open; except result := false; //写日志什么的处理 end;
// 通过另外一个TADOQuery类可以通过查询临时变量@p的方式获得返回值 // 这种方式不是很好,并发量比较大的情况下,取@p的值存在问题 // 解决的办法是不使用传出参数,通过传出第二个结果集的形式,取第二个结果集中的数据相对来说比较好一点 query2.close; query2.sql.clear; query2.sql.add('select @p as aValue;'); try query2.open; aValue := query2.FieldByname('aValue').asString; except end; end;
|
|