Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Python在SQLite中插入包含相同列的两个表的外键_Python_Sqlite_Sql Update_Foreign Keys_Primary Key - Fatal编程技术网

使用Python在SQLite中插入包含相同列的两个表的外键

使用Python在SQLite中插入包含相同列的两个表的外键,python,sqlite,sql-update,foreign-keys,primary-key,Python,Sqlite,Sql Update,Foreign Keys,Primary Key,我的计算机上有一个SQLite数据库,其中有两个表: 表_post包含关于twitter帖子的信息:喜欢、作者、URL等。。。 表_profile包含关于Twitter配置文件的信息:用户名、描述、关注者等。。。 我使用的是一个python脚本,它创建了两个单独的CSV文件,其中包含table_post和table_profile的行 然后我使用另一个脚本将CSV文件传输到SQLite数据库。在我想用外键链接这两个表之前,一切都正常 My table_post有以下列:post_IDPK、pro

我的计算机上有一个SQLite数据库,其中有两个表:

表_post包含关于twitter帖子的信息:喜欢、作者、URL等。。。 表_profile包含关于Twitter配置文件的信息:用户名、描述、关注者等。。。 我使用的是一个python脚本,它创建了两个单独的CSV文件,其中包含table_post和table_profile的行

然后我使用另一个脚本将CSV文件传输到SQLite数据库。在我想用外键链接这两个表之前,一切都正常

My table_post有以下列:post_IDPK、profile_IDPK、postrl、postText、pubDate、commentCount、likeCount、profileUrl

我的表格配置文件有以下列:profile_IDPK、profileUrl、subCount、userName、profileDesc

两个表都有profileUrl,我想使用profileUrl列将相应的表profile.profile\u ID插入到表\u post.profile\u ID中

我知道我们可以使用此SQLite查询来连接行:

从表_profile中选择* JOIN table_post ON table_profile.profileUrl=table_post.profileUrl 您需要的是UPDATE语句,而不是INSERT语句

将CSV文件传输到SQLite数据库后,必须更新表\u post:

UPDATE table_post
SET profile_ID = (SELECT profile.profile_ID FROM profile WHERE profile.profileUrl = table_post.profileUrl)
如果您的SQLite版本为3.33.0+,则可以使用UPDATE…FROM语法:


如果您已经从CSV加载了两个表,并且如果您不使用或不希望使用外键约束,那么您可以简单地运行更新,例如

UPDATE table_post 
    SET profile_ID = (SELECT table_profile.profile 
    FROM table_profile 
    WHERE table_profile.profileurl = table_post.profileurl)
;
但是,如果您希望使用外键约束来强制引用完整性,和/或如果您希望规范profileurl以减少数据的重复,那么另一种方法是

读取配置文件CSV文件并插入/加载配置文件的, 然后读取帖子的CSV文件,并使用子查询插入/加载帖子,以在插入过程中解析帖子的概要文件ID。 除非关闭外键处理,否则插入/加载后的更新将失败,并出现外键约束异常。请参阅

您可能必须打开外键处理,因为默认情况下它是打开的。 使用外键约束不仅可以强制引用完整性,还可以将概要文件中的更新和删除级联到帖子中。例如,如果您要删除一个配置文件,那么与该配置文件相关的所有帖子都将被删除,而不是外键例外

如果不使用外键约束,删除一个配置文件可能会导致孤立的帖子,使其没有与之相关的配置文件。 第一种方法的关键是使用子查询SELECT profile_id FROM table_profile设置table_post profile_id列,其中profileurl='url2'。如果使用唯一约束,这将增加所需的时间,从而减少所需的时间,但这样做的代价是在配置文件表中插入所需的时间稍长一点,因为它们是父对象,插入配置文件的影响较小

关于正常化;在当前模型中,profileurl存储在父配置文件和子配置文件中,但似乎不想将其用于关系,因此不需要将profileurl存储在post表中。可以释放多余的存储空间。此外,您不必维护重复的事件。假设你有一个url为X_is_的档案X,由于某些原因,需要更改为X的url不在这里,如果没有标准化,你将不得不更改所有与X相关的帖子。但是,如果url仅存储在配置文件中,则只需更改一次

另一种方法是利用已经存在的关系,即use profileurl。但是,如果您想强制引用完整性,那么需要稍微修改table_profile和table_post,然后按原样插入/加载就可以了

范例

这是一个基于您描述的模式但利用外键约束的示例。此外,还提供了一种使用关系档案URL的替代方案

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; 
运行上述操作将导致使用您的查询:-

并使用仅为替代表名修改的查询:-

注意:值无关紧要已用于表明,由于FK是profileurl,因此配置文件Id不匹配无关紧要。您可以使用与第一个选项相同的方法来获取正确的值,但数据未完全正常化,它不在原始文件中,因为您有两次出现profileurl。
非常感谢。这正是我所需要的,它现在可以工作了!感谢您的辛勤工作,事实上,我还没有想过要更改profileUrl,并在post表中留下孤儿,以及数据库中的数据重复问题。我会考虑让我的数据正常化,再次感谢大家!
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;