简体   繁体   English

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

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

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 category , subcategory and brand and the corresponding columns and rows in the original table becoming foreign key references?categorysubcategorybrand创建单独的表以及原始表中的相应列和行成为外键引用的好方法是什么?

To outline the operations involved:概述所涉及的操作:

  • 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 the 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, etc...在这种情况下,PostgreSQL 数据库是通过 Ruby 应用程序中的 Sequel 访问的,因此可用的接口是命令行、Sequel、PGAdmin 等...

The question: how would you do this?问题:你会怎么做?

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

Note: the fragment:注意:片段:

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

will lead to problems if these columns contain NULLs.如果这些列包含 NULL,则会导致问题。 It would be better to compare them using最好使用它们进行比较

(ins.category,ins.subcategory) IS NOT DISTINCT FROM (ani.category,ani.subcategory) (ins.category,ins.subcategory) 与 (ani.category,ani.subcategory) 没有区别

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 .我不确定我是否完全理解你的问题,如果这似乎没有回答它,那么请发表评论并可能改进你的问题以澄清,但听起来你想做一个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.然后更改parent_table以添加外键约束。

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注意:代码和参考适用于 Postgresql 9.4

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM