进入:
目前我已经将所有数据抓取到一个 PostgreSQL 'Bigtable' 表中(大约有 120 万行)。现在我需要将设计拆分为单独的表,这些表都依赖于 Bigtable。一些表可能有子表。该模型看起来很像雪花。
问题:
将数据插入表的最佳选择是什么?我想用“SQL”或 PLgSQL 编写的函数进行插入。但问题仍然在于自动生成的 ID。
另外,如果您知道哪些工具可以使解决此问题更容易,请发布!
//编辑我添加了例子,这不是真实的例子,只是为了说明
进入:
目前我已经将所有数据抓取到一个 PostgreSQL 'Bigtable' 表中(大约有 120 万行)。现在我需要将设计拆分为单独的表,这些表都依赖于 Bigtable。一些表可能有子表。该模型看起来很像雪花。
问题:
将数据插入表的最佳选择是什么?我想用“SQL”或 PLgSQL 编写的函数进行插入。但问题仍然在于自动生成的 ID。
另外,如果您知道哪些工具可以使解决此问题更容易,请发布!
//编辑我添加了例子,这不是真实的例子,只是为了说明
120 万行不算太多。最好的工具是从控制台“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
如果我理解你的问题,你可以使用这样的 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();
在这种情况下,假设每个表都运行自己的主键序列,并且我减少了表中的字段数以简化。我希望你对你有所帮助。
无需为此使用函数(除非我误解了您的问题)
如果您的 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