如果您已经从 CSV 加载了两个表,并且您没有使用或不希望使用外键约束,那么您可以简单地运行 UPDATE,例如
UPDATE table_post
SET profile_ID = (SELECT table_profile.profile
FROM table_profile
WHERE table_profile.profileurl = table_post.profileurl)
;
但是,如果您想使用外键约束来强制引用完整性,并且/或者如果您想规范化 profileurl(减少数据的重复),那么另一种方法是到
- 读取配置文件 CSV 文件并插入/加载配置文件,
- 然后读取帖子的 CSV 文件并使用子查询插入/加载帖子,以在 INSERT 期间解析帖子的 profile_ID。
-
除非关闭外键处理,否则插入/加载后的 UPDATE 会因外键约束异常而失败(请参阅 PRAGMA Foreign Keys)
-
使用外键约束不仅可以强制引用完整性,还可以将配置文件中的更新和删除 CASCADE 到帖子。例如。如果您要删除个人资料,则与该个人资料相关的所有帖子都将被删除,而不是外键异常。
- 不使用外键约束删除配置文件可能会孤立帖子(让它们没有相关的配置文件)。
-
第一种方法的关键是使用子查询(SELECT profile_id FROM table_profile WHERE profileurl = 'url2') 设置 table_post profile_id 列。这将增加所花费的时间(因此,如果使用 UNIQUE 约束,则会减少时间,但代价是插入配置文件表需要更长的时间,看到它们是插入配置文件的父母将不那么重要)。
-
关于标准化;在您当前的模型中,您将 profileurl 存储在父级(配置文件)和子级(帖子)中,但似乎不想将其用于关系,因此不需要将 profileurl 存储在 post 表中。可以释放多余的存储空间。此外,您不必维护重复的事件。假设您的个人资料 X 的 url 为 x_is_here 并且由于某种原因需要更改为 x 的 url 不在此处,您将不得不更改与 X 相关的所有帖子(如果未标准化)。但是,如果 url 只存储在配置文件中,那么它只需要更改一次。
另一种方法是利用已经存在的关系,即使用 profileurl。但是,如果你想强制引用完整性,那么 table_profile 和 table_post 需要稍微修改一下,插入/加载就可以了。
示例
这是一个基于您描述的架构但使用外键约束的示例。此外,还有一种利用 profileurl 建立关系的替代方案。
DROP TABLE IF EXISTS table_post;
DROP TABLE IF EXISTS table_post_alt;
DROP TABLE IF EXISTS table_profile;
CREATE TABLE IF NOT EXISTS table_profile (
profile_id INTEGER PRIMARY KEY,
profileurl TEXT UNIQUE,
subCount INTEGER,
userName,
profileDesc TEXT
);
CREATE TABLE IF NOT EXISTS table_post (
post_id INTEGER PRIMARY KEY,
profile_id INTEGER REFERENCES table_profile(profile_id),
post_url TEXT,
postText TEXT,
pubDate TEXT,
commentCount INTEGER,
likeCount INTEGER,
profileurl
);
CREATE TABLE IF NOT EXISTS table_post_alt (
post_id INTEGER PRIMARY KEY,
profile_id INTEGER,
post_url TEXT,
postText TEXT,
pubDate TEXT,
commentCount INTEGER, likeCount INTEGER, profileurl REFERENCES table_profile(profileurl));
INSERT OR IGNORE INTO table_profile VALUES
(null,'url1',10,'user1','blah1')
,(null,'url2',100,'user2','blah2')
,(null,'url3',10,'user3','blah3')
/* etc.... */
,(null,'url2',100,'user2','blah2') /* purposeful duplicate (ignored) */
;
INSERT OR IGNORE INTO table_post VALUES
(null,(SELECT profile_id FROM table_profile WHERE profileurl = 'url2'),'post_url1','post text 1st post','2020-04-01',5,7,'url2')
,(null,(SELECT profile_id FROM table_profile WHERE profileurl = 'url1'),'post_url2','post text 2nd post','2020-04-01',5,7,'url1')
,(null,(SELECT profile_id FROM table_profile WHERE profileurl = 'url1'),'post_url3','post text 3rd post','2020-04-01',5,7,'url1')
,(null,(SELECT profile_id FROM table_profile WHERE profileurl = 'url3'),'post_url4','post text 4th post','2020-04-01',5,7,'url3')
,(null,(SELECT profile_id FROM table_profile WHERE profileurl = 'url2'),'post_url5','post text 5th post','2020-04-01',5,7,'url2')
,(null,(SELECT profile_id FROM table_profile WHERE profileurl = 'url1'),'post_url6','post text 6th post','2020-04-01',5,7,'url1')
/* etc .... */
;
INSERT OR IGNORE INTO table_post_alt VALUES
(null,'does not matter','post_url1','post text 1st post','2020-04-01',5,7,'url2')
,(null,'does not matter','post_url2','post text 2nd post','2020-04-01',5,7,'url1')
,(null,'does not matter','post_url3','post text 3rd post','2020-04-01',5,7,'url1')
,(null,'does not matter','post_url4','post text 4th post','2020-04-01',5,7,'url3')
,(null,'does not matter','post_url5','post text 5th post','2020-04-01',5,7,'url2')
,(null,'does not matter','post_url6','post text 6th post','2020-04-01',5,7,'url1')
;
SELECT * FROM table_profile
JOIN table_post ON table_profile.profileUrl = table_post.profileUrl;
SELECT * FROM table_profile
JOIN table_post_alt ON table_profile.profileUrl = table_post_alt.profileUrl;
运行上述结果(使用您的查询):-
并且(使用仅针对替代表名修改的查询):-
- 注意值
does not matter 已用于表明由于 FK 是 profileurl,profile_Id 不匹配并不重要 (您可以使用与第一个选项相同的方法来获得正确的值但是然后数据没有完全标准化,它不是原始的,因为你有两次出现的profileurl)。