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

标签 sql ruby postgresql data-modeling sequel

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

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

为以下项目创建单独的表的好方法是什么 类别子类别品牌 并且原始表中相应的列和行成为外键引用?

概述所涉及的操作:

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

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

问题:你会怎么做?

最佳答案

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

关于sql - 将表列移动到新表并在 PostgreSQL 中作为外键引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29867687/

相关文章:

sql - 提取特定空间实例之间的字符串 - SQL Server

c# - 批量插入未保存到数据库

java - 从多个线程中选择和更新一行的安全方法

ruby - 为什么 `defined?` 关键字不返回 bool 值?

css - 每行四个产品 Bootstrap/ROR 停止使用添加的信息?

MySQL - 如何优化大量条件

ruby-on-rails - 将来自 instagram api 调用的照片保存到 Postgresql?

sql - 如何衡量数据库索引的成本?

php postgresql pg_fetch_all

python - 在 SqlAlchemy 中将子类添加到 session 时发生外键冲突