我有一个包含 1600 列的表,并希望在其中添加更多字段,但根据数据库规则,由于达到上限,不允许创建更多字段。
所以我决定从表中删除一些不需要的字段,我做到了。我再次尝试在该表中添加一些字段,但它引发了相同的错误,即 1600 列无法添加更多。
我浏览了 postgresql">pg_attribute"的其他表,所有这些字段都在那里并且具有删除参数 = True。
到目前为止我尝试过什么
删除约束 将表数据放入另一个表 截断表 重新创建约束 将数据重新复制到主表。
但是删除的列仍然存在于pg_attributes表中。
我也试图从pg_attribute中删除该记录,但后来它 给我这样的错误。
ERROR: catalog is missing 1 attribute(s) for relid 208996 ********** Error ********** ERROR: catalog is missing 1 attribute(s) for relid 208996 SQL state: XX000
为什么我们有这么多列的原因是
我们有odoo-magento(odoo使用的postgresql db)集成和 在Magento有超过60000种产品,并拥有3000种独特的产品 属性,因此在连接器中,所有这些属性都创建为字段 在产品表中,我已经同步了 magento -> odoo 产品和 已达到 1600 限制。现在我不允许从中删除字段 桌子。
我已经在洋红色连接器中修复了这个问题,它只会 同步所需的属性,但我应该为已经同步的属性做什么 字段如何删除它????
即使放下桌子也不是一种正确的方法,因为它很大而且非常 重要的表格,所以我可以承担任何风险。
我想做什么
我想简单地从表中删除这些列,并且需要 改为添加其他几列。
这个问题还有其他可能的解决方案吗?
任何帮助将不胜感激。
永远不要直接惹pg_attribute
。如果您这样做了,可能是时候从备份还原了。
当一个列被删除时,PostgreSQL实际上并没有删除它,而是更改名称并将其标记为已删除。
CREATE TABLE testtab (
id integer PRIMARY KEY,
dropme text NOT NULL,
val text NOT NULL
);
ALTER TABLE testtab DROP dropme;
SELECT attname, attnum, attisdropped
FROM pg_attribute
WHERE attrelid = 'testtab'::regclass
AND attnum > 0
ORDER BY attnum;
┌──────────────────────────────┬────────┬──────────────┐
│ attname │ attnum │ attisdropped │
├──────────────────────────────┼────────┼──────────────┤
│ id │ 1 │ f │
│ ........pg.dropped.2........ │ 2 │ t │
│ val │ 3 │ f │
└──────────────────────────────┴────────┴──────────────┘
(3 rows)
所以我想删除的列仍然计入列限制。
我能想到一种不太舒服的方法来摆脱它:
BEGIN;
CREATE TABLE testtab_2 (LIKE testtab INCLUDING ALL);
INSERT INTO testtab_2 SELECT * FROM testtab;
DROP TABLE testtab;
ALTER TABLE testtab_2 RENAME TO testtab;
COMMIT;
如手册中所述
DROP COLUMN 窗体不会以物理方式删除该列,而只是使其对 SQL 操作不可见。表中的后续插入和更新操作将存储列的 null 值。因此,删除列很快,但它不会立即减小表的磁盘大小,因为不会回收已删除列占用的空间。随着现有行的更新,空间将随着时间的推移而回收。
要强制立即回收已删除列占用的空间,可以执行 ALTER TABLE 的一种形式,该形式执行整个表的重写。这会导致重建每一行,并将删除的列替换为 null 值。