Delphi一般使用TADOStoredProc來訪問存儲過程,TADOStoredProc與TADOQuery都是繼承自TCustomADODataSet類,實(shí)際上使用TADOQuery來訪問存儲過程會更靈活一點(diǎn)。
現(xiàn)將使用TADOQuery訪問存儲過程總結(jié)一下:
1. 執(zhí)行存儲過程,不返回結(jié)果結(jié)合
存儲過程腳本:
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 ;
執(zhí)行存儲過程代碼:
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. 執(zhí)行存儲過程,返回一個結(jié)果集,從結(jié)果集中獲取數(shù)據(jù)
存儲過程腳本:
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 ;
調(diào)用存儲過程代碼:
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
//讀數(shù)據(jù)
query.next;
end;
except
result := false;
//寫日志什么的處理
end;
end;
3. 執(zhí)行存儲過程,返回一個結(jié)果集,結(jié)果集在grid中顯示
設(shè)置datasource1.dataset = query;
設(shè)置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 ;
調(diào)用存儲過程代碼:
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. 執(zhí)行存儲過程,返回多個結(jié)果集
設(shè)置datasource1.dataset = query;
設(shè)置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 ;
調(diào)用存儲過程代碼:
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;
// 獲得第二個結(jié)果集中的數(shù)據(jù)
rs := query.NextRecordset(recordCount);
if rs <> nil then
begin
sqn := rs.Fields[0].value;
name := rs.Field[1].value;
end;
// 獲得第二個結(jié)果集,第二個結(jié)果集用于grid顯示
// 設(shè)置query2與grid的關(guān)聯(lián)關(guān)系(通過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 ;
調(diào)用存儲過程代碼:
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的方式獲得返回值
// 這種方式不是很好,并發(fā)量比較大的情況下,取@p的值存在問題
// 解決的辦法是不使用傳出參數(shù),通過傳出第二個結(jié)果集的形式,取第二個結(jié)果集中的數(shù)據(jù)相對來說比較好一點(diǎn)
query2.close;
query2.sql.clear;
query2.sql.add('select @p as aValue;');
try
query2.open;
aValue := query2.FieldByname('aValue').asString;
except
end;
end;