【问题标题】:Moving table columns to new table and referencing as foreign key in PostgreSQL将表列移动到新表并在 PostgreSQL 中作为外键引用
【发布时间】:2015-07-04 06:00:12
【问题描述】:

假设我们有一个包含字段的数据库表

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

有什么好办法为 categorysubcategorybrand 并且原表中对应的列和行成为外键引用?

概述所涉及的操作:

  • 获取原表每一列中应成为外键的所有唯一值;
  • 为这些人创建表
  • 在原始表(或副本)中创建外键引用列

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

问题:你会怎么做?

【问题讨论】:

  • get all unique values in each column of the original table which should become foreign keys; - create tables for those - 是的,但是在新表中添加一个代理项(可能是序列号),并让原始表的 FK 是一个(新的)整数字段,指代代理项而不是实际值( s)。

标签: sql ruby postgresql data-modeling sequel


【解决方案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
        ;

注意:片段:

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

如果这些列包含 NULL 将导致问题。 使用比较它们会更好

(ins.category,ins.subcategory) 与 (ani.category,ani.subcategory)

【讨论】:

  • 感谢您抽出宝贵时间。
【解决方案2】:

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

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

以下是相关文档:

CREATE TABLE

ALTER TABLE

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

【讨论】:

  • 感谢您的回复,另一个答案更接近我正在寻找的内容,因为需要索引。干杯
猜你喜欢
  • 2022-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-21
相关资源
最近更新 更多