为了学习,我在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查询奇怪的事情:
答案 0 :(得分:3)
SQLite有一个内置函数来防止违反约束。
在字段Date
和User
上构建唯一约束,您可以使用
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;
但为此,您必须在多用户场景中小心。有人可以在检查此软约束和插入数据之间的小时间间隔内插入相同的数据。
这很难找到失败