PostgreSQL有意思的现象:支持不带列的表

1、前言

以前从没有试过建一张表,不带任何列。在PG中却支持这种语法。这是个什么鬼?

最近,把PG源码扒了下,简单浏览了下最近的一些merge。其中有一个fix:

eeb0ebad79 ("Fix the initial sync tables with no columns.", 2023-11-22)

    Fix the initial sync tables with no columns.

    The copy command formed for initial sync was using parenthesis for tables
    with no columns leading to syntax error. This patch avoids adding
    parenthesis for such tables.

    Reported-by: Justin G
    Author: Vignesh C
    Reviewed-by: Peter Smith, Amit Kapila
    Backpatch-through: 15
    Discussion: http://postgr.es/m/[email protected]

简单的说,是它考虑到一张表,在初始SYNC时,有可能没有任何列。按自己的印象,别的DBMS好像没有支持这种语法的。

2、简单验证

如果我们在SQLSERVER哪怕是最新版2022上试一下,

https://dbfiddle.uk/1n2I7Bj9
create table tab_no_col();
-- 立马报错
Msg 102 Level 15 State 1 Line 1
Incorrect syntax near ')'.

PostgreSQL有意思的现象:支持不带列的表_第1张图片

切到MySQL, 也不支持这种语法:

https://dbfiddle.uk/xZPbFq4N
create table tab_no_col();
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1

PostgreSQL有意思的现象:支持不带列的表_第2张图片

再试下Oracle, 发现也不支持。哪怕是23C。

https://dbfiddle.uk/-F2lutlX
create table tab_no_col();
ORA-00931: missing identifier

PostgreSQL有意思的现象:支持不带列的表_第3张图片

3、PostgreSQL中的行为

我们就以PostgreSQL 14为例 :

postgres=# create table tab_no_col();
CREATE TABLE
postgres=# insert into tab_no_col default values;
INSERT 0 1
postgres=# select * from tab_no_col;
--
(1 row)

postgres=# insert into tab_no_col default values;
INSERT 0 1
postgres=# insert into tab_no_col default values;
INSERT 0 1
postgres=# insert into tab_no_col default values;
INSERT 0 1
postgres=# select count(*) from tab_no_col;
 count 
-------
     4
(1 row)

postgres=# select * from tab_no_col;
--
(4 rows)

虽然没有真正的值,但是却一样可以插入相关的值,并得到相应的行数。

根据这种特性,我们甚至可以预先建一张没有任何列的表,然后,插入一些列。看看:

postgres=# alter table tab_no_col add col2 varchar(32) null;
ALTER TABLE

postgres=# select * from tab_no_col;
 col2 
------




(4 rows)

更新一些值:

postgres=# update tab_no_col set col2 = 'a_' || ctid || '_' || xmin;
UPDATE 4
postgres=# select * from tab_no_col;
    col2     
-------------
 a_(0,1)_785
 a_(0,2)_786
 a_(0,3)_787
 a_(0,4)_788
(4 rows)

这种功能,也许最大的好处就是先建一张表(空列),然后可以动态的增加或改变一些列。利用FOR循环时,直接"(" 和 ”)" 做匹配,而不用考虑列数是否真正大于0。

反正CREATE TABLE ABC(, 即算完全是空的,语法上它也不会报错。

你可能感兴趣的:(PostgreSQL,Database,General,postgresql,数据库)