在创建列管理工具时,我遇到了在 PostgreSQL 中快速复制表的需求,因此我不会使用非测试表测试新工具。为了有效地测试我最终打算在表格上使用的新列工具,parts
我创建了这个新工具来复制parts
,所以我最终会得到一个parts1
表格。当我以为我终于解决了所有问题时,当列工具删除表时遇到以下错误:
错误:无法删除表部分,因为其他对象依赖于它详细信息:表部分的默认值列 id 取决于序列parts_id_seq1
我花了我一天的大部分时间来研究这个解决方案,所以简而言之,我可以简单地使用字符串函数来重命名SEQUENCE_NAME
变量以将parts
表与parts
表分离,还是比这更复杂的问题?这是查询:
DO $$
DECLARE
SEQUENCE_NAME VARCHAR;
BEGIN
SELECT s.relname INTO SEQUENCE_NAME
FROM pg_class AS s JOIN pg_depend d ON d.objid = s.oid
INNER JOIN pg_class AS t ON d.objid = s.oid AND d.refobjid = t.oid
INNER JOIN pg_attribute AS a ON (d.refobjid, d.refobjsubid) = (a.attrelid, a.attnum)
INNER JOIN pg_namespace AS n ON n.oid = s.relnamespace
WHERE s.relkind = 'S'
AND n.nspname = 'public'
AND t.relname='parts';
LOCK TABLE parts;
CREATE TABLE parts1 (LIKE parts INCLUDING ALL);
INSERT INTO parts1 SELECT * FROM parts;
PERFORM setval(SEQUENCE_NAME::regclass, (SELECT max(id) FROM parts)+1);
END;
$$ LANGUAGE plpgsql;
要创建尽可能接近的副本,请使用
INCLUDING ALL
with,CREATE TABLE .. (LIKE ..)
因为可以有任意数量的列具有您显然想要复制的默认值。您只希望
serial
列拥有自己的独立序列,这很有意义,并且可能应该是开始时的默认行为。Postgres 10通过添加符合 SQL 标准的列来“修复”该问题,
IDENTITY
这些列具有内部专用的序列,并且在CREATE TABLE .. (LIKE ..)
. 手册:大胆强调我的。现有的序列列保持不变。考虑更换
serial
列。看:复制带(或不带)
serial
列的表的功能serial
虽然仍然涉及任何列,但这个函数应该可以完成这项工作:使用新的给定名称和独立
serial
列(如果有)复制任何给定的表(必须存在)。数据不包括在内,复制它也很简单。
称呼:
或者:
生成并执行以下形式的 SQL 代码:
源(第一个参数)必须是表、视图、物化视图、复合类型或外部表。可选的模式限定。
第二个参数是新表名。
第三个参数是新表的模式。如果未给出,则默认为源的架构。
系统列
pg_attrdef.adsrc
已在 Postgres 12 中删除。按照手册中的说明pg_get_expr(ad.adbin, ad.adrelid)
使用代替也适用于旧版本。只有
serial
列有自己的序列。其他列默认值被原封不动地复制 - 包括nextval()
从不属于该列的序列或以任何方式与serial
.该函数对 SQL 注入是安全的,并且可以使用任意表和列名。
db<>fiddle here
旧sqlfiddle
问题是您的parts1 表使用了parts 表中的序列(而不是它自己的序列)......因此它抱怨您不能删除parts 表,因为parts1 表依赖于它(通过其中一个的默认值列)...您在创建parts1表时遇到了这种行为...
创建表- 见
LIKE source_table [ like_option ... ]
部分您可以通过像您所做的那样创建表,然后创建新序列、设置新默认值以及为每个 SERIAL 列创建新依赖项来获得所需的结果(因为 LIKE 选项行为显然不会创建自己的序列)这次)。
完成上述步骤的步骤在 Deszo 的回答中给出
(为方便起见复制.. 更改了他的第 2 步,因为您已经创建了一个表)
您还可以使用此 SQL 帮助识别哪些列属于相关表的 pkey,尽管这不会帮助您识别所有串行列(如果碰巧不是 pkey)。
请参阅Erwin Brandstetter 的答案(我假设)一个更完整的解决方案。
我想至少发布直接的 PHP 函数(我最终会将我正在构建的工具发布到 Github 之类的东西),尽管我还没有时间做很多其他事情,至少在这里发布它。希望这将节省其他人的时间,请随时提出改进建议。我不确定代码的安全性(它只是我仅用于开发的工具,目前用于我正在建立一个仅限 Intranet 的网站的客户),尽管我尽力听取了来自Erwin Brandstetter 和 Joishi Bodio 的其他问题/答案。
示例 URL 请求:
我只是有 PHP 调用函数,因为我经常重复我的 PostgreSQL 工具执行的操作,所以我只是将信息存储在一个
$_GET
数组中。