CSV 文件数据到 PostgreSQL 表中
Posted
技术标签:
【中文标题】CSV 文件数据到 PostgreSQL 表中【英文标题】:CSV file data into a PostgreSQL table 【发布时间】:2016-05-06 14:18:08 【问题描述】:我正在尝试为电影镜头 (http://grouplens.org/datasets/movielens/) 创建一个数据库。我们有电影和收视率。电影有多种类型。我把它们分成一个单独的表,因为它是一个 1:many 关系。用户与电影之间也存在多:多关系。我需要能够以多种方式查询此表。
所以我创建了:
CREATE TABLE genre (
genre_id serial NOT NULL,
genre_name char(20) DEFAULT NULL,
PRIMARY KEY (genre_id)
)
.
INSERT INTO genre VALUES
(1,'Action'),(2,'Adventure'),(3,'Animation'),(4,'Children\s'),(5,'Comedy'),(6,'Crime'),
(7,'Documentary'),(8,'Drama'),(9,'Fantasy'),(10,'Film-Noir'),(11,'Horror'),(12,'Musical'),
(13,'Mystery'),(14,'Romance'),(15,'Sci-Fi'),(16,'Thriller'),(17,'War'),(18,'Western');
.
CREATE TABLE movie (
movie_id int NOT NULL DEFAULT '0',
movie_name char(75) DEFAULT NULL,
movie_year smallint DEFAULT NULL,
PRIMARY KEY (movie_id)
);
.
CREATE TABLE moviegenre (
movie_id int NOT NULL DEFAULT '0',
genre_id tinyint NOT NULL DEFAULT '0',
PRIMARY KEY (movie_id, genre_id)
);
我不知道如何导入包含movie_id、movie_name 和movie_genre 列的movies.csv 例如,第一行是(1;Toy Story (1995);Animation|Children's|Comedy)
如果我手动插入,它应该是这样的:
INSERT INTO moviegenre VALUES (1,3),(1,4),(1,5)
因为3是动画,4是儿童,5是喜剧
如何以这种方式导入所有数据集?
【问题讨论】:
如何使用 COPY 上传数据?或者你编辑文本文件? 我使用 COPY 上传我的数据 【参考方案1】:您应该首先创建一个可以从 CSV 文件中提取数据的表:
CREATE TABLE movies_csv (
movie_id integer,
movie_name varchar,
movie_genre varchar
);
请注意,任何单引号 (Children's
) 都应加倍 (Children''s
)。一旦数据在这个暂存表中,您可以将数据复制到movie
表中,该表应具有以下结构:
CREATE TABLE movie (
movie_id integer, -- A primary key has implicit NOT NULL and should not have default
movie_name varchar NOT NULL, -- Movie should have a name, varchar more flexible
movie_year integer, -- Regular integer is more efficient
PRIMARY KEY (movie_id)
);
同样对其他桌子进行消毒。
现在复制数据,从 CSV 名称中提取简单的名称和年份:
INSERT INTO movie (movie_id, movie_name)
SELECT parts[1], parts[2]::integer
FROM movies_csv, regexp_matches(movie_name, '([[:ascii:]]*)\s\(([\d]*)\)$') p(parts)
regular expression 说:
([[:ascii:]]*)
- 捕获所有字符,直到下面的匹配项
\s
- 读过去一个空格
\(
- 阅读左括号
([\d]*)
- 捕获任何数字
\)
- 读完右括号
$
- 从字符串末尾开始匹配
因此,在输入“Die Hard 17(约翰永生)(2074)”时,它会创建一个带有'Die Hard 17 (John lives forever)', '2074'
的字符串数组。扫描必须从结尾 $
开始,假设所有电影标题都以括号中的出版年份结尾,以便在电影标题中保留括号和数字。
现在您可以处理电影类型了。您必须使用regex_split_to_table()
函数拆分条上的字符串|
,然后加入流派名称上的genre
表:
INSERT INTO moviegenre
SELECT movie_id, genre_id
FROM movies_csv, regexp_split_to_table(movie_genre, '\|') p(genre) -- escape the |
JOIN genre ON genre.genre_name = p.genre;
完成所有操作后,您可以删除movies_csv
表。
【讨论】:
很好的解释!非常感谢!以上是关于CSV 文件数据到 PostgreSQL 表中的主要内容,如果未能解决你的问题,请参考以下文章
将 CSV 导入到 postgreSQL 中的表中,忽略重复项 - 亚马逊 AWS/RDS