Sqlite将数据库合并为一个,具有唯一值,保留外键关系

时间:2014-02-03 05:17:07

标签: sql database sqlite merge

提供了两种解决方案(参见底部的链接),但两者都失败了我正在尝试做的事情:

1。给定数据库中的表(相同)结构,例如:

DB1

水果
--------------
| id | name  |
--------------
| 1  | Apple |
| 2  | Lemon |
| 3  | Kiwi  |
| 4  | Banana|
--------------
果汁
----------------
| id | name    |
----------------
| 1  | Juice A |
| 2  | Juice B |
----------------
食谱(接合表)
----------------------------
| id | juice_id | fruit_id |
----------------------------
| 1  | 1        | 1        |
| 2  | 1        | 2        |
| 3  | 2        | 1        |
| 4  | 2        | 3        |
----------------------------

DB2

水果
---------------
| id | name   |
---------------
| 1  | Kiwi   |
| 2  | Lemon  |
| 3  | Apple  |
| 4  | Orange |
| 5  | Lime   |
---------------
果汁
----------------
| id | name    |
----------------
| 1  | Juice C |
| 2  | Juice D |
----------------
食谱(接合表)
----------------------------
| id | juice_id | fruit_id |
----------------------------
| 1  | 1        | 1        |
| 2  | 1        | 3        |
| 3  | 2        | 2        |
| 4  | 2        | 4        |
----------------------------

2。将它们转换为:

DB3

水果
|----------------|
| id | name      |
|----------------|
| 1  | Kiwi      |
| 2  | Lemon     |
| 3  | Apple     |
| 4  | Orange    |
| 5  | Lime      |
| 6  | Banana    |
------------------
果汁
|--------------|
| id | name    |
|--------------|
| 1  | Juice A |
| 2  | Juice B |
| 3  | Juice C |
| 4  | Juice D |
----------------
食谱(接合表)
----------------------------
| id | juice_id | fruit_id |
----------------------------
| 1  | 1        | 3        |
| 2  | 1        | 2        |
| 3  | 2        | 3        |
| 4  | 2        | 1        |
++++++++++++++++++++++++++++
| 5  | 3        | 1        |
| 6  | 3        | 3        |
| 7  | 4        | 2        |
| 8  | 4        | 4        |
----------------------------

请注意,水果ID会相应改变,尽管水果ID发生变化,但保持关系。 ID是主整数自动递增键,Recipe包含两个外键(加上自己的主整数自动递增键)。

3。只有两个建议的解决方案是:

A)

$sqlite3 database1.db '.dump' >> tmp
$sqlite3 database2.db '.dump' >> tmp
$sqlite3 database3.db '.import tmp'
$ #sometimes sqlite3 database3.db < 'tmp' instead of last row

来自4,以及类似的问题,并且:

b)中

$ sqlite3 newdb
attach 'b.db' as toMerge;   
BEGIN; 
insert into newdb select * from toMerge.sometable; 
COMMIT;

其他答案即。 1234567只是重复相同的模式。也许6可能是解决办法,但我无法说清楚,该查询的长度吓坏了我......

此外,正如1所述,没有gui比较&amp;合并解决方案至少除了2011 sqlitecompare,它可能在Windows中运行(我正在寻找Linux工具) 8中的一些观点也证实,几乎没有任何用户友好的gui有合并选项。

所以,问题是。 如何在Linux中合​​并sqlite DB,保持关系,但不保留标签/注释中的重复值?我认为保持有组织的结构是保存数据库的主要原因,但似乎我不明白,如果从两个篮子里合并,为什么我要把两个相同的水果放在一个篮子里。我的篮子应该包含独特的水果和收成,我想吃那个奇异果:)

1 个答案:

答案 0 :(得分:3)

PRAGMA foreign_keys = on;

ATTACH DATABASE 'db1.sqlite' AS db1;

ATTACH DATABASE 'db2.sqlite' AS db2;

BEGIN;

CREATE TABLE Fruit      (
                          id            INTEGER PRIMARY KEY NOT NULL,
                          name          TEXT    UNIQUE ON CONFLICT IGNORE
                          )
                          ;

CREATE TABLE Juice      (
                          id            INTEGER PRIMARY KEY NOT NULL,
                          name          TEXT    UNIQUE ON CONFLICT IGNORE
                        )
                        ;

CREATE TABLE Recipe     (
                          id            INTEGER PRIMARY KEY NOT NULL,
                          juice_id      INTEGER NOT NULL,
                          fruit_id      INTEGER NOT NULL,
                          FOREIGN KEY   ( juice_id ) REFERENCES Juice ( id )
                                        ON UPDATE CASCADE
                                        ON DELETE CASCADE,
                          FOREIGN KEY   ( fruit_id ) REFERENCES Fruit ( id )
                                        ON UPDATE CASCADE
                                        ON DELETE CASCADE
                        )
                        ;


INSERT INTO Fruit  ( id, name )               SELECT id, name FROM db1.Fruit;
INSERT INTO Juice  ( id, name )               SELECT id, name FROM db1.Juice;
INSERT INTO Recipe ( id, juice_id, fruit_id ) SELECT id, juice_id, fruit_id FROM db1.Recipe;

INSERT INTO Fruit ( name ) SELECT name FROM db2.Fruit;
INSERT INTO Juice ( name ) SELECT name FROM db2.Juice;

CREATE TEMPORARY TABLE Recipe_tmp AS
                                    SELECT Juice.name AS j_name, Fruit.name AS f_name
                                      FROM db2.Recipe, db2.Fruit, db2.Juice
                                        WHERE db2.Recipe.juice_id = db2.Juice.id AND db2.Recipe.fruit_id = db2.Fruit.id
;

INSERT INTO Recipe ( juice_id, fruit_id ) SELECT j.id, f.id
                                            FROM Recipe_tmp AS r, Juice AS j, Fruit AS f
                                              WHERE r.j_name = j.name AND r.f_name = f.name
;


DROP TABLE Recipe_tmp;

COMMIT;

DETACH DATABASE db1;
DETACH DATABASE db2;