Moving table columns to new table and referencing as foreign key in PostgreSQL

两盒软妹~` 提交于 2019-12-13 05:37:37

问题


Suppose we have a DB table with fields "id", "category", "subcategory", "brand", "name", "description", etc. What's a good way of creating separate tables for (eg.) "category", "subcategory" and "brand" and the corresponding columns and rows in the original table becoming foreign key references?

To outline the operations envolved: - get all unique values in each column of the original table which should become foreign keys; - create tables for those - create foreign key reference columns in original table (or a copy)

In this case the PostgreSQL db is accessed via Sequel in a Ruby app, so available interfaces are the command line, Sequel, PGAdmin, or (...)

The question: how would you do this?


回答1:


        -- Some test data
CREATE TABLE animals
        ( id SERIAL NOT NULL PRIMARY KEY
        , name varchar
        , category varchar
        , subcategory varchar
        );
INSERT INTO animals(name, category, subcategory) VALUES
 ( 'Chimpanzee' , 'mammals', 'apes' )
,( 'Urang Utang' , 'mammals', 'apes' )
,( 'Homo Sapiens' , 'mammals', 'apes' )
,( 'Mouse' , 'mammals', 'rodents' )
,( 'Rat' , 'mammals', 'rodents' )
        ;

        -- [empty] table to contain the "squeezed out" domain
CREATE TABLE categories
        ( id SERIAL NOT NULL PRIMARY KEY
        , category varchar
        , subcategory varchar
        , UNIQUE (category,subcategory)
        );

        -- The original table needs a "link" to the new table
ALTER TABLE animals
        ADD column category_id INTEGER -- NOT NULL
        REFERENCES categories(id)
        ;
        -- FK constraints are helped a lot by a supportive index.
CREATE INDEX animals_categories_fk ON animals (category_id);

        -- Chained query to:
        -- * populate the domain table
        -- * initialize the FK column in the original table
WITH ins AS (
        INSERT INTO categories(category, subcategory)
        SELECT DISTINCT a.category, a.subcategory
        FROM animals a
        RETURNING *
        )
UPDATE animals ani
SET category_id = ins.id
FROM ins
WHERE ins.category = ani.category
AND ins.subcategory = ani.subcategory
        ;

        -- Now that we have the FK pointing to the new table,
        -- we can drop the redundant columns.
ALTER TABLE animals DROP COLUMN category, DROP COLUMN subcategory;

        -- show it to the world
SELECT a.*
        , c.category, c.subcategory
FROM animals a
JOIN categories c ON c.id = a.category_id
        ;



回答2:


I'm not sure I completely understand your question, if this doesn't seem to answer it, then please leave a comment and possibly improve your question to clarify, but it sounds like you want to do a CREATE TABLE xxx AS. For example:

CREATE TABLE category AS (SELECT DISTINCT(category) AS id FROM parent_table);

Then alter the parent_table to add a foreign key constraint.

ALTER TABLE parent_table ADD CONSTRAINT category_fk FOREIGN KEY (category) REFERENCES category (id);

Repeat this for each table you want to create.

Here is the related documentation:

CREATE TABLE

ALTER TABLE

Note: code and references are for Postgresql 9.4



来源:https://stackoverflow.com/questions/29867687/moving-table-columns-to-new-table-and-referencing-as-foreign-key-in-postgresql

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!