当前位置: 首页 > 知识库问答 >
问题:

INSERT IGNORE在mysql模式下使用h2抛出主键冲突

燕正德
2023-03-14

我正在将Scopus数据抓取到h2文件数据库中。数据中有超过46,000,000条记录,每条记录都被视为不同的,这意味着重复数百GB的数据(因此是关系数据库)。为了减少所有这些数据的插入时间,我最初创建了一组没有约束的临时表,然后使用SELECT DISTINCT和GROUP BY将数据复制到真实表中以强制执行唯一性。

唯一的例外是“文档”( documents)表格和“参考文档”( referenced documents)表格。由于数据的格式,我可以保证每条记录都代表一个惟一的文档,所以我可以只插入到documents表中,然后只连接引用的documents表中id不在documents表中的行。

这是相关代码:

CREATE TABLE document (docid varchar NOT NULL, title varchar, abstract varchar, docType varchar NULL, ref boolean);

CREATE TABLE refdoc (refid varchar NOT NULL, title varchar);

INSERT INTO document (docid, title, abstract, docType, ref)
VALUES ('2-s2.0-0000098715', 'title', 'abstract', 'ab', 'false');

INSERT INTO refdoc (refid, title)
VALUES ('2-s2.0-0000098715', 'title'),
VALUES ('2-s2.0-33947184743', 'title');

ALTER TABLE document
ADD PRIMARY KEY (docid);

ALTER TABLE document
ADD FOREIGN KEY (docType) REFERENCES doctype(abbrev);

INSERT IGNORE INTO document (docid, title, ref)
SELECT refid, title, 'true' FROM refdoc;

    < li >创建文档表格 < li >创建引用文档表 < li >在文档表中插入记录 < li >在refdoc表中插入两条记录,包括一条重复记录 < li >用主键改变文档表 < li >用外键改变文档表 < li >插入refdoc中与文档不冲突的行

插入忽略查询抛出:org.h2.jdbc.JdbcSQLException:唯一索引或主键冲突:" CONSTRAINT_INDEX_6 ON PUBLIC。文档(DOCID)

我还尝试使用不存在的地方:

INSERT INTO document (docid, title, ref)
SELECT refid, title, 'true'
FROM refdoc
WHERE NOT EXISTS (
SELECT refid FROM refdoc
INNER JOIN document
ON document.docid = refdoc.refid );

但是,尝试连接没有索引的表似乎实际上是不可能的——我尝试连接的任何东西都没有奏效。

作为最后的手段,我可以使用FileHashMap,只转储refdoc表的内容,然后构造一个巨大的PreparedStatement,如下所示:

INSERT INTO document (docid, title, ref)
SELECT ?, ?, 'true'
WHERE NOT EXISTS (
SELECT docid FROM document
WHERE docid = ? );

但我显然不想这么做,因为这需要很长时间。

共有1个答案

冯峻
2023-03-14

终于找到了一个不涉及构造包含 100,000,000 条记录的批处理语句的解决方案。问题是我既需要强制我插入到文档中的 refdoc 尚未在文档表中,也需要我只插入 refdoc 表中的唯一行。在此之前,我的所有解决方案要么未能避免冲突,要么未能强制实施唯一性,要么涉及对没有索引的表的连接。

以下是解决方案SQL:

CREATE TABLE document (docid varchar NOT NULL, title varchar, abstract varchar, docType varchar NULL);

CREATE TABLE refdoc (refid varchar NOT NULL, title varchar);

INSERT INTO document (docid, title, abstract, docType)
VALUES ('2-s2.0-0000098715', 'title', 'abstract', 'ab');

INSERT INTO refdoc (refid, title)
VALUES ('2-s2.0-0000098715', 'title'),
VALUES ('2-s2.0-33947184743', 'title');

INSERT IGNORE INTO document (docid, title)
SELECT refid, MAX(title)
FROM refdoc
WHERE refid NOT IN (
SELECT docid FROM document )
GROUP BY refid;

ALTER TABLE document
ADD PRIMARY KEY (docid);

ALTER TABLE document
ADD FOREIGN KEY (docType) REFERENCES doctype(abbrev);

现在的逻辑是:

    < li >创建文档表格 < li >创建引用文档表 < li >在文档表中插入记录 < li >在refdoc表中插入两条记录,包括一条重复记录 < li >插入refdoc中与文档不冲突且唯一的行 < li >用主键改变文档表 < li >用外键改变文档表

这还有一个额外的好处,即在插入完成之前不会为文档表编制索引。

我仍然不完全清楚为什么我在一个没有主键的表上遇到主键约束冲突,但这听起来像是要提交给h2github的错误报告。

 类似资料:
  • 我在MySQL中创建了以下三个表的基本模式,其中一个表有两个外键(documentreference表): 但是,我在运行时遇到以下错误: 错误1215:无法添加外键约束 SQL语句: 如果不存在,则创建表( int(5)非空自动增量, varchar(50), varchar(50), JSON,--single codableconcept数据类型 JSON,--创建的单个CodeableCo

  • 以前很多次,当我尝试在mySQL表中设置/更新/删除某些内容时,它会给出 错误代码: 1175年。您正在使用安全更新模式,并且您尝试更新不使用使用 KEY 列的 WHERE 的表 要禁用安全模式,请切换首选项中的选项 - 我可以通过在where子句中包含一个涉及主键的真实条件来解决这个问题。 但是,为什么以下方法不起作用? LiftID是一个varchar,是主键。 更新:根据Bill Karwi

  • Java:Oracle JRE1.8.0_45 提供商:BC,BouncyCastle v1.52 我只是像这样做篡改,在byte[]已经包含加密数据和身份验证标记的16个额外字节之后,我覆盖它的第一个字节。 当我在模拟篡改时更改指定的值时,得到的解密文本在第一个字符处发生更改。它以非线性的方式变化。0x65生成“C”,0x67生成“?”诸如此类。普通消息的其余部分保持正确,只有解密输出的第一个字

  • 在前面的章节中,你交互式地使用mysql输入查询并且查看结果。你也可以以批模式运行mysql。为了做到这些,把你想要运行的命令放在一个文件中,然后告诉mysql从文件读取它的输入: shell> mysql < batch-file 如果在Windows下运行mysql,并且文件中有一些可以造成问题的特殊字符,可以这样操作: C:\> mysql -e "source batch-file" 如果

  • 主要内容:在创建表时设置主键约束,在修改表时添加主键约束,删除主键约束主键(PRIMARY KEY)的完整称呼是“主键约束”,是 MySQL 中使用最为频繁的约束。一般情况下,为了便于 DBMS 更快的查找到表中的记录,都会在表中设置一个主键。 主键分为单字段主键和多字段联合主键,本节将分别讲解这两种主键约束的创建、修改和删除。 使用主键应注意以下几点: 每个表只能定义一个主键。 主键值必须唯一标识表中的每一行,且不能为 NULL,即表中不可能存在有相同主键值的两行

  • 问题内容: 所需结果: 在MySQL中具有重音敏感的主键。 我有一个独特的单词表,所以我将单词本身用作主键(顺便说一句,如果有人可以给我一些建议,我不知道它是否是一个好的设计/实践)。 我需要使该字段具有重音(为什么不区分大小写),因为它必须区分法语动词“ demander”的两个不同的变体,例如和。我在数据库中存储重音词没有任何问题。我只是无法插入没有重音时相同的两个重音字符字符串。 错误 :