CSV文件数据到PostgreSQL表中

时间:2016-05-06 14:18:09

标签: postgresql csv

我正在尝试为movielens(http://grouplens.org/datasets/movielens/)创建一个数据库。我们有电影和收视率。电影有多种类型。我把它们拆分成一个单独的表,因为这是一个很多的关系。有很多:很多关系,用户也喜欢电影。我需要能够以多种方式查询此表。

所以我创建了:

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是喜剧

如何以这种方式导入所有数据?

1 个答案:

答案 0 :(得分: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]*) - 捕获任何数字
  • \) - 阅读右括号
  • $ - 从字符串末尾开始匹配

所以在输入"死硬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表。