ADOQuery 保存新记录和更新记录
ADOQuery to save new and update record
我创建了一个 TForm 来在 Access 数据库中创建新用户。
我创建了 DBedit1,它使用更改事件更新 Edit1。如果将全新的数据输入到我的 TEdit 文件中,然后在插入查询时按保存,它会毫无问题地保存数据。
procedure TFNewUser.BtnSaveClick(Sender: TObject);
begin
if (Edit1.Text = '') or (Edit2.Text='') or (Edit3.Text='') or (Edit4.Text='') then begin
ShowMessage('Please enter the missing data!')
end else if (Edit3.Text) <> (Edit4.Text) then begin
ShowMessage('Password not match!')
end else begin
adoQuery1.Close();
adoQuery1.SQL.Clear;
adoQuery1.SQL.Add('INSERT INTO taccount (UserN,FName,Pword,ID)VALUES');
adoQuery1.SQL.Add('(:UserN,:FName,:Pword,:ID)');
adoQuery1.Parameters.ParamByName('UserN').Value:= Edit2.Text;
adoQuery1.Parameters.ParamByName('FName').Value:= Edit1.Text;
adoQuery1.Parameters.ParamByName('Pword').Value:= Edit3.Text;
adoQuery1.Parameters.ParamByName('ID').Value:= Edit5.Text;
Adoquery1.ExecSQL;
ShowMessage('New user created successfully');
end;
ADOQuery1.close;
ADOQuery1.SQL.text:='select * from taccount';
ADOQuery1.Open;
end;
当用户点击 BtnNew 时,在 TEdit 字段中输入一条新记录,当按下保存它时保存新记录 - 是否可以在没有用户输入的情况下为记录分配一个自动编号。
但是如果数据从现有记录加载到 Tedit 如何通过按 BtnSave 更新。
Kobik 已经很好地回答了您实际提出的问题。我想
我会 post 这表明你不需要 TEdits,你可以离开
对 DB-aware 控件(如 TDBEdit 和 TDBNavigator)的所有工作。
如果您编译并 运行 编写的项目,当您
单击 DBNavigator 中的 +
按钮,AdoQuery 进入插入模式
并且鼠标光标放置在 UserN DBEdit 中,以便您可以开始填充
在新用户记录中。
有一个 btnSave,这是您应该保存记录的方式。我有
提供这个按钮只是因为你有一个。请注意,如果您单击
DBNavigator 上的保存按钮,您会收到一条消息,说明保存按钮
没有被点击,取消插入操作,新建用户数据
被丢弃。
项目中的大部分代码都是必需的,因为它模仿了您的
使用单独的保存按钮。为了说明这一点,将项目更改如下
将 btnSave 的 Visible
属性 设置为 false
在if ...
之前添加一个Exit
作为CheckSaveButtonClicked
的第一行
& compile/run 再次项目。
您会发现 DBNavigator 上的“保存”按钮现在可以使用并且项目
从 DBNavigator 的行为角度来看,其行为完全
正如用户直觉所期望的那样。
所以实际上,如果您按预期使用 DBNavigator,代码的 none
在项目中是必要的 AT ALL,除了 DBEdit1.SetFocus
放置鼠标
插入操作开始时此控件中的光标,当然还有 AdoQuery1.open
。这就是为什么我说
在评论中说,如果您使用它们,您可以将工作留给 DB-aware 控件
正确。
更新
you suggest me how to restrict user enter duplicates username with "custom >message" i think should need to add in before post
就我个人而言,我认为在将新记录插入数据库之前避免重复并进行其他验证的最佳方法是首先将其添加到单独的本地table(例如 TClientDataSet 或 FireDAC TFDMemTable)。然后,一旦用户输入了足够的信息来检查重复项并执行您想要的任何其他验证,您就可以提醒用户任何问题并让他们纠正它们。一旦新记录为 "clean",您将其从本地 table 复制到主 table.
这样做允许您使用 db-aware 控件让用户输入新记录数据。另外,就我个人而言,对于实际应用程序,我总是要求用户使用特殊的 a "new record wizard" 作为单独的表单,其中包含用于本地输入 table 的 db-aware 控件;通常这是一个多选项卡表单,除非在非常简单的情况下。这比其他一些方法更费力,例如使用为编辑 existing 记录提供的 db-aware 控件,但效果更好,并且允许您捕获某些类型的错误,这些错误将很困难或如果用户将新记录直接输入主 table.
则不可能
代码
type
TForm1 = class(TForm)
DBGrid1: TDBGrid;
DBNavigator1: TDBNavigator;
DataSource1: TDataSource;
ADOConnection1: TADOConnection;
ADOQuery1: TADOQuery;
ADOQuery1ID: TAutoIncField;
ADOQuery1UserN: TStringField;
ADOQuery1FName: TStringField;
ADOQuery1Pwd: TStringField;
DBEdit1: TDBEdit;
DBEdit2: TDBEdit;
DBEdit3: TDBEdit;
btnSave: TButton;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
procedure FormCreate(Sender: TObject);
procedure ADOQuery1BeforeEdit(DataSet: TDataSet);
procedure ADOQuery1BeforeInsert(DataSet: TDataSet);
procedure ADOQuery1BeforePost(DataSet: TDataSet);
procedure btnSaveClick(Sender: TObject);
private
procedure CheckSaveButtonClicked;
function GetSaveEnabled: Boolean;
procedure SetSaveEnabled(const Value: Boolean);
protected
public
SaveClicked : Boolean;
property SaveEnabled : Boolean read GetSaveEnabled write SetSaveEnabled;
end;
[...]
procedure TForm1.FormCreate(Sender: TObject);
begin
SaveEnabled := False;
AdoQuery1.Open;
end;
procedure TForm1.ADOQuery1BeforeEdit(DataSet: TDataSet);
begin
SaveEnabled := True;
end;
procedure TForm1.ADOQuery1BeforeInsert(DataSet: TDataSet);
begin
SaveEnabled := True;
DBEdit1.SetFocus;
end;
procedure TForm1.CheckSaveButtonClicked;
begin
if not SaveClicked then begin
AdoQuery1.Cancel;
ShowMessage('Save button not clicked');
Abort; // In case the user clicked the DBNavigator Save button
end;
end;
procedure TForm1.ADOQuery1BeforePost(DataSet: TDataSet);
begin
CheckSaveButtonClicked;
end;
procedure TForm1.btnSaveClick(Sender: TObject);
begin
SaveClicked := True;
AdoQuery1.Post;
SaveEnabled := False;
end;
function TForm1.GetSaveEnabled: Boolean;
begin
Result := btnSave.Enabled;
end;
procedure TForm1.SetSaveEnabled(const Value: Boolean);
begin
btnSave.Enabled := Value;
SaveClicked := False;
end;
DFM 内容
object Form1: TForm1
Left = 259
Top = 103
AutoScroll = False
Caption = 'MADefaultForm'
ClientHeight = 314
ClientWidth = 444
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
Position = poScreenCenter
Scaled = False
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 48
Top = 201
Width = 30
Height = 13
Caption = 'UserN'
end
object Label2: TLabel
Left = 48
Top = 225
Width = 34
Height = 13
Caption = 'FName'
end
object Label3: TLabel
Left = 48
Top = 249
Width = 21
Height = 13
Caption = 'Pwd'
end
object DBGrid1: TDBGrid
Left = 40
Top = 8
Width = 320
Height = 153
DataSource = DataSource1
TabOrder = 0
TitleFont.Charset = DEFAULT_CHARSET
TitleFont.Color = clWindowText
TitleFont.Height = -11
TitleFont.Name = 'MS Sans Serif'
TitleFont.Style = []
end
object DBNavigator1: TDBNavigator
Left = 48
Top = 168
Width = 240
Height = 25
DataSource = DataSource1
TabOrder = 1
end
object DBEdit1: TDBEdit
Left = 85
Top = 198
Width = 121
Height = 21
DataField = 'UserN'
DataSource = DataSource1
TabOrder = 2
end
object DBEdit2: TDBEdit
Left = 85
Top = 222
Width = 121
Height = 21
DataField = 'FName'
DataSource = DataSource1
TabOrder = 3
end
object DBEdit3: TDBEdit
Left = 85
Top = 246
Width = 121
Height = 21
DataField = 'Pwd'
DataSource = DataSource1
TabOrder = 4
end
object btnSave: TButton
Left = 288
Top = 240
Width = 75
Height = 25
Caption = 'Save'
TabOrder = 5
OnClick = btnSaveClick
end
object DataSource1: TDataSource
DataSet = ADOQuery1
Left = 112
Top = 8
end
object ADOConnection1: TADOConnection
Connected = True
ConnectionString =
'Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security In' +
'fo=False;Initial Catalog=MATest;Data Source=MAT410\ss2014'
LoginPrompt = False
Provider = 'SQLOLEDB.1'
Left = 32
Top = 8
end
object ADOQuery1: TADOQuery
Connection = ADOConnection1
BeforeInsert = ADOQuery1BeforeInsert
BeforeEdit = ADOQuery1BeforeEdit
BeforePost = ADOQuery1BeforePost
Parameters = <>
SQL.Strings = (
'select * from taccount')
Left = 72
Top = 8
object ADOQuery1ID: TAutoIncField
FieldName = 'ID'
ReadOnly = True
end
object ADOQuery1UserN: TStringField
FieldName = 'UserN'
Size = 50
end
object ADOQuery1FName: TStringField
FieldName = 'FName'
Size = 50
end
object ADOQuery1Pwd: TStringField
FieldName = 'Pwd'
Size = 50
end
end
end
我创建了一个 TForm 来在 Access 数据库中创建新用户。
我创建了 DBedit1,它使用更改事件更新 Edit1。如果将全新的数据输入到我的 TEdit 文件中,然后在插入查询时按保存,它会毫无问题地保存数据。
procedure TFNewUser.BtnSaveClick(Sender: TObject);
begin
if (Edit1.Text = '') or (Edit2.Text='') or (Edit3.Text='') or (Edit4.Text='') then begin
ShowMessage('Please enter the missing data!')
end else if (Edit3.Text) <> (Edit4.Text) then begin
ShowMessage('Password not match!')
end else begin
adoQuery1.Close();
adoQuery1.SQL.Clear;
adoQuery1.SQL.Add('INSERT INTO taccount (UserN,FName,Pword,ID)VALUES');
adoQuery1.SQL.Add('(:UserN,:FName,:Pword,:ID)');
adoQuery1.Parameters.ParamByName('UserN').Value:= Edit2.Text;
adoQuery1.Parameters.ParamByName('FName').Value:= Edit1.Text;
adoQuery1.Parameters.ParamByName('Pword').Value:= Edit3.Text;
adoQuery1.Parameters.ParamByName('ID').Value:= Edit5.Text;
Adoquery1.ExecSQL;
ShowMessage('New user created successfully');
end;
ADOQuery1.close;
ADOQuery1.SQL.text:='select * from taccount';
ADOQuery1.Open;
end;
当用户点击 BtnNew 时,在 TEdit 字段中输入一条新记录,当按下保存它时保存新记录 - 是否可以在没有用户输入的情况下为记录分配一个自动编号。
但是如果数据从现有记录加载到 Tedit 如何通过按 BtnSave 更新。
Kobik 已经很好地回答了您实际提出的问题。我想 我会 post 这表明你不需要 TEdits,你可以离开 对 DB-aware 控件(如 TDBEdit 和 TDBNavigator)的所有工作。
如果您编译并 运行 编写的项目,当您
单击 DBNavigator 中的 +
按钮,AdoQuery 进入插入模式
并且鼠标光标放置在 UserN DBEdit 中,以便您可以开始填充
在新用户记录中。
有一个 btnSave,这是您应该保存记录的方式。我有 提供这个按钮只是因为你有一个。请注意,如果您单击 DBNavigator 上的保存按钮,您会收到一条消息,说明保存按钮 没有被点击,取消插入操作,新建用户数据 被丢弃。
项目中的大部分代码都是必需的,因为它模仿了您的 使用单独的保存按钮。为了说明这一点,将项目更改如下
将 btnSave 的
Visible
属性 设置为 false在
if ...
之前添加一个
Exit
作为CheckSaveButtonClicked
的第一行
& compile/run 再次项目。
您会发现 DBNavigator 上的“保存”按钮现在可以使用并且项目 从 DBNavigator 的行为角度来看,其行为完全 正如用户直觉所期望的那样。
所以实际上,如果您按预期使用 DBNavigator,代码的 none
在项目中是必要的 AT ALL,除了 DBEdit1.SetFocus
放置鼠标
插入操作开始时此控件中的光标,当然还有 AdoQuery1.open
。这就是为什么我说
在评论中说,如果您使用它们,您可以将工作留给 DB-aware 控件
正确。
更新
you suggest me how to restrict user enter duplicates username with "custom >message" i think should need to add in before post
就我个人而言,我认为在将新记录插入数据库之前避免重复并进行其他验证的最佳方法是首先将其添加到单独的本地table(例如 TClientDataSet 或 FireDAC TFDMemTable)。然后,一旦用户输入了足够的信息来检查重复项并执行您想要的任何其他验证,您就可以提醒用户任何问题并让他们纠正它们。一旦新记录为 "clean",您将其从本地 table 复制到主 table.
这样做允许您使用 db-aware 控件让用户输入新记录数据。另外,就我个人而言,对于实际应用程序,我总是要求用户使用特殊的 a "new record wizard" 作为单独的表单,其中包含用于本地输入 table 的 db-aware 控件;通常这是一个多选项卡表单,除非在非常简单的情况下。这比其他一些方法更费力,例如使用为编辑 existing 记录提供的 db-aware 控件,但效果更好,并且允许您捕获某些类型的错误,这些错误将很困难或如果用户将新记录直接输入主 table.
则不可能代码
type
TForm1 = class(TForm)
DBGrid1: TDBGrid;
DBNavigator1: TDBNavigator;
DataSource1: TDataSource;
ADOConnection1: TADOConnection;
ADOQuery1: TADOQuery;
ADOQuery1ID: TAutoIncField;
ADOQuery1UserN: TStringField;
ADOQuery1FName: TStringField;
ADOQuery1Pwd: TStringField;
DBEdit1: TDBEdit;
DBEdit2: TDBEdit;
DBEdit3: TDBEdit;
btnSave: TButton;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
procedure FormCreate(Sender: TObject);
procedure ADOQuery1BeforeEdit(DataSet: TDataSet);
procedure ADOQuery1BeforeInsert(DataSet: TDataSet);
procedure ADOQuery1BeforePost(DataSet: TDataSet);
procedure btnSaveClick(Sender: TObject);
private
procedure CheckSaveButtonClicked;
function GetSaveEnabled: Boolean;
procedure SetSaveEnabled(const Value: Boolean);
protected
public
SaveClicked : Boolean;
property SaveEnabled : Boolean read GetSaveEnabled write SetSaveEnabled;
end;
[...]
procedure TForm1.FormCreate(Sender: TObject);
begin
SaveEnabled := False;
AdoQuery1.Open;
end;
procedure TForm1.ADOQuery1BeforeEdit(DataSet: TDataSet);
begin
SaveEnabled := True;
end;
procedure TForm1.ADOQuery1BeforeInsert(DataSet: TDataSet);
begin
SaveEnabled := True;
DBEdit1.SetFocus;
end;
procedure TForm1.CheckSaveButtonClicked;
begin
if not SaveClicked then begin
AdoQuery1.Cancel;
ShowMessage('Save button not clicked');
Abort; // In case the user clicked the DBNavigator Save button
end;
end;
procedure TForm1.ADOQuery1BeforePost(DataSet: TDataSet);
begin
CheckSaveButtonClicked;
end;
procedure TForm1.btnSaveClick(Sender: TObject);
begin
SaveClicked := True;
AdoQuery1.Post;
SaveEnabled := False;
end;
function TForm1.GetSaveEnabled: Boolean;
begin
Result := btnSave.Enabled;
end;
procedure TForm1.SetSaveEnabled(const Value: Boolean);
begin
btnSave.Enabled := Value;
SaveClicked := False;
end;
DFM 内容
object Form1: TForm1
Left = 259
Top = 103
AutoScroll = False
Caption = 'MADefaultForm'
ClientHeight = 314
ClientWidth = 444
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
Position = poScreenCenter
Scaled = False
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 48
Top = 201
Width = 30
Height = 13
Caption = 'UserN'
end
object Label2: TLabel
Left = 48
Top = 225
Width = 34
Height = 13
Caption = 'FName'
end
object Label3: TLabel
Left = 48
Top = 249
Width = 21
Height = 13
Caption = 'Pwd'
end
object DBGrid1: TDBGrid
Left = 40
Top = 8
Width = 320
Height = 153
DataSource = DataSource1
TabOrder = 0
TitleFont.Charset = DEFAULT_CHARSET
TitleFont.Color = clWindowText
TitleFont.Height = -11
TitleFont.Name = 'MS Sans Serif'
TitleFont.Style = []
end
object DBNavigator1: TDBNavigator
Left = 48
Top = 168
Width = 240
Height = 25
DataSource = DataSource1
TabOrder = 1
end
object DBEdit1: TDBEdit
Left = 85
Top = 198
Width = 121
Height = 21
DataField = 'UserN'
DataSource = DataSource1
TabOrder = 2
end
object DBEdit2: TDBEdit
Left = 85
Top = 222
Width = 121
Height = 21
DataField = 'FName'
DataSource = DataSource1
TabOrder = 3
end
object DBEdit3: TDBEdit
Left = 85
Top = 246
Width = 121
Height = 21
DataField = 'Pwd'
DataSource = DataSource1
TabOrder = 4
end
object btnSave: TButton
Left = 288
Top = 240
Width = 75
Height = 25
Caption = 'Save'
TabOrder = 5
OnClick = btnSaveClick
end
object DataSource1: TDataSource
DataSet = ADOQuery1
Left = 112
Top = 8
end
object ADOConnection1: TADOConnection
Connected = True
ConnectionString =
'Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security In' +
'fo=False;Initial Catalog=MATest;Data Source=MAT410\ss2014'
LoginPrompt = False
Provider = 'SQLOLEDB.1'
Left = 32
Top = 8
end
object ADOQuery1: TADOQuery
Connection = ADOConnection1
BeforeInsert = ADOQuery1BeforeInsert
BeforeEdit = ADOQuery1BeforeEdit
BeforePost = ADOQuery1BeforePost
Parameters = <>
SQL.Strings = (
'select * from taccount')
Left = 72
Top = 8
object ADOQuery1ID: TAutoIncField
FieldName = 'ID'
ReadOnly = True
end
object ADOQuery1UserN: TStringField
FieldName = 'UserN'
Size = 50
end
object ADOQuery1FName: TStringField
FieldName = 'FName'
Size = 50
end
object ADOQuery1Pwd: TStringField
FieldName = 'Pwd'
Size = 50
end
end
end