我不是SQL专家,这是我的SQLite查询表“Query”(键:SystemId,TopicId,DocumentId,所有也是外键),它获取外键并插入避免重复。但它是巨大的,丑陋的,我必须执行数千次:
command.CommandText = "INSERT INTO Query (SystemId, TopicId, DocumentId) " +
"(SELECT Id FROM System WHERE Tag = @SystemTag COLLATE NOCASE), " +
"(SELECT Id FROM Topic WHERE Number = @TopicNumber COLLATE NOCASE), " +
"(SELECT Id FROM Document WHERE Number = @DocNumber COLLATE NOCASE) " +
"WHERE NOT EXISTS (SELECT 1 FROM Query WHERE " +
"SystemId = (SELECT Id FROM System WHERE Tag = @SystemTag) AND " +
"TopicId = (SELECT 1 FROM Topic WHERE Number = @TopicNumber) AND " +
"DocumentId = (SELECT Id FROM Document WHERE Number = @DocNumber))";
问题:任何告诉sql的方法“不要担心重复,忽略插入语句”。或者也许使用变量/临时表,AD语句?
编辑:直接查询:
INSERT INTO Query (SystemId, TopicId, DocumentId)
(SELECT Id FROM System WHERE Tag = @SystemTag COLLATE NOCASE),
(SELECT Id FROM Topic WHERE Number = @TopicNumber COLLATE NOCASE),
(SELECT Id FROM Document WHERE Number = @DocNumber COLLATE NOCASE)
WHERE NOT EXISTS (SELECT 1 FROM Query WHERE
SystemId = (SELECT Id FROM System WHERE Tag = @SystemTag) AND
TopicId = (SELECT 1 FROM Topic WHERE Number = @TopicNumber) AND
DocumentId = (SELECT Id FROM Document WHERE Number = @DocNumber));
答案 0 :(得分:1)
要防止插入副本,您需要做两件事:
一个表定义,用于将列标识为需要唯一。例如:
CREATE TABLE Query (
SystemId INTEGER,
TopicId INTEGER,
DocumentId INTEGER,
PRIMARY KEY (SystemId, TopicId, DocumentId));
或
CREATE TABLE Query (
SystemId INTEGER,
TopicId INTEGER,
DocumentId INTEGER,
PRIMARY KEY (SystemId, TopicId, DocumentId));
和conflict clause。您可以通过以下两种方式之一执行此操作:在表定义中保留(如上所述将使其默认为IGNORE,这几乎是您想要的),或者在您的插入命令中:
INSERT OR IGNORE INTO Query...
如果您使用UNIQUE约束进行表设置,则实际上不需要更改INSERT查询(除了删除遗漏的WHERE NOT EXISTS
位。
缺点是,是的,它会使您的代码尝试各种插入并失败。但从另一个角度来看:它使您的数据库按照您希望的方式运行。这是使用数据库的关键,您不希望在进行操作时对所有表进行全手动扫描。你想让数据库做脏工作。
答案 1 :(得分:0)
在关于忽略重复项的问题中,您需要调查DISTINCT
答案 2 :(得分:0)
我不知道你是如何在SQL Lite中执行此操作的(如果存在任何特定于平台的语法问题),但删除重复项的常用方法是使用GROUP BY。
W3Schools在通用SQL方面有一个很好的例子:
http://www.w3schools.com/sql/sql_groupby.asp
另一个选项是DISTINCT,但这可能会在大型数据集中出现问题。
最后,作为观察,你可能想要研究使用JOIN而不是嵌套的SELECT。