防止插入重复记录

时间:2014-03-12 06:29:58

标签: sql sqlite delphi unidac

为了学习,我在SQLite中创建了两个相同的表,并试图弄清楚如何防止从一个表到另一个表插入重复项。 我正在使用此查询尝试在发布记录之前查找是否存在重复项。 但是,它无法正常工作,因为仍会插入重复项,并且不会显示警告消息。

procedure TForm1.Button1Click(Sender: TObject);
begin
UNIQuery1.Close;
UNIQuery1.SQL.Clear;
UNIQuery1.SQL.Text:='SELECT * FROM TEMP2 WHERE DATE=:F1 AND user=:F2';
UNIQuery1.Params.ParamByName('F1').Value:=UNITable1.FieldByName('DATE').Value;
UNIQuery1.Params.ParamByName('F2').Value:=UNITable1.FieldByName('USER').Value;
UNIQuery1.Open;
if UNIQuery1.isempty then begin  
UNIQuery1.Close;
UNIQuery1.SQL.Clear;
UNIQuery1.SQL.Text:='INSERT INTO TEMP2 (DATE,USER) select DATE,USER FROM TEMP1';
UNIQuery1.ExecSQL;
UNITable2.Refresh;
end
else
ShowMessage('Record already exists !');
end;

有人可以告诉我如何做到这一点吗?表只有3个字段:ID(Autoinc),DATE(日期)和USER(字符)。两者是相同的。所以基本上我希望程序告诉我USER和DATE已经存在于表中我试图发布相同的记录。

编辑;使用Sir Rufos查询奇怪的事情:

enter image description here

1 个答案:

答案 0 :(得分:3)

SQLite有一个内置函数来防止违反约束。

ON CONFLICT

在字段DateUser上构建唯一约束,您可以使用

插入新值
insert or ignore into TEMP2 ( Date, User )
select Date, User from TEMP1

但是,如果其中一个字段包含NULL值,那么SQLite似乎没有得到唯一性。

要检查目标表是否包含值(包含NULL),您必须

SELECT * 
FROM TEMP2 
WHERE 
  COALESCE( "DATE", '0000-00-00 00:00:00' ) = COALESCE( :DATE, '0000-00-00 00:00:00' ) 
AND 
  COALESCE( "USER", '' ) = COALESCE( :USER, '' )

<强>更新

您的方法不起作用,因为您只检查TEMP1中的当前行,但将所有行插入TEMP2。< / p>

procedure TForm1.Button1Click(Sender: TObject);
begin
  // Prepare the queries

  // check duplicates query
  UNIQuery1.Close;
  UNIQuery1.SQL.Text := 'SELECT * FROM TEMP2 WHERE COALESCE( "DATE", '0000-00-00 00:00:00' ) = COALESCE( :DATE, '0000-00-00 00:00:00' ) AND COALESCE( "USER", '' ) = COALESCE( :USER, '' )';

  // insert data query
  UNIQuery2.Close;
  UNIQuery2.SQL.Text := 'INSERT INTO TEMP2 (DATE,USER) VALUES (:DATE,:USER)';

  // walk through TEMP1
  UNITable1.First;
  while not UNITable1.EOF do
  begin
    // check current row of TEMP1 for duplicates
    UNIQuery1.Params.ParamByName('DATE').Value := UNITable1.FieldByName('DATE').Value;
    UNIQuery1.Params.ParamByName('USER').Value := UNITable1.FieldByName('USER').Value;
    UNIQuery1.Open;
    // if no duplicates found
    if UNIQuery1.IsEmpty then 
    begin
      // insert the data
      UNIQuery2.Params.ParamByName('DATE').Value := UNITable1.FieldByName('DATE').Value;
      UNIQuery2.Params.ParamByName('USER').Value := UNITable1.FieldByName('USER').Value;
      UNIQuery2.ExecSQL;
      // delete current entry from TEMP1
      UNITable1.Delete;
    end
    else
      // next row from TEMP1
      UNITable1.Next;
  end;
  // refresh
  UNITable1.Refresh;
  UNITable2.Refresh;
end;

但为此,您必须在多用户场景中小心。有人可以在检查此软约束和插入数据之间的小时间间隔内插入相同的数据。

这很难找到失败