2

Delphi XE3 と Zeos 7.0.4 を使用して、MySQL 5.6 でマスター/ディテール関係を持つ 2 つのテーブルを保持しようとしています。マスターで ApplyUpdates を実行すると、自動インクリメント フィールドの値は 0 のままです。自動インクリメント値が必要なので、詳細テーブルを ApplyUpdates から取得したマスター テーブルの ID フィールドにリンクできます。AutoCommit = FALSE および TransactionIsolationLevel = tiReadCommitted で ZConnection を使用し、CachedUpdates = TRUE で ZQuery を使用しています。私は何が欠けていますか?

ZQPerson.Append;
ZQEmployee.Append;
try
  ZQPersonName.Value := Edit1.Text;
  ZQPerson.ApplyUpdates; //Here I expected to have the auto increment value on the Id field of ZQPerson, but it returns always 0
  ZQEmployeePersonID.Value := ZQPersonId.Value; //Here I'd link Employee to it's Person record
  ZQEmployeeRegNo.Value := StrToInt(Edit2.Text);
  ZQEmployee.ApplyUpdates;
  ZConnection1.Commit; //Here I would persist both tables in a single transaction to avoid master table without details
except
  ZQPerson.CancelUpdates;
  ZQEmployee.CancelUpdates;
  ZConnection1.Rollback; //In case of exceptions rollback everything
  raise;
end;
ZQPerson.CommitUpdates;
ZQEmployee.CommitUpdates;

私の ZSQLMonitor トレースは次のとおりです。

2013-08-29 00:01:23 cat: Execute, proto: mysql-5, msg: INSERT INTO person (Id, name) VALUES (NULL, 'Edit1') --> This is just after ZQPerson.ApplyUpdates
2013-08-29 00:01:50 cat: Execute, proto: mysql-5, msg: INSERT INTO employee (Id, RegNo, ProductId) VALUES (NULL, 1000, 0), errcode: 1452, error: Cannot add or update a child row: a foreign key constraint fails (`test`.`employee`, CONSTRAINT `FK_A6085E0491BDF8EE` FOREIGN KEY (`PersonId`) REFERENCES `person` (`Id`) --> This is just after ZQEmployee.ApplyUpdates
2013-08-29 00:02:05 cat: Execute, proto: mysql-5, msg: Native Rollback call --> Rollback after Exception on the ZQEmployee.ApplyUpdates
4

3 に答える 3

2

ZConnection1.StartTransaction でトランザクションを開始していますか? ZQuery1.ApplyUpdates を呼び出して新しい ID を取得した後、ZQuery1 を更新する必要があると思います。

あなたのコメントを読んで、select * を where 節なしで実行しているに違いありませんか? 右?このアプローチを使用することをお勧めします。

1) 現在の自動インクリメント値を選択してインクリメントします
2) id=[step1 id] のマスター テーブルから選択します // もちろん空になります
3) ステップ 1 で ID を使用して詳細を追加します
4) マスター データセットに ID を割り当てます
5) 両方の更新を適用する

于 2013-08-29T01:28:59.233 に答える
0

私が見つけた回避策はこれでした。データベースの自動インクリメント機能の使用を透過的にせず、Last_Insert_ID() 関数を使用するため、完全には満足できません。これを確認するために、zeos 開発者と連絡を取り合っています。

function LastInsertID(ATableName: string): Integer;
var DBQuery: TZQuery;
begin
  DBQuery := TZQuery.Create(Self);
  with DBQuery do
  begin
    Connection := ZConnection1;
    SQL.Clear;
    SQL.Add('Select Last_Insert_ID() as Last_Insert_ID from ' + ATableName);
    Open;
    Result := FieldByName('Last_Insert_ID').Value;
    Free;
  end;
end;

procedure Persist;
var LastID: Integer;
begin
  ZQPerson.Append;
  ZQEmployee.Append;
  try
    ZQPersonName.Value := Edit1.Text;
    ZQPerson.ApplyUpdates; // Here I expected to have the auto increment value on the Id field of ZQPerson, but it returns always 0
    LastID := LastInsertID('Person'); //Getting the Last_Insert_ID(), even on the uncommitted transction, works
    ZQEmployeePersonId.Value := LastID; //Link the two tables using the Last_Insert_ID() result
    ZQEmployeeRegNo.Value := StrToInt(Edit2.Text);
    ZQEmployee.ApplyUpdates;
    ZConnection1.Commit; // Here I persist both tables in a single transaction to avoid master table without details
  except
    ZQPerson.CancelUpdates;
    ZQEmployee.CancelUpdates;
    ZConnection1.Rollback; // In case of exceptions rollback everything
    raise;
  end;
  ZQPerson.CommitUpdates;
  ZQEmployee.CommitUpdates;
于 2013-08-29T20:27:52.493 に答える