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;
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;