【问题标题】:Merging multiple databases with relations in SQLite在 SQLite 中将多个数据库与关系合并
【发布时间】:2019-05-17 06:31:05
【问题描述】:

我有几个结构相当简单的 sqlite 文件(数据库),例如:

  | Id | Category |                                | Id | CatId | Name |
  -----------------                                ---------------------
  | 1  |     A    |                                | 1  |   2   |  A   |
  -----------------  -- relations one to many  --> ---------------------
  | 2  |     B    |                                | 2  |   1   |  B   |
                                                   ---------------------
                                                   | 3  |   2   |  BC  |

如您所见,有一张表,其中包含与 name tabe 相关的类别。问题是我有几个 sutrch 文件,我想将它们合并为一个并保持关系。

所以合并第一个表很简单:

ATTACH DATABASE '{databaseFilePath}' AS Db;

BEGIN;
INSERT INTO Category (Category) SELECT Category FROM Db.Category;
COMMIT;

DETACH DATABASE Db;

但这会改变我的 id(它被设置为自动增量,因为在许多 db 文件中可以有相同的 id)。现在我可以对带有名称的第二个表做同样的事情,问题是保持关系,因为主要已经改变了。有什么合理的方法可以做到这一点?

这里是创建表:

CREATE TABLE Category (Id INTEGER PRIMARY KEY NOT NULL UNIQUE,Category STRING);
INSERT INTO Category (Category, Id) VALUES ('B', 2), ('A', 1);

CREATE TABLE Name (Id INTEGER PRIMARY KEY UNIQUE NOT NULL, 
CatId INTEGER 
REFERENCES Category (Id) ON DELETE CASCADE ON UPDATE CASCADE MATCH SIMPLE, Name  STRING);
INSERT INTO Name (Name,CatId,Id)VALUES ('A',1,1),('AB',1,3 ),('B',2,2);

【问题讨论】:

  • 请以create table ...insert ...的几行形式提供minimal reproducible example。或者使用 SQLite 命令行工具中的.dump 来提供定制的玩具数据库。
  • 实际上是两个 TTDB...
  • 无需使主键唯一;已经是了。 Category.Category 不应该是独一无二的吗?如果是这样就很简单了。
  • 另外,你想要TEXT,而不是STRINGsqlite.org/datatype3.html#type_affinity

标签: sql sqlite


【解决方案1】:

我相信您可以基于以下内容(不是附加数据库,而是将 2 附加到第二组表名(为方便起见),另外,第二组表的数据已以 C2 为前缀) :-

DROP TABLE IF EXISTS Name;
DROP TABLE IF EXISTS Name2;
DROP TABLE IF EXISTS Category;
DROP TABLE IF EXISTS Category2;

CREATE TABLE Category (Id INTEGER PRIMARY KEY NOT NULL UNIQUE,Category STRING);
INSERT INTO Category (Category, Id) VALUES ('B', 2), ('A', 1);

CREATE TABLE Name (Id INTEGER PRIMARY KEY UNIQUE NOT NULL, 
CatId INTEGER 
REFERENCES Category (Id) ON DELETE CASCADE ON UPDATE CASCADE MATCH SIMPLE, Name  STRING);
INSERT INTO Name (Name,CatId,Id)VALUES ('A',1,1),('AB',1,3 ),('B',2,2);

CREATE TABLE Category2 (Id INTEGER PRIMARY KEY NOT NULL UNIQUE,Category STRING);
INSERT INTO Category2 (Category, Id) VALUES ('C2B', 2), ('C2A', 1);

CREATE TABLE Name2 (Id INTEGER PRIMARY KEY UNIQUE NOT NULL, 
CatId INTEGER 
REFERENCES Category2 (Id) ON DELETE CASCADE ON UPDATE CASCADE MATCH SIMPLE, Name  STRING);
INSERT INTO Name2 (Name,CatId,Id)VALUES ('C2A',1,1),('C2AB',1,3 ),('C2B',2,2);

UPDATE Category2 SET id = id + (Max((SELECT max(id) FROM Category),(SELECT max(id) FROM Category2)));
UPDATE Name2 SET id = id + (Max((SELECT Max(id) FROM name) ,(SELECT max(id) FROM name2)));

SELECT * FROM Category2;
SELECT * FROM Name2;
INSERT INTO Category SELECT * FROM Category2 WHERE 1;
INSERT INTO name SELECT * FROM name2 WHERE 1;
SELECT * FROM Category;
SELECT * FROM Name;
  • 请注意,您提到了 AUTOINCREMENT 但未包含它,因此未包含检查最高 sqlite_sequence 值。
  • 以上内容依赖于 CASCADE On UPDATE,将 Category.id 的增加级联到 CatId。

这是通过查找具有相同架构的两个表的最高 id,然后通过将找到的最高 id 添加到所有行的 id 来更新要合并的表的 id。当表是类别表时,更新后的 ID 将级联到相应的名称表。

对Category表对和Name表对都执行该过程。

结果(最后一个查询是):-

【讨论】:

    猜你喜欢
    • 2018-06-09
    • 1970-01-01
    • 2010-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多