1. 퇴장방법
원래는 Exit 메서드가 실행되면 바로 프로세스가 종료될 줄 알았는데, 실제로 테스트해 보기 위해 예제를 만들고 나서 생각이 바뀌었습니다. 이것 좀 봐주세요
예를 들어, flag에는 최종적으로 'C' 값이 할당됩니다.
================================================= ==============================================
var
플래그: 문자열;
시작하다
노력하다
플래그 := 'A';
출구;
플래그 := 'B';
마지막으로
플래그 := 'C';
끝;
플래그 := 'D';
끝;
================================================= ==============================================
분석: try 절이 어떻게 끝나든 상관없이 finally 절은 항상 실행됩니다. (일mg네티즌님 감사합니다)
2. 전체 시스템을 정지시킬 수 있는 작은 문제
데이터베이스 시스템 설계에서는 데이터 무결성을 보장하기 위해 트랜잭션 작업이 자주 사용됩니다. 그러나 부적절한 설계는 상대적으로 큰 영향을 미칠 수 있습니다. 다음 예에서는 데이터 무결성이 보장되더라도 시스템이 완전히 작동하지 않을 수 있음을 보여줍니다.
================================================= ==============================================
AdoConnection1.BeginTrans;
노력하다
...
if application.MessageBox('삭제하시겠습니까?', 'Question', MB_YESNO+MB_ICONQUESTION)<>IDYes then //(1)
시작하다
...
끝;
Application.MessageBox('작업 실패', '경고', MB_OK) //(2)
AdoConnection1.CommitTrans;
제외하고
Application.MessageBox('작업 실패', '경고', MB_OK) //(3)
AdoConnection1.RollbackTrans;
끝;
================================================= ==============================================
분석: 위 코드의 문제는 모두 (1), (2), (3)의 Application.MessageBox에 의해 발생하지만, 문제를 일으키는 것은 Application.MessageBox 자체가 아니라 프로그램을 중단시키고 필요로 합니다. 사용자 개입 후 후속 작업을 계속 수행합니다. 이때 사용자가 컴퓨터를 떠나거나 이러한 대화 상자의 작업을 확인하지 않으면 이 트랜잭션이 완료되지 않았기 때문에 전체 시스템이 대기 상태에 있는 것으로 생각할 수 있습니다. 끝났다.
이 문제를 방지하려면 다음 두 가지 원칙이 있습니다.
(1) 거래가 시작된 후 프로그램은 사용자 개입 없이 자동으로 거래를 종료할 수 있습니다.
(2) 트랜잭션에서 가장 짧은 작업을 수행합니다.
3. 시도...제외...끝 구조
다음은 try 구조를 설명하는 예 또는 트랜잭션 작업을 사용하는 예입니다.
문제의 코드:
================================================= ==============================================
노력하다
...
AdoConnection1.BeginTrans;
...
AdoConnection1.CommitTrans;
제외하고
AdoConnection1.RollbackTrans;
끝;
================================================= ==============================================
분석: try 후 AdoConnection1.BeginTrans 코드에서 예외가 발생하면 AdoConnection1.RollbackTrans로 점프하여 실행하는데 AdoConnection1이 오류로 인해 트랜잭션을 시작하지 않아 AdoConnection1.RollbackTrans 실행 중에 오류가 발생했습니다.
올바른 코드: ================================================ ================================================
AdoConnection1.BeginTrans;
노력하다
...
...
AdoConnection1.CommitTrans;
제외하고
AdoConnection1.RollbackTrans;
끝;
================================================= ==============================================
즉, try의 구조는 비정상적인 동작을 방지하기 위해 사용됩니다. try...exc 사이에 예외가 발생하면, try 명령을 설계할 때 합리성에 주의해야 합니다. 건축의.
4. 자기사무보호를 사취한 경우
데이터베이스 응용 소프트웨어를 만들 때 우리는 종종 다음과 같은 문제에 직면해야 합니다. 원본 데이터를 판단한 다음 그에 따라 수정해야 합니다. 이 문제는 비교적 간단해 보이지만 네트워크에 동일한 시스템을 사용하는 다른 사람이 있다는 점을 고려하면 우발적인 변경 가능성도 고려해야 합니다. 내 동료는 내 메시지를 받은 후 다중 사용자 문제를 고려했지만 여전히 문제가 있는 코드를 작성했습니다.
================================================= ==============================================
var
AdsTemp: TAdoDataSet;
isOk: 부울;
시작하다
AdsTemp := TAdoDataSet.Create(self);
노력하다
AdsTemp.Connection := AdoConnection1;
AdsTemp.CommandText := 'fid=120인 tb1에서 fid, fnumber 선택';
AdsTemp.Open;
isOk := AdsTemp.FieldByName('fnumber').AsInteger>100;
마지막으로
AdsTemp.Free;
끝;
그렇지 않다면알겠습니다
출구;
AdoConnection1.BeginTrans;
노력하다
AdoConnection1.Execute('fid=120인 tb1에서 tb1 세트 ffull=ffull + 1 업데이트';
...
...
AdoConnection1.CommitTrans;
제외하고
AdoConnection1.RollbackTrans;
끝;
끝;
================================================= ==============================================
분석: 문제를 보셨는지 모르겠습니다. AdoConnection1.BeginTrans 이전에 데이터를 판단한 다음 AdoConnection1.Execute를 사용하여 데이터를 공유하면 판단 이후 기간 동안 이전으로 이동합니다. AdoConnection1.BeginTrans, tb1 데이터가 변경되었을 수 있으며 이 트랜잭션 보호는 쓸모가 없습니다.
올바른 방법은 판단과 수정이 동일한 데이터여야 한다는 것입니다. 다음은 두 가지 방법의 예입니다(차이점은 거래가 시작되는 위치가 다릅니다).
코드 1(거래 보호 사용 후 동일한 데이터가 판단 및 수정됨):
================================================= ==============================================
var
AdsTemp: TAdoDataSet;
isOk: 부울;
시작하다
AdoConnection1.BeginTrans;
노력하다
AdsTemp := TAdoDataSet.Create(self);
노력하다
AdsTemp.Connection := AdoConnection1;
AdsTemp.CommandText := 'fid=120인 tb1에서 fid, fnumber, ffull 선택';
AdsTemp.Open;
AdsTemp.FieldByName('fnumber').AsInteger>100이면
시작하다
광고온도.편집;
AdsTemp.FieldByName('ffull').AsInteger := AdsTemp.FieldByName('ffull').AsInteger + 1;
AdsTemp.Post;
끝;
마지막으로
AdsTemp.Free;
끝;
AdoConnection1.CommitTrans;
제외하고
AdoConnection1.RollbackTrans;
끝;
끝;
================================================= ==============================================
코드 2(예외 캡처를 사용하여 판단과 수정이 동일한 데이터가 아닌 경우 AdsTemp.Post 중에 예외가 발생합니다. 이는 ADODataSet 개체의 기능입니다):
================================================= ==============================================
var
AdsTemp: TAdoDataSet;
isOk: 부울;
시작하다
AdsTemp := TAdoDataSet.Create(self);
노력하다
AdsTemp.Connection := AdoConnection1;
AdsTemp.CommandText := 'fid=120인 tb1에서 fid, fnumber, ffull 선택';
AdsTemp.Open;
AdsTemp.FieldByName('fnumber').AsInteger>100이면
시작하다
AdoConnection1.BeginTrans;
노력하다
광고온도.편집;
AdsTemp.FieldByName('ffull').AsInteger := AdsTemp.FieldByName('ffull').AsInteger + 1;
AdsTemp.Post;
AdoConnection1.CommitTrans;
제외하고
AdoConnection1.RollbackTrans;
끝;
끝;
마지막으로
AdsTemp.Free;
끝;
끝;