调整来自mysql transaction - roll back on any exception的代码我通过事务进行两次插入,如果插入失败则回滚。我想使用Delphi来检测是否发生了回滚。
我已经使用try - except块来检查执行整个事务时的错误,但可能是Delphi将回滚视为正确的执行。
这是唯一的方法,以后使用SELECT来查看数据是否存在?
这可能很棘手,因为如果同一个人,相同金额和同一天发生了两次交易,插入的实时数据可能会重复。 (每行的唯一性通过自动增量列(subs_paid_id)实现,并且不会出现在插入中)
冒着冗长的风险,我在下面显示了表的DLL和用于插入的delphi代码。
( ToSQL 只是一个将各种传递参数转换为适合SQL字符串格式的类.MyConnection1是一个与远程数据库连接的Devart MyDAC TMyConnection) < / p>
/*DDL Information*/
-------------------
CREATE TABLE subscriptions_paid
(
subscription_year varchar(4) NOT NULL DEFAULT '',
member_id int(11) NOT NULL DEFAULT '0',
individual_subs_due float DEFAULT NULL,
individual_subs_paid float DEFAULT NULL,
payment_date date DEFAULT NULL,
import_date date DEFAULT NULL,
user_comment varchar(100),
subs_paid_id int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (subscription_year,member_id,subs_paid_id),
KEY subs_paid_id (subs_paid_id)
)
ENGINE=InnoDB AUTO_INCREMENT=538 DEFAULT CHARSET=utf8
和Delphi代码,包括生成SQL是
procedure TFrm_EditSubsPaid.btnConfirmTransferToSelectedClick(Sender: TObject);
//make sql to add a new payment for FirstMemberID, FirstSubsDue, FirstSubsYear using
//dtpNewPaymentDate, edtNewPaymentComment, edtNewPayment and
//a new negative 'payment' for SecondMemberID, SecondSubsDue,
//SecondSubsYear, using edtAmountToTransferFrom , dtpTransferFrom and
//edtNewTransferFromComment
var overpaid : single;
begin
if TransferAmountValid then
begin
SQL := ''
+'DELIMITER $$ '
+'CREATE PROCEDURE transfer() '
+'BEGIN '
//next two lines allow for all the transaction to be rolled back if any insert fails
+' DECLARE `_rollback` BOOL DEFAULT 0; '
+' DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET `_rollback` = 1; '
+ 'START TRANSACTION '
+'INSERT INTO subscriptions_paid ' //the positive payment into account
+' ( '
+' subscription_year , '
+' member_id , '
+' individual_subs_due , '
+' individual_subs_paid, '
+' payment_date , '
+' import_date , '
+' user_comment '
+' ) '
+' VALUES '
+' ( '
+' ToSQL.Text(FirstSubsYear) + ', '
+ FirstMemberID + ', '
+ ToSQL.Float(StrToFloat(FirstSubsDue)) +', '
+ ToSQL.Float(StrToFloat(edtAmountToTransferFrom.Text)) +', '
+ ToSQL.Date(DateOf(dtpTransferFrom.date)) + ', '
+ 'NULL' + ', '
+ ToSQL.Text('(Tfr From ' + SecondMemberID +') ' + edtNewTransferFromComment.text) +' '
+ ');'
+'INSERT INTO subscriptions_paid ' //the negative payment out of account
+' ( '
+' subscription_year , '
+' member_id , '
+' individual_subs_due , '
+' individual_subs_paid, '
+' payment_date , '
+' import_date , '
+' user_comment '
+' ) '
+' VALUES '
+' ( '
+ ToSQL.Text(FirstSubsYear) + ', '
+ SecondMemberID + ', '
+ ToSQL.Float(StrToFloat(SecondSubsDue)) +', '
+ ToSQL.Float(StrToFloat('-' + edtAmountToTransferFrom.Text)) +', '
+ ToSQL.Date(DateOf(dtpTransferFrom.date)) + ', '
+ 'NULL' + ', '
+ ToSQL.Text('(Tfr To ' + FirstMemberID +') ' + edtNewTransferFromComment.text) +' '
+ ');'
//next five lines allow for all the transaction to be rolled back if any insert fails
+'IF `_rollback` THEN '
+' ROLLBACK; '
+'ELSE '
+' COMMIT; '
+'END IF; '
+'END$$'
+'DELIMITER ;' ;
try
begin
dMod.MyConnection1.ExecSQL(sql);
dMod.MyConnection1.ExecSQL('CALL transfer;');
// ???? now check if the inserts went OK ???
end;
except
on E : Exception do
begin
showmessage (
'Exception class name = '+E.ClassName+ slinebreak
+ 'Exception message = '+E.Message);
end //on E
end;//try
end; //if
end;