SQL Server 2008 R2中不同客户端更新同一记录
我正在网络模式下使用 SQL Server 2008 R2 在 Delphi-2010 中开发应用程序。
我的问题是,在某些情况下,多个客户端打开同一条记录进行更新。
第一个客户端可以更新记录,但其他客户端则不能,因为 SQL SERVER 无法找到有问题的记录,因为它已被修改。应用程序应允许这 2 次更新而不通知客户端。
该表包含许多字段,并且客户端可以更新其中的任何字段,因为不使用 SQL 语句并且使用 UPDATEBATCH()。
// Press UPDATE
procedure TarticleEditForm.saveButtonClick(Sender: TObject);
begin
if (articleCode.Text <> '') AND (counter.Text <> '') AND (articleLabel.Text <> '') AND (tbCombo.Text <> '') AND (griffeCombo.Text <> '') then begin
ADOArticleFind.SQL.Text := 'SELECT * FROM article WHERE ID<>''' + ADOArticle.FieldByName('ID').Value + ''' AND article=''' + articleCode.Text + ''' AND mode=''' + modeCombo.Text + ''' AND counter=''' + counter.Text + '''';
ADOArticleFind.Open;
// UPDATE
if ADOArticleFind.RecordCount = 0 then begin
// SET Date Modification
ADOArticle.FieldByName('dateModification').Value := Now;
ADOArticle.FieldByName('modifiePar').Value := mainForm.user;
ADOArticle.UpdateBatch();
// Update ArticleColor/ArticleTissu tables
ADOArticleColor.SQL.Text := 'UPDATE articleColor SET article=''' + articleCode.Text + ''', mode=''' + modeCombo.Text + ''', counter=''' + counter.Text + ''' WHERE article=''' + tmpArticleCode + ''' AND mode=''' + tmpMode + ''' AND counter=''' + tmpCounter + '''';
ADOArticleColor.ExecSQL;
ADOArticleTissu.SQL.Text := 'UPDATE articleTissu SET article=''' + articleCode.Text + ''', mode=''' + modeCombo.Text + ''', counter=''' + counter.Text + ''' WHERE article=''' + tmpArticleCode + ''' AND mode=''' + tmpMode + ''' AND counter=''' + tmpCounter + '''';
ADOArticleTissu.ExecSQL;
// create event log
mainForm.ADOUser.SQL.Text := 'SELECT * FROM users WHERE online=1 AND editArticleEvent=1 AND username<>''' + mainForm.user + '''';
mainForm.ADOUser.Open;
while not mainForm.ADOUser.Recordset.EOF do begin
mainForm.ADOMainEventLog.Insert;
mainForm.ADOMainEventLog.FieldByName('event').Value := 'Article modifié: ' + designationCombo.Text + ' ' + saisonCombo.Text + ' ' + articleCode.Text + '-' + modeCombo.Text + counter.Text + ' de ' + griffeCombo.Text;
mainForm.ADOMainEventLog.FieldByName('eventFrom').Value := mainForm.user;
mainForm.ADOMainEventLog.FieldByName('eventTo').Value := mainForm.ADOUser.FieldByName('username').Value;
mainForm.ADOMainEventLog.FieldByName('eventType').Value := 'editArticleEvent';
mainForm.ADOMainEventLog.UpdateBatch();
mainForm.ADOUser.Next;
end;
// Finish
Self.Close;
end
else begin
MessageBox(Application.Handle, 'Cet article existe déja.', 'GET© Driver', MB_ICONWARNING);
articleCode.SetFocus;
end;
end
else
MessageBox(Application.Handle, 'Champs obligatoire(s) manquant(s).', 'GET© Driver', MB_ICONWARNING);
end;
I am developing an application in Delphi-2010 using SQL Server 2008 R2 in network Mode.
My problem is that in certain cases, multiple clients open the same record for update.
The first client can update the record but the others can't because SQL SERVER can't find the record in question because it has been modified. The application should allow the 2 updates without informing the client.
The table contains many fields nd' the client can update anyone of it for that am not using SQL statement nd' am using UPDATEBATCH().
// Press UPDATE
procedure TarticleEditForm.saveButtonClick(Sender: TObject);
begin
if (articleCode.Text <> '') AND (counter.Text <> '') AND (articleLabel.Text <> '') AND (tbCombo.Text <> '') AND (griffeCombo.Text <> '') then begin
ADOArticleFind.SQL.Text := 'SELECT * FROM article WHERE ID<>''' + ADOArticle.FieldByName('ID').Value + ''' AND article=''' + articleCode.Text + ''' AND mode=''' + modeCombo.Text + ''' AND counter=''' + counter.Text + '''';
ADOArticleFind.Open;
// UPDATE
if ADOArticleFind.RecordCount = 0 then begin
// SET Date Modification
ADOArticle.FieldByName('dateModification').Value := Now;
ADOArticle.FieldByName('modifiePar').Value := mainForm.user;
ADOArticle.UpdateBatch();
// Update ArticleColor/ArticleTissu tables
ADOArticleColor.SQL.Text := 'UPDATE articleColor SET article=''' + articleCode.Text + ''', mode=''' + modeCombo.Text + ''', counter=''' + counter.Text + ''' WHERE article=''' + tmpArticleCode + ''' AND mode=''' + tmpMode + ''' AND counter=''' + tmpCounter + '''';
ADOArticleColor.ExecSQL;
ADOArticleTissu.SQL.Text := 'UPDATE articleTissu SET article=''' + articleCode.Text + ''', mode=''' + modeCombo.Text + ''', counter=''' + counter.Text + ''' WHERE article=''' + tmpArticleCode + ''' AND mode=''' + tmpMode + ''' AND counter=''' + tmpCounter + '''';
ADOArticleTissu.ExecSQL;
// create event log
mainForm.ADOUser.SQL.Text := 'SELECT * FROM users WHERE online=1 AND editArticleEvent=1 AND username<>''' + mainForm.user + '''';
mainForm.ADOUser.Open;
while not mainForm.ADOUser.Recordset.EOF do begin
mainForm.ADOMainEventLog.Insert;
mainForm.ADOMainEventLog.FieldByName('event').Value := 'Article modifié: ' + designationCombo.Text + ' ' + saisonCombo.Text + ' ' + articleCode.Text + '-' + modeCombo.Text + counter.Text + ' de ' + griffeCombo.Text;
mainForm.ADOMainEventLog.FieldByName('eventFrom').Value := mainForm.user;
mainForm.ADOMainEventLog.FieldByName('eventTo').Value := mainForm.ADOUser.FieldByName('username').Value;
mainForm.ADOMainEventLog.FieldByName('eventType').Value := 'editArticleEvent';
mainForm.ADOMainEventLog.UpdateBatch();
mainForm.ADOUser.Next;
end;
// Finish
Self.Close;
end
else begin
MessageBox(Application.Handle, 'Cet article existe déja.', 'GET© Driver', MB_ICONWARNING);
articleCode.SetFocus;
end;
end
else
MessageBox(Application.Handle, 'Champs obligatoire(s) manquant(s).', 'GET© Driver', MB_ICONWARNING);
end;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我总是更喜欢使用纯 SQL 来在数据库中进行操作,而不是依赖数据集/表中的数据库抽象。
使用这样的代码,您可以根据需要对 SQL 服务器设置任意数量的并发更新。
I always prefer to use pure SQL to make stuff happen in databases, instead of relying on the database-abstraction in the datasets/tables.
Using code like this you can set as many concurrent updates to SQL-server as you'd like.
既然您说您使用 updatebatch,我假设您使用 TADODataSet(或者可能是 TADOTable、TADOQuery)。
ADO 如何构建更新语句由记录集属性
Update Criteria
控制。默认值为adCriteriaUpdCols
,这意味着更新的 where 子句会将所有修改的字段与旧/原始值进行比较。要使 updatebatch 仅使用关键列,您可以执行以下操作。上面的 TADOQuery 代码如下所示。
顺便说一句,
adCriteriaKey
是在 ADOInt.pas 中定义的Since you say that you use
updatebatch
I assume that you use TADODataSet (or perhaps TADOTable, TADOQuery).How ADO builds the update statement is controlled by the recordset property
Update Criteria
. Default value isadCriteriaUpdCols
which means that the update's where clause compares all modified fields against the old/original value. To makeupdatebatch
only use the key columns you can do something like this.The above code for a TADOQuery would look like this.
BTW,
adCriteriaKey
is defined in ADOInt.pas