Подтвердить что ты не робот

Использует ли значение Postgresql varchar использование длины символа Юникода или длины символа ASCII?

Я попытался импортировать дамп базы данных из файла SQL, и вставка не удалась при вставке строки Mér в поле, определенное как varying(3). Я не зафиксировал точную ошибку, но указал на это конкретное значение с ограничением varying(3).

Учитывая, что я считал это несущественным для того, что я делал в то время, я просто изменил значение на Mer, он работал, и я перешел.

Поле varying с его лимитом с учетом длины строки байта? Что действительно пугает мой разум, так это то, что он был сброшен из другой базы данных PostgreSQL. Таким образом, не имеет смысла, как ограничение может позволить первоначально записать значение.

4b9b3361

Ответ 1

Предел длины, наложенный типами 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');

И затем сбросил это и попытался загрузить его в базу данных 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, она загружается штрафом.

Эта проблема возникает из-за комбинации сброса базы данных с многобайтовой кодировкой символов и попытки ее восстановления в базу данных SQL_ASCII. Использование SQL_ASCII в основном отключает транскодирование данных клиента на данные сервера и предполагает один байт на символ, оставляя его для клиентов брать на себя ответственность за использование правильной карты символов. Поскольку файл дампа содержит сохраненную строку как UTF-8, то есть четыре байта, поэтому база данных SQL_ASCII видит это как четыре символа и поэтому считает это нарушением ограничения. И он печатает значение, которое мой терминал затем собирает в виде трех символов.

Ответ 2

Это зависит от того, какое значение вы использовали при создании базы данных. createdb -E UNICODE создает unicode db, который также должен принимать многобайтовые символы и указывать их как один символ.

Вы можете использовать

psql -l

чтобы узнать, какая кодировка была использована. На странице http://www.postgresql.org/docs/8.4/interactive/multibyte.html есть таблица, включающая информацию о том, сколько байтов на символ используется.