我try 从SQL文件导入数据库转储,但在将字符串Mér插入定义为varying(3)的字段时,插入失败.我没有捕捉到确切的错误,但它指向了特定的值,限制为varying(3).

考虑到我认为这对我当时正在做的事情并不重要,我只是将值改为Mer,它起了作用,我继续前进.

varying字段的限制是否考虑了字节字符串的长度?真正让我吃惊的是,这是从另一个PostgreSQL数据库中转储的.因此,约束如何允许最初写入值是没有意义的.

推荐答案

varchar(N)个类型施加并由length函数计算的长度限制是字符,而不是字节.因此,'abcdef'::char(3)被截断为'abc',但'a€cdef'::char(3)被截断为'a€c',即使在编码为UTF-8的数据库中,其中'a€c'使用5个字节进行编码.

如果恢复转储文件时抱怨'Mér'不会进入varchar(3)列,则表明您正在将UTF-8编码的转储文件恢复到SQL_ASCII数据库中.

例如,我在UTF-8数据库中这样做:

create schema so4249745;
create table so4249745.t(key varchar(3) primary key);
insert into so4249745.t values('Mér');

然后将其转储并try 将其加载到SQL_ASCII数据库:

pg_dump -f dump.sql --schema=so4249745 --table=t
createdb -E SQL_ASCII -T template0 enctest
psql -f dump.sql enctest

果然:

psql:dump.sql:34: ERROR:  value too long for type character varying(3)
CONTEXT:  COPY t, line 1, column key: "Mér"

相比之下,如果我将数据库enctest创建为编码为LATIN1或UTF8,那么它的加载很好.

出现此问题的原因是,将数据库转储为多字节字符编码,然后try 将其恢复为SQL_ASCII数据库.使用SQL_ASCII基本上会禁用客户端数据到服务器数据的转码,并假设每个字符有一个字节,让客户端负责使用正确的字符映射.由于转储文件包含存储为UTF-8的字符串,即四个字节,因此SQL_ASCII数据库将其视为四个字符,因此认为它违反了约束.它打印出值,然后我的终端将其重新组合为三个字符.

Postgresql相关问答推荐

一列引用两个不同的表

如何使用docker/docker-compose转到本地主机?

为什么在使用PostGIS时,英国郡的几何图形会出现在几内亚湾?

有没有一种方法可以在参数中添加密码,并在批处理文件中需要时自动获取密码?

PostgreSQL 中的 Datum 数据类型是什么以及它的用途是什么?

JOOQ:数据库版本早于 COCKROACHDB 支持的方言:13.0.0

当参数大小超过 393166 个字符时,PSQL 准备语句查询挂起

将数组的所有元素循环到jsonb中并修改值

如何包装 record_out() 函数?

PostgreSQL:在timestamp::DATE 上创建索引

PostgreSQL 返回准确或最接近查询日期的日期

Postgres中的GROUP BY - JSON数据类型不相等?

使用 RPostgreSQL 进行 UTF-8 / Unicode 文本编码

如何在 PostgreSQL 中截断日期?

SQLAlchemy 和多个进程的连接问题

在同一分区上应用多个窗口函数

用于更改 postgresql 用户密码的 bash 脚本

Hibernate 启动很慢

如何在 postgresql 交叉表中用零替换空值

Postgresql - 更新规则 - 可能有一个最后修改日期,自动更新该行的on update?