从一个大表到其他相关表的大量插入

时间:2011-12-29 12:01:53

标签: postgresql insertion

目前我已将所有数据整理到一个PostgreSQL“Bigtable”表中(大约有1.2M行)。现在我需要将设计拆分为单独的表,这些表都依赖于Bigtable。有些表可能有子表。该模型看起来非常像雪花。

问题

将数据插入表格的最佳选择是什么?我想用'SQL'或PLgSQL编写的函数进行插入。但问题仍然是使用自动生成的ID-s。

此外,如果你知道哪些工具可以让这个问题解决更容易,那么发帖!

// 编辑我添加了示例,这不仅仅是为了说明.的真实案例

3 个答案:

答案 0 :(得分:1)

1.2 M行不是太多。最好的工具是从控制台“psql”执行的sql脚本。如果您有一些较新版本的Pg,那么您可以在必要时使用内联函数(DO语句)。但可能最有用的命令是INSERT INTO SELECT语句。

-- file conversion.sql
DROP TABLE IF EXISTS f1 CASCADE;
CREATE TABLE f1(a int, b int);
INSERT INTO f1
   SELECT x1, y1 
      FROM data
     WHERE x1 = 10;

    ...

-- end file

psql mydb -f conversion.sql

答案 1 :(得分:0)

如果我理解你的问题,你可以使用这样的psql函数:

CREATE OR REPLACE FUNCTION migration() RETURNS integer AS
$BODY$
DECLARE
   currentProductId   INTEGER;
   currentUserId      INTEGER;
   currentReg         RECORD;
BEGIN
   FOR currentReg IN
     SELECT * FROM bigtable
   LOOP
     -- Product
     SELECT productid INTO currentProductId 
     FROM product 
     WHERE name = currentReg.product_name;

     IF currentProductId IS NULL THEN
        EXECUTE 'INSERT INTO product (name) VALUES (''' || currentReg.product_name || ''') RETURNING productid' 
        INTO currentProductId;
     END IF;

     -- User
     SELECT userid INTO currentUserId 
     FROM user
     WHERE first_name = currentReg.first_name and last_name = currentReg.last_name;

     IF currentUserId IS NULL THEN
        EXECUTE 'INSERT INTO user (first_name, last_name) VALUES (''' || currentReg.first_name || ''', ''' || currentReg.last_name || ''') RETURNING userid' 
        INTO currentUserId;

        -- Insert into userAdded too with: currentUserId and currentProductId
        [...]

     END IF;

     -- Rest of tables
     [...]    

    END LOOP;
  RETURN 1;
END;
$BODY$
LANGUAGE plpgsql;

select * from migration();

在这种情况下,假设每个表都运行自己的主键序列,并且我减少了表中字段的数量以简化。 我希望你能提供帮助。

答案 2 :(得分:0)

不需要使用函数(除非我误解了你的问题)

如果您的id列都定义为serial列(即它们自动生成值),则可以使用简单的INSERT语句完成此操作。这假设目标表都是空的。

INSERT INTO users (firstname, lastname)
SELECT DISTINCT firstname, lastname
FROM bigtable;

INSERT INTO category (name)
SELECT DISTINCT category_name 
FROM bigtable;

-- the following assumes a column categoryid in the product table 
-- which is not visible from your screenshot
INSERT INTO product (product_name, description, categoryid)
SELECT DISTINCT b.product_name, b.description, c.categoryid 
FROM bigtable b
  JOIN category c ON c.category_name = b.category_name;

INSERT INTO product_added (product_productid, user_userid)
SELECT p.productid, u.userid
FROM bigtable b
  JOIN product p ON p.product_name = b.product_name
  JOIN users u ON u.firstname = b.firstname AND u.lastname = b.lastname