DBgrid没有显示更改并在尝试更新时显示错误 - 用于更新或刷新的键列信息不足

时间:2017-08-03 10:35:56

标签: delphi ms-access

我有以下代码;

    unit UNewCar;

    interface

    uses
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, 
    System.Classes, Vcl.Graphics,
    Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Data.DB, Vcl.StdCtrls, Vcl.Mask,
    Vcl.DBCtrls, Vcl.Grids, Vcl.DBGrids, Data.Win.ADODB, Datasnap.DBClient,
    Vcl.ExtCtrls;

    type
      TFNewCar = class(TForm)
      ADOConnection1: TADOConnection;
      ADOQueryTC: TADOQuery;
     DataSourceTC: TDataSource;
     ADOQueryCC: TADOQuery;
     DataSourceCC: TDataSource;

     DBLookupComboBox1: TDBLookupComboBox;
     Label1: TLabel;
     Label2: TLabel;
     BtnNew: TButton;
     BtnSave: TButton;
     DBGrid1: TDBGrid;
     ADOQueryTCCusID: TAutoIncField;
     ADOQueryTCName: TWideStringField;
     ADOQueryTCCName: TWideStringField;
     ADOQueryTCAdd: TWideMemoField;
     ADOQueryTCCity: TWideStringField;
     ADOQueryTCPhone: TWideStringField;
     ADOQueryTCEmail: TWideStringField;
     ADOQueryCCName: TWideStringField;
     ADOQueryCCCusID: TIntegerField;
     ADOQueryCCCar: TWideStringField;
     DBEdit1: TDBEdit;
     procedure BtnNewClick(Sender: TObject);
     procedure FormCreate(Sender: TObject);
     procedure btnSaveClick(Sender: TObject);
     procedure ADOQueryCCBeforeEdit(DataSet: TDataSet);
     procedure ADOQueryCCBeforeInsert(DataSet: TDataSet);
     procedure ADOQueryCCBeforePost(DataSet: TDataSet);
   private
    procedure CheckSaveButtonClicked;
    function GetSaveEnabled: Boolean;
    procedure SetSaveEnabled(const Value: Boolean);
  protected
   public
    SaveClicked : Boolean;
    property SaveEnabled : Boolean read GetSaveEnabled write SetSaveEnabled;
    end;

   var
    FNewCar: TFNewCar;

   implementation

   {$R *.dfm}

   procedure TFNewCar.FormCreate(Sender: TObject);
   begin
  SaveEnabled := False;
  ADOQueryCC.Open;
  ADOQueryTC.Open;
  ADOQueryCC.Requery;
end;

procedure TFNewCar.ADOQueryCCBeforeEdit(DataSet: TDataSet);
begin
  SaveEnabled := True;
end;

procedure TFNewCar.ADOQueryCCBeforeInsert(DataSet: TDataSet);
begin
  SaveEnabled := True;
  DBEdit1.SetFocus;
end;

procedure TFNewCar.ADOQueryCCBeforePost(DataSet: TDataSet);
begin
  CheckSaveButtonClicked;
end;

procedure TFNewCar.CheckSaveButtonClicked;
begin
  if not SaveClicked then begin
    AdoQueryCC.Cancel;
    Abort;   //  In case the user clicked the DBNavigator Save button
  end;
end;

procedure TFNewCar.btnSaveClick(Sender: TObject);
begin
  SaveClicked := True;
  if DBEdit1.Text = '' then
    begin
     ShowMessage('Please enter the missing data!');
    end
    else
    begin
    AdoQueryCC.Post;
    SaveEnabled := False;
    ADOQueryCC.close;
    ADOQueryCC.SQL.text:='SELECT tcustomer.Name,  tcustomercar.CusID,  tcustomercar.Car FROM tcustomer, tcustomercar WHERE tcustomer.CusID = tcustomercar.CusID';
    ADOQueryCC.Open;
    end;
end;

function TFNewCar.GetSaveEnabled: Boolean;
begin
  Result := btnSave.Enabled;
end;

procedure TFNewCar.SetSaveEnabled(const Value: Boolean);
begin
  btnSave.Enabled := Value;
  SaveClicked := False;
end;

procedure TFNewCar.BtnNewClick(Sender: TObject);
begin
ADOQueryCC.Insert;
end;

end.

以下AdoqueryCC => SQL

SELECT tcustomer.Name,  tcustomercar.CusID,  tcustomercar.Car FROM tcustomer, tcustomercar WHERE tcustomer.CusID = tcustomercar.CusID

当我的表单FNewCar加载它没有最近的更改,即使我尝试使用Requery并刷新创建一个事件。 FNewCar表单允许用户成功输入新记录(汽车),但尝试更新字段时也会出现以下错误 密钥列信息不足以更新或刷新“

我做错了什么???

ScreenShot

1 个答案:

答案 0 :(得分:2)

我的猜测是:

  

没有最近的更改

是因为数据尚未发布。而且不能从我所看到的。您尝试从两个表中插入和更新元组,但是您只获取了详细信息表的外键。想象一下,您希望更新此结果集(甚至可以通过某些SQL命令工具手动更新):

SELECT
   Customer.Name,
   CustomerCar.CusID,
   CustomerCar.Car
FROM
   Customer, CustomerCar
WHERE
   Customer.CusID = CustomerCar.CusID

您可以更新 CustomerCar 表格:

UPDATE CustomerCar SET Car = 'NewValue' WHERE CusID = <Fetched CustomerCar.CusID>

因为您在 CustomerCar.CusID 列中获取了其唯一的外键,而您无法更新客户表:

UPDATE Customer SET Name = 'NewValue' WHERE <What?>

因为您没有获取任何唯一的主键。我想,同样的情况是发动机。我只是猜测,但我不相信已经为 WHERE 子句获取了任何元数据(这是唯一可以获得客户的唯一主键的地方表)。是的,您可以使用SQL命令工具作弊并使用为其他表提取的密钥,但是客户端引擎并不那么聪明,我必须添加。

您收到此错误:

  

用于更新或刷新的键列信息不足

因为ADO不知道哪个记录应更新(或刷新),因为两个表都缺少唯一标识符(您错过了获取的主要唯一键)。

我对可能解决方案的建议很简单,只需获取两个表的主要唯一键( CusCarID CustomerCar 表的主要唯一键):

SELECT
   Customer.CusID,
   Customer.Name,
   CustomerCar.CusCarID,
   CustomerCar.Car
FROM
   Customer, CustomerCar
WHERE
   Customer.CusID = CustomerCar.CusID