将 table 列移动到新的 table 并在 PostgreSQL 中作为外键引用

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

假设我们有一个 DB table 字段

"id", "category", "subcategory", "brand", "name", "description", etc. 

创建单独的 table 的好方法是什么 categorysubcategorybrand 并且原始 table 中的相应列和行成为外键引用?

概述涉及的操作:

在这种情况下,在 Ruby 应用程序中通过 Sequel 访问 PostgreSQL 数据库,因此可用的界面是命令行、Sequel、PGAdmin 等...

问题:你会怎么做?

我不确定我是否完全理解你的问题,如果这似乎不能回答它,那么请发表评论并可能改进你的问题以澄清,但听起来你想做一个 CREATE TABLE xxx AS。例如:

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

然后修改 parent_table 添加外键约束。

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

对每个要创建的 table 重复此操作。

这里是相关文档:

CREATE TABLE

ALTER TABLE

注意:代码和参考资料适用于 Postgresql 9.4

        -- 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
        ;

注:片段:

WHERE ins.category = ani.category AND ins.subcategory = ani.subcategory

如果这些列包含 NULL,将会导致问题。 最好使用

来比较它们

(ins.category,ins.subcategory) IS NOT DISTINCT FROM (ani.category,ani.subcategory)