sql >> Databasteknik >  >> RDS >> PostgreSQL

Räknas Postgresql varchar med unicode-teckenlängd eller ASCII-teckenlängd?

Längdgränsen som sätts av varchar(N) typer och beräknas av length Funktionen är i tecken, inte byte. Så 'abcdef'::char(3) trunkeras till 'abc' men 'a€cdef'::char(3) trunkeras till 'a€c' , även i sammanhanget med en databas kodad som UTF-8, där 'a€c' är kodad med 5 byte.

Om återställning av en dumpfil klagade på att 'Mér' skulle inte gå in i en varchar(3) kolumn, som tyder på att du återställde en UTF-8-kodad dumpfil till en SQL_ASCII-databas.

Till exempel gjorde jag detta i en UTF-8-databas:

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

Och sedan dumpade detta och försökte ladda det till en SQL_ASCII-databas:

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

Och visst:

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

Om jag däremot skapar databasen enctest som kodande LATIN1 eller UTF8, laddas den bra.

Detta problem uppstår på grund av en kombination av att dumpa en databas med en multi-byte teckenkodning och försöka återställa den till en SQL_ASCII-databas. Att använda SQL_ASCII inaktiverar i princip omkodningen av klientdata till serverdata och antar en byte per tecken, vilket överlåter till klienterna att ta ansvar för att använda rätt teckenkarta. Eftersom dumpfilen innehåller den lagrade strängen som UTF-8, det vill säga fyra byte, så ser en SQL_ASCII-databas det som fyra tecken och anser därför att det bryter mot begränsningen. Och den skriver ut värdet, som min terminal sedan sätter ihop som tre tecken.



  1. Exempel på att konvertera "datum" till "datetimeoffset" i SQL Server (T-SQL)

  2. Välj föregående rad mysql?

  3. Yttre välj kolumnvärde i sammanfogad delfråga?

  4. Granskning av SQL Server-dataändringar