PostgreSQL中的序列名很长很长怎么办

              PostgreSQL中的序列名很长很长怎么办

PostgreSQL中的序列名很长很长怎么办

tag: PostgreSQL, 数据库移植

1.前言

我们回忆一下,PostgreSQL好像有对象名不超过63个字符的默认限制。详见: current/limit.html

 

而序列名可能是由系统自动生成的那种。比如一个表定义了某一列是serial之类的,它会隐含创建一个sequence。

我们来通过简单的实例看看这是啥样的情形?本能的,你可能以为,如果表名很长,序列名是不是超长了?

2.实际验证

2.1 正常的示例:

 1postgres=# create table test(id bigserial, col2 text);
2CREATE TABLE
3postgres=# \d+ test
4                                                       Table "public.test"
5 Column |  Type  | Collation | Nullable |             Default              | Storage  | Compression | Stats target | Description
6--------+--------+-----------+----------+----------------------------------+----------+-------------+--------------+-------------
7 id     | bigint |           | not null | nextval('test_id_seq'::regclass) | plain    |             |              |
8 col2   | text   |           |          |                                  | extended |             |              |
9Access method: heap
10
11postgres=# \d+ test_id_seq
12                        Sequence "public.test_id_seq"
13  Type  | Start | Minimum |       Maximum       | Increment | Cycles? | Cache
14--------+-------+---------+---------------------+-----------+---------+-------
15 bigint |     1 |       1 | 9223372036854775807 |         1 | no      |     1
16Owned by: public.test.id

在这个例子中,我们建了一个普通的表test,列: id是一个8位序列类型,这样系统会为表test自动生成序列:test_id_seq,它的名字不过就是11。是<表名>_<列名>_seq,也就是len(序列名) = len(表名) + len(seq列名)+5

这种情况发生在后者加起来不超过63的情况。

接下来,我们构造一两个边界的例子看看是什么样子的。

2.2 列名很长

建了下面这张表,让序列对应的列名长为63.

 1postgres=# create table test1(col123456789012345678901234567890123456789012345678901234567890 bigserial, col2 text);
2CREATE TABLE
3postgres=# \d+ test1
4                                                                                                             Table "public.test1"
5                             Column                              |  Type  | Collation | Nullable |
6 Default                                        | Storage  | Compression | Stats target | Description
7-----------------------------------------------------------------+--------+-----------+----------+--------------------------------------
8------------------------------------------------+----------+-------------+--------------+-------------
9 col123456789012345678901234567890123456789012345678901234567890 | bigint |           | not null | nextval('test1_col1234567890123456789
100123456789012345678901234567890_seq'::regclass) | plain    |             |              |
11 col2                                                            | text   |           |          |
12                                                | extended |             |              |
13Access method: heap

我们能看到,生成的序列名为:test1_col12345678901234567890123456789012345678901234567890_seq,总长也是63。

 

将列名最末字符换成1,结果就是:

 1postgres=# create table test1(col123456789012345678901234567890123456789012345678901234567891 bigserial, col2 text);
2CREATE TABLE
3postgres=# \d+ test1
4                                                                                                             Table "public.test1"
5                             Column                              |  Type  | Collation | Nullable |
6 Default                                        | Storage  | Compression | Stats target | Description
7-----------------------------------------------------------------+--------+-----------+----------+--------------------------------------
8------------------------------------------------+----------+-------------+--------------+-------------
9 col123456789012345678901234567890123456789012345678901234567891 | bigint |           | not null | nextval('test1_col1234567890123456789
100123456789012345678901234567890_seq'::regclass) | plain    |             |              |
11 col2                                                            | text   |           |          |
12                                                | extended |             |              |
13Access method: heap

生成的序列名为:test1_col12345678901234567890123456789012345678901234567890_seq,总长也是63。

名字与前边那个是一样的,对比一下看下图:

 

反向推理:它是把 {表名_截短后的列名_seq}构造成新的序列名。截短的原则是,从最末尾的子串进行截短。超长的部分都截掉。

2.3 表名很长

我们再看看如下示例,表名长度为63:tab123456789012345678901234567890123456789012345678901234567890

生成的序列名为:tab1234567890123456789012345678901234567890123_id1234567890_seq, 长度仍然为63.

 1postgres=# create table tab123456789012345678901234567890123456789012345678901234567890(id1234567890 bigserial, col2 text);
2CREATE TABLE
3postgres=# \d+ tab123456789012345678901234567890123456789012345678901234567890
4                                                      Table "public.tab123456789012345678901234567890123456789012345678901234567890"
5    Column    |  Type  | Collation | Nullable |                                       Default                                        | S
6torage  | Compression | Stats target | Description
7--------------+--------+-----------+----------+--------------------------------------------------------------------------------------+--
8--------+-------------+--------------+-------------
9 id1234567890 | bigint |           | not null | nextval('tab1234567890123456789012345678901234567890123_id1234567890_seq'::regclass) | p
10lain    |             |              |
11 col2         | text   |           |          |                                                                                      | e
12xtended |             |              |
13Access method: heap

对比一下这两个名字:

看起来,生成的名字是:{截短后表名_列名_seq}。如果是这样,依据这个,构造一个不同的表名,看看是什么样的?

比如表名是:tab123456789012345678901234567890123456789012345678901234567891,即最末一个字符不同。我们看看:

 1postgres=# create table tab123456789012345678901234567890123456789012345678901234567891(id1234567890 bigserial, col2 text);
2CREATE TABLE
3postgres=# \d+ tab123456789012345678901234567890123456789012345678901234567891
4                                                      Table "public.tab123456789012345678901234567890123456789012345678901234567891"
5    Column    |  Type  | Collation | Nullable |                                       Default                                        | S
6torage  | Compression | Stats target | Description
7--------------+--------+-----------+----------+--------------------------------------------------------------------------------------+--
8--------+-------------+--------------+-------------
9 id1234567890 | bigint |           | not null | nextval('tab123456789012345678901234567890123456789012_id1234567890_seq1'::regclass) | p
10lain    |             |              |
11 col2         | text   |           |          |                                                                                      | e
12xtended |             |              |
13Access method: heap

在这个我们想像的”反例“中,

表名:
tab123456789012345678901234567890123456789012345678901234567891

序列名:
tab123456789012345678901234567890123456789012_id1234567890_seq1

与上边的示例四个名字对比一下:

 

 

反推一下,情况也明了了,当它发现序列名可能重复时,会在seq后边加上计数器,然后前边的截断重新调整一下就实现了唯一性。这个算法看来不错。

2.4 表名和列名都很长

我们一步到位。表名:
tab123456789012345678901234567890123456789012345678901234567892  长度:63

序列列名:
col123456789012345678901234567890123456789012345678901234567890 长度:63

两者都很长。

 1postgres=# create table tab123456789012345678901234567890123456789012345678901234567892(col123456789012345678901234567890123456789012345678901234567890 bigserial, col2 text);
2CREATE TABLE
3postgres=# \d+ tab123456789012345678901234567890123456789012345678901234567892
4                                                                                Table "public.tab123456789012345678901234567890123456789
5012345678901234567892"
6                             Column                              |  Type  | Collation | Nullable |
7 Default                                        | Storage  | Compression | Stats target | Description
8-----------------------------------------------------------------+--------+-----------+----------+--------------------------------------
9------------------------------------------------+----------+-------------+--------------+-------------
10 col123456789012345678901234567890123456789012345678901234567890 | bigint |           | not null | nextval('tab12345678901234567890123456_col12345678901234567890123456_seq'::regclass) | plain    |             |              |
11 col2                                                            | text   |           |          |
12                                                | extended |             |              |
13Access method: heap

我们看看生成的序列名:tab12345678901234567890123456_col12345678901234567890123456_seq  长度:63

1表名:tab123456789012345678901234567890123456789012345678901234567892
2列表:col123456789012345678901234567890123456789012345678901234567890 
3序列:tab12345678901234567890123456_col12345678901234567890123456_seq

 

从现象上看,它从表名中拿了30个字符,从列名中拿了前30个字符。这个应该也有一定的选择性算法。

如果我们把上边的表名调整一下,末位改为1. 得到的是下边的结果:

 1postgres=# create table tab123456789012345678901234567890123456789012345678901234567891(col123456789012345678901234567890123456789012345678901234567890 bigserial, col2 text)
2;
3CREATE TABLE
4postgres=# \d+ tab123456789012345678901234567890123456789012345678901234567891
5                                                                                Table "public.tab123456789012345678901234567890123456789
6012345678901234567891"
7                             Column                              |  Type  | Collation | Nullable |
8 Default                                        | Storage  | Compression | Stats target | Description
9-----------------------------------------------------------------+--------+-----------+----------+--------------------------------------
10------------------------------------------------+----------+-------------+--------------+-------------
11 col123456789012345678901234567890123456789012345678901234567890 | bigint |           | not null | nextval('tab12345678901234567890123456_col1234567890123456789012345_seq1'::regclass) | plain    |             |              |
12 col2                                                            | text   |           |          |
13                                                | extended |             |              |
14Access method: heap
1表名:tab123456789012345678901234567890123456789012345678901234567891
2列表:col123456789012345678901234567890123456789012345678901234567890 
3序列:tab12345678901234567890123456_col1234567890123456789012345_seq1

 


作为对比,我们发现,它这里仍然以”去重“为思想,然后从总的表名列名全并串里头重新截短。真是妙。

至此,全部验证结束。我们可以大胆放心的使用了。

小结:

PostgreSQL中的对象名长度限制,针对序列类型的序列对象名的自动生成,还是比较巧妙的。我们也不用担心超长的问题。它会根据表名以及对应的列名,有规律的生成序列名。在认为有重复的时候,后缀可能就是_seq1, _seq2。

所以,放心大胆的用吧。只要表名列名都不超长即可。

posted @ 2023-05-13 14:52  binbinx  阅读(160)  评论(0编辑  收藏  举报