Jak zmienić kodowanie znaków w bazie danych postgres?

Odpowiedzi:

64

Aby zmienić kodowanie bazy danych:

  1. Zrzuć swoją bazę danych
  2. Porzuć swoją bazę danych,
  3. Utwórz nową bazę danych z innym kodowaniem
  4. Załaduj ponownie swoje dane.

Upewnij się, że kodowanie klienta jest poprawnie ustawione podczas tego wszystkiego.

Źródło: http://archives.postgresql.org/pgsql-novice/2006-03/msg00210.php

Daniel Kutik
źródło
Jedyną rzeczą, której nie dostaję z linku, jest "Sprawdź, czy plik zrzutu utworzony w pierwszym kroku ma jakieś znaki specjalne i
wprowadź
1
Czy możesz dodać polecenia zrzutu i ponownego importu do odpowiedzi? jak sudo -u postgres pg_dump your_db > /backups/postgresql.sql...
rubo77
104

Po pierwsze, odpowiedź Daniela to właściwa, bezpieczna opcja.

W konkretnym przypadku zmiany z SQL_ASCII na coś innego, możesz oszukać i po prostu przejrzeć katalog pg_database, aby ponownie przypisać kodowanie bazy danych. Zakłada się, że już zapisałeś wszystkie znaki spoza ASCII w oczekiwanym kodowaniu (lub po prostu nie użyłeś żadnych znaków spoza ASCII).

Następnie możesz:

update pg_database set encoding = pg_char_to_encoding('UTF8') where datname = 'thedb'

Nie zmieni to sortowania bazy danych, tylko sposób, w jaki zakodowane bajty są konwertowane na znaki (więc teraz length('£123')zwróci 4 zamiast 5). Jeśli baza danych używa sortowania „C”, kolejność ciągów ASCII nie powinna być zmieniana. Prawdopodobnie będziesz jednak musiał przebudować wszelkie indeksy zawierające znaki spoza ASCII.

Caveat emptor. Zrzucanie i ponowne ładowanie umożliwia sprawdzenie, czy zawartość bazy danych jest rzeczywiście zgodna z oczekiwanym kodowaniem, a tak się nie dzieje. A jeśli okaże się, że masz w bazie danych nieprawidłowo zakodowane dane, ratowanie będzie trudne. Więc jeśli możesz, zrzuć i ponownie zainicjuj.

araqnid
źródło
1
+1 Dziękuję. Moja maszyna deweloperska używa kodowania UTF8, ale moja produkcja używa LATIN1. Miałem z tego powodu wiele błędów.
Luiz Damim
1
Daje mi ten błąd: -bash: syntax error near unexpected token (''
Abhipso Ghosh
@AbhipsoGhosh to nie powinno być wklejane do powłoki bash, ale po znaku psqlzachęty.
Pierre
14

Zrzucenie bazy danych z określonym kodowaniem i próba przywrócenia jej do innej bazy danych z innym kodowaniem może spowodować uszkodzenie danych. Kodowanie danych należy ustawić PRZED wstawieniem jakichkolwiek danych do bazy danych.

Sprawdź to : podczas kopiowania jakiejkolwiek innej bazy danych nie można zmienić ustawień kodowania i ustawień regionalnych w stosunku do ustawień źródłowej bazy danych, ponieważ może to spowodować uszkodzenie danych.

I to : Niektóre kategorie ustawień narodowych muszą mieć ustalone wartości podczas tworzenia bazy danych. Możesz użyć różnych ustawień dla różnych baz danych, ale po utworzeniu bazy danych nie możesz ich już zmienić dla tej bazy danych. LC_COLLATE i LC_CTYPE to te kategorie. Mają one wpływ na kolejność sortowania indeksów, więc muszą być stałe, w przeciwnym razie indeksy kolumn tekstowych zostaną uszkodzone. ( Ale możesz złagodzić to ograniczenie za pomocą sortowania, jak omówiono w sekcji 22.2. ) Domyślne wartości dla tych kategorii są określane podczas uruchamiania initdb i te wartości są używane podczas tworzenia nowych baz danych, chyba że określono inaczej w poleceniu CREATE DATABASE.


Wolałbym raczej odbudować wszystko od samego początku poprawnie z poprawnym kodowaniem lokalnym w twoim debian OS, jak wyjaśniono tutaj :

su root

Zmień konfigurację ustawień lokalnych:

dpkg-reconfigure locales

Wybierz lokalizację (np. Francuski w Szwajcarii: fr_CH.UTF8)

Odinstaluj i wyczyść poprawnie postgresql:

apt-get --purge remove postgresql\*
rm -r /etc/postgresql/
rm -r /etc/postgresql-common/
rm -r /var/lib/postgresql/
userdel -r postgres
groupdel postgres

Zainstaluj ponownie postgresql:

aptitude install postgresql-9.1 postgresql-contrib-9.1 postgresql-doc-9.1

Teraz każda nowa baza danych zostanie automatycznie utworzona z odpowiednim kodowaniem, LC_TYPE (klasyfikacja znaków) i LC_COLLATE (kolejność sortowania ciągów).

Douglas
źródło
2
Myślę, że jest to „dpkg-rekonfiguruj ustawienia regionalne”, liczba mnoga. Forma pojedyncza wydaje się nie działać (tylko zaznaczona).
foo
9

Odpowiedź Daniela Kutika jest poprawna, ale może być jeszcze bezpieczniejsza dzięki zmianie nazwy bazy danych .

Tak więc naprawdę bezpieczny sposób to:

  1. Utwórz nową bazę danych z innym kodowaniem i nazwą
  2. Zrzuć swoją bazę danych
  3. Przywróć zrzut do nowej bazy danych
  4. Sprawdź, czy Twoja aplikacja działa poprawnie z nową bazą danych
  5. Zmień nazwę starego DB na coś znaczącego
  6. Zmień nazwę nowej bazy danych
  7. Przetestuj aplikację ponownie
  8. Usuń starą bazę danych

W nagłych przypadkach po prostu zmień nazwę DB z powrotem

Sergey Zarubin
źródło
7
# dump into file
pg_dump myDB > /tmp/myDB.sql

# create an empty db with the right encoding (on older versions the escaped single quotes are needed!)
psql -c 'CREATE DATABASE "tempDB" WITH OWNER = "myself" LC_COLLATE = '\''de_DE.utf8'\'' TEMPLATE template0;'

# import in the new DB
psql -d tempDB -1 -f /tmp/myDB.sql

# rename databases
psql -c 'ALTER DATABASE "myDB" RENAME TO "myDB_wrong_encoding";' 
psql -c 'ALTER DATABASE "tempDB" RENAME TO "myDB";'

# see the result
psql myDB -c "SHOW LC_COLLATE"   
rubo77
źródło