将所有值从一个表中的列移动到新表中,并用这些表之间的关系更新第三个表,PostgreSQL

问题描述

我使用sql已有很长时间了,并且具有以下特点:
我已经有table1个列idname和许多其他列,它已经包含行了。
我创建了一个table2,其中只有列idname
我创建了空的table3,其中只有参考列table1_idtable2_id

现在我要:

  1. name的{​​{1}}列中获取所有值(可以为NULL,在这种情况下将其丢弃),
  2. 将它们作为新行插入table1
  3. 将相应table2id行的table1插入table2
  4. table3删除name
    =>可能是table1,但我想可能会有一种更整洁的方法来剪切步骤1中的结果,对其进行转换并在步骤2中粘贴为行。

编辑:我想出了类似的东西(尚未测试):

ALTER TABLE table1 DROP COLUMN name;

编辑: 我忘了告诉我,如果SELECT table1.id,table1.name INTO results FROM table1; FOR result1 IN results LOOP WITH result2 AS ( INSERT INTO table2 (name) VALUES (result1.name) RETURNING id ) INSERT INTO table3 (table2_id,table1_id) VALUES (result2.id,result1.id); END LOOP; ALTER TABLE table1 DROP COLUMN name; 中已经存在name,我不想再次添加它(在表2中应该是唯一的),但是我添加table2间的关系从id以及从已插入/现有的table1idtable2

编辑: 我发现我们有用于创建数据库的源脚本,并在那里进行了更改。现在我不知道如何摆脱这个开放的问题:(

解决方法

对于步骤1)和2):

--Since you already have a table2
DROP TABLE table2;
--Create new table2 with data. Unless you are going to replace NULL with something 
--discarding them would just end up with NULL again.
CREATE table2 AS SELECT id,name from table1;

步骤3)。不确定table3的用途,因为在table1和table2之间将有匹配的id值。实际上,您可以使用它在它们之间建立FOREIGN KEY关系。

步骤4)您的解决方案:ALTER TABLE table1 DROP COLUMN name;

,

不确定您要如何使用它。如果您希望将其作为一次性转换批量运行,则可能会有所帮助(您可以在sqlfiddle上尝试代码):

CREATE TABLE table1 (
     id int,name varchar(9)
     );
INSERT INTO table1 (
     id,name
     )
     VALUES
        (1,'A'),(2,null),(3,'C'),(4,(5,'E'),(6,'C')
    ;
CREATE TABLE table2 (
     id SERIAL,name varchar(9) UNIQUE
     );
INSERT INTO table2 (name)
    SELECT DISTINCT name
    FROM table1
    WHERE name IS NOT NULL
    ;
/*
-- This would be better option,but I was not able to test the merge/upsert function of PostgreSQL
INSERT INTO table2 (name)
    SELECT name
    FROM table1
    WHERE name IS NOT NULL
    ON CONFLICT table2_name_key DO NOTHING --merge/upsert,supports PostgreSQL 9.5 and newer
    ;
*/
CREATE TABLE table3 (
     id_table1 int,id_table2 int
     ) AS
    SELECT
        t1.id id_table1,t2.id id_table2
    FROM table1 t1
        INNER JOIN table2 t2
            ON t1.name = t2.name
    ;
--ALTER TABLE table1 DROP COLUMN name;

这也可能有用: