关于防止数据重复的问题(在线等待)(50分)

  • 主题发起人 主题发起人 heron
  • 开始时间 开始时间
H

heron

Unregistered / Unconfirmed
GUEST, unregistred user!
为了防止产品编码重复,用以下代码:
procedure TData.Table1BeforePost(DataSet: TDataSet);
begin
Table1.Refresh;

condition := 'SELECT * FROM ":' + DataName + ':Table1" Where CP_ID="';
condition := condition + FL_Data.AChanPin.fieldbyname('CP_ID').AsString + '"';

Query1.close;
Query1.SQL.clear;
Query1.sql.add(condition);
Query1.prepare;
try
Query1.open
except
Query1.ExecSQL;
end;

if Query1.RecordCount > 1 then
begin
application.MessageBox(' 输入的编码重复!' + #13 + #13 + '请重新输入数据.' + #13 + #13 ,'警告',MB_OK );
Table1.Delete;
exit;
end;
end;

编译通过,运行时输入数据保存时提示“Stack overflow”,注释掉Table1.Refresh
则不再提示“Stack overflow”,为什么??
注释掉Table1.Refresh后,运行程序仍然不能防止CP_ID字段的数据重复,
谁能帮帮我?



 
还有,如何用自定义信息提示替代系统的“key violation”提示?
 
用另一个query连接同一个表来查找与记录是否相同![:)]
 
当然不能Table1.Refresh;
因为你没有注意到你的Table1.Refresh;写在哪里-----在Table1的BeforePost中间
因为你现在是增加数据状态
在执行Table1.Refresh前;就必须执行完BeforePost
而执行BeforePost你的代码又执行Table1.Refresh;
你这样就产生无限级循环调用,当然产生堆栈溢出错了。所以不能加Table1.Refresh;

至于你的代码不能防止重复数据,是有可能的,和Query1的属性设置有关,
某些情况下Query1.RecordCount的值是永远是-1的,你可能正是这种情况,
这样你的代码Query1.RecordCount > 1就永远只有一种你不想要的结果了。

你把查询select语句改一下,改成
Select Count(*) AS rCount From ……
判断语句改为
Query1.fieldByName('rCount').Value > 1
这样在任何情况下,本代码都能正常执行。
而且你以后的习惯也要改改,如果想要获取记录的数量采用我的方法,
比你的那种Query1.RecordCount效率要高,至于为什么,你多研究下数据库的使用方法和技巧。
 
你按我的方法处理,
系统就不会产生“key violation”错误了
就可以不用注释了。
你的方法在单用户的环境下,是绝对没有问题的。
如果多用户环境上面代码有可能产生“key violation”错,
不过根据你的代码执行方式可能性极小。
 
刚才看漏了一个地方
Query1.fieldByName('rCount').Value > 1
必须写为
Query1.fieldByName('rCount').Value >= 1
 
代码
begin
application.MessageBox(' 输入的编码重复!' + #13 + #13 + '请重新输入数据.' + #13 + #13 ,'警告',MB_OK );
Table1.Delete;
exit;
end;
也有问题,改为
begin
application.MessageBox(' 输入的编码重复!' + #13 + #13 + '请重新输入数据.' + #13 + #13 ,'警告',MB_OK );
Table1.Cancel;
Abort;
end;

 
看看Delphi的例子,DBErr 和 MastApp.

下面是DBErr中处理 key violation 和 RequiredFieldMissing 的代码

procedure TDM.OrdersPostError(DataSet: TDataSet; E: EDatabaseError;
var Action: TDataAction);
var
iDBIError: Integer;
begin
if (E is EDBEngineError) then
begin
iDBIError := (E as EDBEngineError).Errors[0].Errorcode;
case iDBIError of
eRequiredFieldMissing:
{The EmpNo field is defined as being required.}
begin
MessageDlg('Please provide an Employee ID', mtWarning, [mbOK], 0);
Abort;
end;
eKeyViol:
{The primary key is OrderNo}
begin
MessageDlg('Unable to post. Duplicate Order Number', mtWarning,
[mbOK], 0);
Abort;
end;
end;
end;
end;

还有能让数据库自己做的事,就让它自己做,最好不要手工控制。
 
多谢biggo的指教,待我先验证一下
 
to:JobsLee
我只是不想程序运行时出现英文的提示,有什么好方法吗?
 
谢谢各位,问题解决了!:)
真的很感谢“大富翁”,这样菜鸟们就可以少走很多弯路
 
你可以直接修改资源,关于数据库的在DBConsts.Pas中。
其它的你自己找一下,记得生成新的.DCU啊。
 
后退
顶部