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;