PostgreSQL 數據庫編碼問題
1. 數據庫不支持中文,如何使用utf-8編碼
解決辦法:
注意:以下所有代碼都應在數據庫中執行,即可以輸入 ‘\l’ 查看數據庫的命令行,其行首有 ’=#‘ (超級用戶) 或 ’=>‘ (普通用戶)。
方法一:直接修改數據庫編碼
# 修改 datname 為你的數據庫名字,兩條命令效果相同,選擇一個即可
update pg_database set encoding=6 where datname='postgres';
# 命令2
update pg_database set encoding=pg_char_to_encoding('UTF8')
where datname='postgres';
方法二:修改模板庫編碼,一勞永逸。
# 修改模板庫template1編碼, 同理可修改 template0
update pg_database
set (encoding, datctype, datcollate)=(6, 'en_US.UTF8','en_US.UTF8')
where datname = 'template1';
方法三:創建/刪除模板庫
# 創建模板庫,這是一條命令,SQL語法允許命令分行,以分號結束,但回車后,前一行命令不可修改
# 復制前先將第一行的 template1 改成你想要的名字,比如任何簡單的名字: td
create database template1 with
template template0
encoding='UTF8'
lc_ctype='en_US.UTF8'
lc_collate='en_US.UTF8'
allow_connections=TRUE
is_template=True;
# 以后創建數據庫指定模板創建即可
create database template mytemplate;
# 也可以一勞永逸,刪除原來的 template1, 重新創建即可
# 先將模板庫變成普通數據庫,使 datistemplate=True 可以將任何普通數據庫變成模板庫。
update pg_database set datistemplate=False where datname='template1';
# 刪除數據庫
drop database template1;
2. 深入理解
模板庫
PostgreSQL 安裝后自帶三個庫:template0,template1 和 postgres。
template 是模板的意思,template0,template1都是模板庫,創建數據庫便實質是拷貝模板庫,默認的模板庫是 template1。兩個模板庫的唯一區別就是 template1 是可連接的,而 template0 不可連接,就是 \c template 不能進入數據庫。這個屬性是可以修改的(見下文)。
postgres 是一個普通的數據庫,不能作為模板。這個屬性也是可以更改的(見下文),所以任何數據庫都能變成模板庫,模板庫唯一特點就是不能被刪除,所以要想刪除模板庫,需要先將模板庫變成普通數據庫。創建 postgres 數據庫唯一的目的便是方便進入數據庫,因為進入數據庫的命令psql的默認參數是psql -U 用戶名 -d 用戶名命名的數據庫 ,如psql -U postgres -d postgres, PostgreSQL 默認創建的用戶名為 postgres, 所以要創建一個名為postgres的數據庫。數據庫名是必要參數,如果沒有就進不了數據庫。
注意:創建數據庫必須依賴模板庫,所以不要刪除了全部的數據庫,否則沒有模板庫,就再也沒法創建數據庫了。
數據庫編碼
數據庫編碼都是可以直接修改的,所有數據庫基本參數都存放在表 pg_database 中,超級用戶可以在任何數據庫中查看它、修改它。
# 查看 pg_database 表結構,
\d pg_database
Table "pg_catalog.pg_database"
Column | Type | Modifiers
---------------+-----------+-----------
datname | name | not null
datdba | oid | not null
encoding | integer | not null
datcollate | name | not null
datctype | name | not null
datistemplate | boolean | not null
datallowconn | boolean | not null
datconnlimit | integer | not null
datlastsysoid | oid | not null
datfrozenxid | xid | not null
datminmxid | xid | not null
dattablespace | oid | not null
datacl | aclitem[] |
-
參數說明
-
datname 數據庫名字, name類型即字符串,用單引號 ‘’ 括起來,如 ‘template1’。
-
encoding 數據庫編碼代號,一個整數。utf-8的代號為6,代號也可以通過函數得到:
update pg_database set encoding=6 where ... update pg_database set encoding=pg_char_to_encoding('UTF8') where ... -
datcollate、datctype 分別對應數據庫的 Collate 和 Ctype。name字符串,可為 ‘en_US.UTF-8’。模板庫的這兩個字段必須和encoding對應,否則創建數據庫時會報錯:
ERROR: encoding "UTF8" does not match locale "en_US" DETAIL: The chosen LC_CTYPE setting requires encoding "LATIN1".- ‘en_US.UTF-8’ 對應編碼 UTF8 、 ‘en_US’ 對應編碼 LATIN1 。
- 去了解更多編碼:https://www.postgresql.org/docs/12/multibyte.html#MULTIBYTE-CHARSET-SUPPORTED
-
datistemplate 是否為模板庫, 布爾值: false/true ,不限大小寫: TRUE
-
datallowconn 是否能連接,布爾值。
-
查看表 pg_database 內容
select * from pg_database;
datname | datdba | encoding | datcollate | datctype | datistemplate | datallowconn | datconnlimit | datlastsysoid | datfrozenxid | datminmxid | dattablespace | datacl
----------+--------+----------+------------+------------+---------------+--------------+--------------+---------------+--------------+------------+---------------+-------------------------------------
postgres | 10 | 6 | en_US | en_US | f | t | -1 | 12416 | 662 | 1 | 1663 |
template1 | 10 | 6 | en_US.UTF8 | en_US.UTF8 | t | t | -1 | 12416 | 662 | 1 | 1663 |
template0 | 10 | 6 | en_US.UTF8 | en_US.UTF8 | t | f | -1 | 12416 | 662 | 1 | 1663 | {=c/postgres,postgres=CTc/postgres}
(3 rows)
修改表 pg_database / 修改數據庫編碼 / 修改模板庫編碼
這三個問題是等同的,都是用命令 update 修改表 pg_database
# 查看 update 命令用法
\h update
Command: UPDATE
Description: update rows of a table
Syntax:
[ WITH [ RECURSIVE ] with_query [, ...] ]
UPDATE [ ONLY ] table_name [ * ] [ [ AS ] alias ]
SET { column_name = { expression | DEFAULT } |
( column_name [, ...] ) = ( { expression | DEFAULT } [, ...] ) |
( column_name [, ...] ) = ( sub-SELECT )
} [, ...]
[ FROM from_item [, ...] ]
[ WHERE condition | WHERE CURRENT OF cursor_name ]
[ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ]
這里只解釋兩種用法:
# 用法一:
update pg_database set datname='template1' where datname='mytemplate';
# 只能更改表的一個字段,例如這句修改數據庫的名字,只要將默認的模板刪了,就可以把自己的模板設置成默認模板了。
# 用法二:
update pg_database
set (encoding, datcollate, datctype)=(6, 'en_US.UTF8','en_US.UTF8')
where datname='template1';
# 更改表的多個字段,比如修改模板庫的編碼,需要同時修改三個字段。
創建數據庫時,也可以自定義某些參數,並不是完全復制模板庫,甚至可以直接創建模板庫。如下所示:
\h create database
Command: CREATE DATABASE
Description: create a new database
Syntax:
CREATE DATABASE name
[ [ WITH ] [ OWNER [=] user_name ]
[ TEMPLATE [=] template ]
[ ENCODING [=] encoding ]
[ LC_COLLATE [=] lc_collate ]
[ LC_CTYPE [=] lc_ctype ]
[ TABLESPACE [=] tablespace_name ]
[ ALLOW_CONNECTIONS [=] allowconn ]
[ CONNECTION LIMIT [=] connlimit ]
[ IS_TEMPLATE [=] istemplate ] ]
- 解釋:
- [] 里左邊的名字才是參數名,右邊的是說明,但 SQL 語句不區分大小寫,使用小寫字母更直觀,如
create database allow_connections true。害怕寫錯單詞可以直接復制,使用大寫字母。 - owner 擁有者,template 模板
- encoding 編碼, lc_collate Collate屬性, lc_ctype Ctype屬性,這三個字段必須對應,設置時應同時設置。
- allow_connection 允許連接,istemplate 是模板庫
- [] 里左邊的名字才是參數名,右邊的是說明,但 SQL 語句不區分大小寫,使用小寫字母更直觀,如
如:創建一個模板庫
create database mytemplate
encoding='UTF8'
lc_ctype='en_US.UTF8'
lc_collate='en_US.UTF8'
IS_TEMPLATE true
TEMPLATE template0;
敲重點:數據庫的三個有關編碼的字段 encoding、ctype、collate 必須同時設置,關系要對應,比如 ‘en_US.UTF-8’ 對應的編碼為 UTF8,代號6, 對應 ‘en_US’ 對應的編碼為 LATIN1,代號8 。 ‘en_US.UTF-8’ 雖為字符串,但一個字也不能錯。
