Sql 使用串行主键列安全地重命名表
我知道,使用Sql 使用串行主键列安全地重命名表,sql,postgresql,database-design,ddl,Sql,Postgresql,Database Design,Ddl,我知道,使用串行主键的PostgreSQL表最终由PostgreSQL创建了一个隐式索引、序列和约束。问题是在重命名表时如何重命名这些隐式对象。下面是我在最后用具体问题来解决这个问题的尝试 给出如下表格: CREATE TABLE foo ( pkey SERIAL PRIMARY KEY, value INTEGER ); 研究生产出: 注意:CREATE TABLE将为序列列“foo.pkey”创建隐式序列“foo_pkey_seq” 注意:CREATE TABLE/主键将
串行
主键的PostgreSQL表最终由PostgreSQL创建了一个隐式索引、序列和约束。问题是在重命名表时如何重命名这些隐式对象。下面是我在最后用具体问题来解决这个问题的尝试
给出如下表格:
CREATE TABLE foo (
pkey SERIAL PRIMARY KEY,
value INTEGER
);
研究生产出:
注意:CREATE TABLE将为序列列“foo.pkey”创建隐式序列“foo_pkey_seq”注意:CREATE TABLE/主键将为表“foo”创建隐式索引“foo_pkey”
查询已成功返回,52毫秒内没有结果 pgAdmin III SQL窗格显示表的以下DDL脚本(已分离): 现在重命名该表:
ALTER table foo RENAME TO bar;
查询已成功返回,17毫秒内没有结果
pgAdmin III:
CREATE TABLE bar (
pkey integer NOT NULL DEFAULT nextval('foo_pkey_seq'::regclass),
value integer,
CONSTRAINT foo_pkey PRIMARY KEY (pkey )
);
ALTER TABLE bar OWNER TO postgres;
CREATE TABLE bar (
pkey serial NOT NULL,
value integer,
CONSTRAINT foo_pkey PRIMARY KEY (pkey )
);
ALTER TABLE bar OWNER TO postgres;
注意额外的默认nextval('foo\u pkey\u seq'::regclass),
这意味着重命名表不会重命名主键的序列,但现在我们有了这个显式的nextval()
现在重命名序列:
ALTER table foo RENAME TO bar;
我想保持数据库命名的一致性,因此我尝试:
ALTER SEQUENCE foo_pkey_seq RENAME TO bar_pkey_seq;
查询已成功返回,17毫秒内没有结果
pgAdmin III:
CREATE TABLE bar (
pkey integer NOT NULL DEFAULT nextval('foo_pkey_seq'::regclass),
value integer,
CONSTRAINT foo_pkey PRIMARY KEY (pkey )
);
ALTER TABLE bar OWNER TO postgres;
CREATE TABLE bar (
pkey serial NOT NULL,
value integer,
CONSTRAINT foo_pkey PRIMARY KEY (pkey )
);
ALTER TABLE bar OWNER TO postgres;
默认的nextval('foo_pkey_seq'::regclass)已消失
问题
foo\u pkey
。约束如何重命名serial
不是实际的数据类型:
数据类型smallserial
、serial
和bigserial
不是真正的类型,
但这仅仅是创建唯一标识符列的一种符号方便
通过执行以下所有操作来解析伪数据类型:
- 创建名为
tablename\u colname\u seq的序列
- 创建类型为
(或integer
/int2
的列,分别用于int8
/smallserial
)bigserial
- 将列
设为非空默认值nextval('tablename\u colname\u seq')
- 使列拥有序列,以便自动删除它
serial
完成所有这些操作。pgAdmin检查列出的功能,如果满足所有要求,则使用匹配的serial
类型简化反向工程DDL脚本。如果不满足其中一个特征,则不会进行此简化。这是pgAdmin所做的。对于基础目录表,这一切都是一样的。不存在类似的串行
类型
无法自动重命名拥有的序列。您可以运行:
ALTER SEQUENCE ... RENAME TO ...
就像你那样。系统本身并不关心名称。列DEFAULT
存储一个('foo\u pkey\u seq'::regclass
),您可以更改序列的名称而不中断该名称-OID保持不变。数据库中的外键和类似引用也是如此
主键的隐式索引绑定到PK约束的名称,如果更改表的名称,该名称将不会更改
也要纠正这一点
还可以引用表名命名索引:
可以对表名进行各种非正式引用。系统无法强制重命名可以随意命名的对象。它不在乎
当然,您不希望使引用这些名称的SQL代码无效。显然,当应用程序逻辑引用名称时,您不想更改名称。通常情况下,索引、序列或约束的名称不会有问题,因为它们通常不被名称引用
Postgres还可以在重命名对象之前获得对象的锁定。因此,如果有并发事务处于打开状态,并且对所讨论的对象有任何类型的锁定,则您的重命名
操作将暂停,直到这些事务提交或回滚
系统目录和OID
数据库架构存储在系统架构pg_catalog
中的系统目录表中。如果你不知道自己在做什么,你就不应该把那些桌子弄得乱七八糟。一个错误的移动,你可以打破你的数据库
对于一些最重要的表,Postgres提供并键入cast以获取OID的名称,反之亦然。比如:
SELECT 'foo_pkey_seq'::regclass
如果架构名称位于搜索路径中,并且表名称是唯一的,则给出的结果与:
SELECT oid FROM pg_class WHERE relname = 'foo_pkey_seq';
大多数目录表的主键是oid,在内部,大多数引用都使用oid。我猜想命名序列具有神奇的语法意义,Postgres知道使用一个所谓的序列作为表的主键序列,而不显式地将其作为表的主键列的默认值列出。不过,我并不知道这一点,也没有任何证据。如果这个问题到那时还没有答案,我们将在下班后进一步调查。“ALTER TABLE…RENAME CONSTRAINT…”需要PostgreSQL 9.2+可能会有所帮助