调整mysql事务中的代码-在任何异常情况下回滚我通过一个事务将两个插入到一个表中,如果其中一个插入失败,该事务将回滚。我想使用delphi来检测是否发生了回滚。
我已经使用try-except块来检查执行整个事务时的错误,但是大概回滚被delphi视为正确的执行。
要做到这一点,唯一的方法是在事后使用select来查看数据是否存在吗?
这可能很棘手,因为如果同一个人、同一金额、同一天发生两个事务,插入的实时数据可能会重复(每一行的唯一性是通过一个自动递增列(subs\u paid\u id)实现的,该列不会出现在insert中)
冒着冗长的风险,我在下面展示了表的dll和执行插入的delphi代码。
(tosql只是一个类,它将传递的各种参数转换为适合sql字符串的格式。myconnection1是一个连接到远程数据库的devart mydac tmy连接)
/*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;
暂无答案!
目前还没有任何答案,快来回答吧!