假设我们有一个包含字段的数据库表
"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/