【问题标题】:Prevent inserting duplicate records防止插入重复记录
【发布时间】:2014-03-12 06:29:57
【问题描述】:

为了学习,我在 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(date) 和 USER (char)。两者是相同的。所以基本上我希望程序告诉我 USER 和 DATE 已经存在于我试图发布相同记录的表中。

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

【问题讨论】:

  • (date, user)上创建唯一索引

标签: sql sqlite delphi unidac


【解决方案1】:

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

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;

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

而且这很难找到失败

【讨论】:

  • 在上述数据字段上设置唯一约束并运行“UNIQuery1.SQL.Text := 'insert or ignore into TEMP2 (Date, User) select Date, User from TEMP1';”还插入重复记录 X2(两次!)。
  • 不理解你....为什么你要在 table1 中搜索重复项,而我应该在 table2 中搜索?
  • 你可以在这里为自己解决这些限制sqlfiddle.com/#!5/447fb/1
  • 我在哪里可以找到 Table1 中的重复项?我检查来自Table1 的当前行是否已经在Table2 中,如果没有,则将其插入Table2
  • 很抱歉听到这个消息——它在 sqlfiddle.com 上对我有用——所以请在 sqlfiddle.com 上发布你不工作的例子
猜你喜欢
  • 2016-08-24
  • 2015-04-14
  • 2018-09-13
  • 2012-08-17
  • 2014-11-12
  • 2015-08-07
  • 2015-08-23
  • 1970-01-01
  • 2015-07-22
相关资源
最近更新 更多