为postgre 创建不同字符集的编码

本文介绍了PostgreSQL如何处理多种字符集编码,包括多字节字符集的支持方式、可用的字符集编码类型、如何设置编码、服务器与客户端间的自动编码转换等关键技术细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

5.2. 多字节支持

多字节支持 (MB)是为了让 PostgreSQL 能够处理多字节字符集,比如 EUC (扩展 Unix 编码 Extended Unix Code),Unicode 和 Mule 国际编码.把 MB 打开, 你就能在正则表达式(regexp) LIKE,和一些其它函数里使用多字节字符集了. 缺省的编码系统是在你用 initdb 初始化 PostgreSQL 系统安装的时候 确立的.请注意这个缺省是可以在使用 createdb 或者 SQL 命令CREATE DATABASE 创建数据库的时候覆盖的.所以你可以拥有多个有着不同编码系统的数据库. 请注意 MB 可以处理类似 ISO-8859-1 这样的单字节字符集。

PostgreSQL版本 7.3 起,多字节支持就是缺省的了。

5.2.1. 支持字符集编码

下面的字符集可以用做数据库编码。

Table 5-1. 字符集编码

编码描述
SQL_ASCIIUS ASCII
EUC_JP日文 EUC
EUC_CN中文 EUC
EUC_KR韩文 EUC
JOHAB韩文 EUC (Hangle base)
EUC_TW台湾 EUC
UNICODEUnicode(UTF-8)
MULE_INTERNALMule 内部编码
LATIN1ISO 8859-1 ECMA-94 Latin Alphabet No.1
LATIN2ISO 8859-2 ECMA-94 Latin Alphabet No.2
LATIN3ISO 8859-3 ECMA-94 Latin Alphabet No.3
LATIN4ISO 8859-4 ECMA-94 Latin Alphabet No.4
LATIN5ISO 8859-9 ECMA-128 Latin Alphabet No.5
LATIN6ISO 8859-10 ECMA-144 Latin Alphabet No.6
LATIN7ISO 8859-13 Latin Alphabet No.7
LATIN8ISO 8859-14 Latin Alphabet No.8
LATIN9ISO 8859-15 Latin Alphabet No.9
LATIN10ISO 8859-16 ASRO SR 14111 Latin Alphabet No.10
ISO-8859-5ECMA-113 Latin/Cyrillic
ISO-8859-6ECMA-114 Latin/Arabic
ISO-8859-7ECMA-118 Latin/Greek
ISO-8859-8ECMA-121 Latin/Hebrew
KOI8KOI8-R(U)
WINWindows CP1251
ALTWindows CP866
WIN1256阿拉伯语 Windows CP1256
TCVN越南语 TCVN-5712(Windows CP1258)
WIN874泰语(Thai) Windows CP874

 

Important: PostgreSQL7.2 之前, LATIN5错误地表示 ISO 8859-5 的意思. 从 7.2 开始 LATIN5表示 ISO8859-9. 如果你有一个在 7.1 或者之前创建的 使用了 LATIN5的数据库, 而且你希望移植到 7.2(或者以后的版本), 那么你必须非常仔细地 注意这个变化.

Important: 并非所有API支持上面列出的编码.比如, PostgreSQL JDBC 驱动就不支持MULE_INTERNALLATIN6LATIN8LATIN10

5.2.2. 设置编码

initdb 为一次 PostgreSQL 安装定义缺省的编码系统,比如:

$ initdb -E EUC_JP

把缺省编码设置为 EUC_JP (用于日文的扩展的 Unix 编码). 如果你喜欢用长选项声明的话,你可以用 --encoding 代替 -E. 如果没有给出-E或者--encoding选项, 则使用 SQL_ASCII。

你可以创建一个有着不同编码的数据库:

$ createdb -E EUC_KR korean

将创建一个带有EUC_KR编码的名字叫 korean 的数据库. 另外一种实现方法是使用 SQL 命令:

CREATE DATABASE korean WITH ENCODING = 'EUC_KR';

数据库的编码是用系统表 pg_database 里的一个 编码字段代表的. 你可以用psql-l选项或 /l命令列出这些编码.

$ psql -l
	    List of databases
   Database    |  Owner  |   Encoding    
---------------+---------+---------------
 euc_cn	| t-ishii | EUC_CN
 euc_jp	| t-ishii | EUC_JP
 euc_kr	| t-ishii | EUC_KR
 euc_tw	| t-ishii | EUC_TW
 mule_internal | t-ishii | MULE_INTERNAL
 regression    | t-ishii | SQL_ASCII
 template1     | t-ishii | EUC_JP
 test	  | t-ishii | EUC_JP
 unicode       | t-ishii | UNICODE
(9 rows)

 

5.2.3. 服务器和客户端之间的自动编码转换

PostgreSQL 支持一些编码 在服务器和前端之间的自动编码转换. 转换信息在系统表 pg_conversion 中存储。 你可以使用 CREATE CONVERSION 创建一个 新的转换。PostgreSQL带着一些预定义的转换。它们在 Table 5-2 中列出.

Table 5-2. Client/Server 字符集编码

服务器编码可用客户端编码
SQL_ASCIISQL_ASCII, UNICODE, MULE_INTERNAL
EUC_JPEUC_JP, SJIS, UNICODE, MULE_INTERNAL
EUC_CNEUC_CN, UNICODE, MULE_INTERNAL
EUC_KREUC_KR, UNICODE, MULE_INTERNAL
JOHABJOHAB, UNICODE
EUC_TWEUC_TW, BIG5, UNICODE, MULE_INTERNAL
LATIN1LATIN1, UNICODE, MULE_INTERNAL
LATIN2LATIN2, WIN1250, UNICODE, MULE_INTERNAL
LATIN3LATIN3, UNICODE, MULE_INTERNAL
LATIN4LATIN4, UNICODE, MULE_INTERNAL
LATIN5LATIN5, UNICODE
LATIN6LATIN6, UNICODE, MULE_INTERNAL
LATIN7LATIN7, UNICODE, MULE_INTERNAL
LATIN8LATIN8, UNICODE, MULE_INTERNAL
LATIN9LATIN9, UNICODE, MULE_INTERNAL
LATIN10LATIN10, UNICODE, MULE_INTERNAL
ISO_8859_5ISO_8859_5, UNICODE, MULE_INTERNAL, WIN, ALT, KOI8
ISO_8859_6ISO_8859_6, UNICODE
ISO_8859_7ISO_8859_7, UNICODE
ISO_8859_8ISO_8859_8, UNICODE
UNICODEEUC_JP, SJIS, EUC_KR, UHC, JOHAB, EUC_CN, GBK, EUC_TW, BIG5, LATIN1 to LATIN10, ISO_8859_5, ISO_8859_6, ISO_8859_7, ISO_8859_8, WIN, ALT, KOI8, WIN1256, TCVN, WIN874, GB18030, WIN1250
MULE_INTERNALEUC_JP, SJIS, EUC_KR, EUC_CN, EUC_TW, BIG5, LATIN1LATIN5, WIN, ALT, WIN1250 BIG5, ISO_8859_5, KOI8
KOI8ISO_8859_5, WIN, ALT, KOI8, UNICODE, MULE_INTERNAL
WINISO_8859_5, WIN, ALT, KOI8, UNICODE, MULE_INTERNAL
ALTISO_8859_5, WIN, ALT, KOI8, UNICODE, MULE_INTERNAL
WIN1256WIN1256, UNICODE
TCVNTCVN, UNICODE
WIN874WIN874, UNICODE

要想打开编码转换功能,你必须告诉 PostgreSQL 你想在客户端使用的编码.你可以用好几种方法实现这个目的.

 

 

  • psql 里的 /encoding 命令. /encoding 允许你动态修改客户端编码. 比如,把编码改变为 SJIS,键入:

    /encoding SJIS

     

  • 使用 libpq 函数. /encoding 在做此用途的时候实际上是调用 PQsetClientEncoding()

    int PQsetClientEncoding(PGconn *conn, const char *encoding)

    这里 conn 与后端的联接,而 encoding 是你想用的编码.如果编码设置成功 它返回 0,否则返回 -1.本次联接的当前编码可以用下面函数显示:

    int PQclientEncoding(const PGconn *conn)

    请注意它只返回编码 ID,而不是象 EUC_JP 这样的编码符号字串. 要把编码 ID 转换为编码符号,你可以用:

    char *pg_encoding_to_char(int encoding_id)

     

  • 使用 SET CLIENT_ENCODING TO. 可以用 SQL 命令设置客户端编码:

    SET CLIENT_ENCODING TO 'encoding';

    你还可以把 SQL92 语法里的 SET NAMES用于这个目的:

    SET NAMES 'encoding';

    查询当前客户端编码:

    SHOW CLIENT_ENCODING;

    返回缺省编码:

    RESET CLIENT_ENCODING;

     

  • 使用 PGCLIENTENCODING. 如果在客户端的环境里定义了 PGCLIENTENCODING 环境变量, 那么在与服务器进行联接时将自动选择客户端编码. (这个编码随后可以用上面谈到的任何其它方法覆盖.)

  • 使用 client_encoding 变量。 如果在 postgresql.conf 里设置了 client_encoding 变量, 那么在与服务器建立了联接之后,这个客户端编码将自动选定。(这个设置随后可以被上面提到 的其他方法覆盖。)

 

5.2.4. 如果不能转换会怎样?

假设你选的服务器编码是EUC_JP, 客户端是LATIN1,那么有些日文字符不能 转换成LATIN1.这时, 不能用LATIN1字符集表示的字母将被转换成:

(HEXA DECIMAL)

 

5.2.5. 参考

下面是学习各种类型的编码系统的好地方.

 

 

ftp://ftp.ora.com/pub/examples/nutshell/ujip/doc/cjk.inf

详细地解释了第3.2节出现的EUC_JPEUC_CNEUC_KREUC_TW

http://www.unicode.org/

Unicode 的家目录.

RFC 2044
<think>我们正在处理一个关于PostgreSQL数据库中将字符类型转换为数值类型的问题。根据用户的问题,我们需要将字符型数据转换为数值型。在PostgreSQL中,我们可以使用`ALTER TABLE...ALTERCOLUMN... TYPE`语句来实现这一转换,但需要注意数据转换的可行性和正确性。 根据引用[2]的内容,修改字段类型有两种情况:①原类型上的修改(如VARCHAR(10)改为VARCHAR(50))②原类型修改为另一种类型(如VARCHAR(50)改为numeric(8,4)) 对于情况②,我们需要使用`USING`子句来指定如何将旧类型转换为新类型。因为直接转换可能会导致错误,特别是当字符串中包含非数字字符时。 因此,将字符类型转换为数值类型的基本语法是: ```sqlALTER TABLEtable_nameALTERCOLUMNcolumn_nameTYPE numeric[(precision,scale)]USINGcolumn_name::numeric; ```这里,`USING`子句中的`column_name::numeric`是将该列当前的数据转换为数值类型。如果转换失败(例如,如果存在非数字字符),则整个操作将失败。另外,我们还需要注意以下几点: 1.在转换前,确保该列中的所有字符串都可以转换为数值。如果有非数字字符,需要先清理数据。2.转换操作可能会锁表,对于大表需要谨慎操作,考虑在低峰期进行或使用其他方法避免长时间锁表。 3.转换后,检查数据是否准确,特别是小数点和精度问题。下面我们给出一个具体的示例: 假设我们有一个表`financial_data`,其中有一个列`amount`是字符类型(如`VARCHAR`),我们想将其转换为`numeric(10,2)`类型。步骤1:检查数据是否可以转换我们可以先运行一个查询来检查是否有非数字数据(除了小数点、负号等):```sqlSELECTamountFROM financial_dataWHERE amount!~ '^[-]?[0-9]+(\.[0-9]*)?$'; ```如果返回有记录,则需要先处理这些数据。步骤2:转换数据类型如果数据都是可转换的,则执行:```sqlALTERTABLE financial_dataALTER COLUMN amountTYPE numeric(10,2)USINGamount::numeric(10,2);``` 注意:如果原始数据中包含多余的空格,我们可以使用`TRIM`函数,例如:```sqlALTERTABLE financial_dataALTER COLUMN amountTYPE numeric(10,2)USINGTRIM(amount)::numeric(10,2);``` 另外,根据引用[3]的内容,数据库编码和字符分类设置(如`LC_CTYPE`)可能会影响字符串的解析,但一般情况下,对于数字转换,只要字符串中只包含数字字符和一个小数点(以及可选的负号),就不会有问题。如果转换过程中出现错误,我们需要根据错误信息调整数据或转换方式。最后,我们生成相关问题:§§相关问题§§1.如何检查PostgreSQL表中某列是否包含非数字字符? 2.在PostgreSQL中转换数据类型时,`USING`子句的作用是什么?3.如何避免在PostgreSQL中修改列类型时长时间锁表?</think>### PostgreSQL 字符类型转数值类型转换指南 在 PostgreSQL 中将字符类型(如 `text`、`varchar`、`char`)转换为数值类型(如 `numeric`、`integer`、`float`)需注意数据兼容性和转换方法。以下是详细步骤和注意事项: #### 1. **基本转换语法** 使用 `ALTER TABLE` 命令配合 `USING` 子句: ```sql ALTER TABLE 表名 ALTER COLUMN 列名 TYPE 数值类型 USING 转换表达式; ``` **示例**: ```sql -- VARCHAR 转 NUMERIC ALTER TABLE sales ALTER COLUMN price TYPE NUMERIC(10,2) USING price::NUMERIC; -- TEXT 转 INTEGER ALTER TABLE products ALTER COLUMN stock TYPE INTEGER USING stock::INTEGER; ``` #### 2. **关键注意事项** - **数据兼容性**:确保所有字符数据都能转换为目标数值类型。若存在非数字字符(如 `'abc'`),转换将失败[^1]。 - **精度处理**:定义数值类型的精度和小数位,例如 `NUMERIC(8,4)` 表示总位数8位,小数位4位[^2]。 - **空值处理**:使用 `NULLIF` 处理空字符串: ```sql USING NULLIF(列名, '')::NUMERIC ``` #### 3. **数据验证与清理** 转换前需验证数据: ```sql -- 检查非数字字符 SELECT * FROM 表名 WHERE 列名 ~ '[^0-9\.\-]' AND 列名 IS NOT NULL; -- 清理数据示例(移除货币符号) UPDATE sales SET price = REPLACE(price, '$', ''); ``` #### 4. **转换失败处理** 若部分数据无法转换,可先创建新列: ```sql -- 步骤1:添加新列 ALTER TABLE sales ADD COLUMN price_new NUMERIC; -- 步骤2:安全转换 UPDATE sales SET price_new = CASE WHEN price ~ '^[0-9\.]+$' THEN price::NUMERIC ELSE NULL END; -- 步骤3:删除旧列并重命名 ALTER TABLE sales DROP COLUMN price; ALTER TABLE sales RENAME COLUMN price_new TO price; ``` #### 5. **区域设置影响** 数据库的 `LC_CTYPE` 设置可能影响字符解析(如小数点分隔符)[^3]: ```sql -- 检查当前设置 SHOW LC_CTYPE; -- 临时覆盖设置(使用点号作为小数点) SET lc_numeric = 'C'; ``` ### 典型错误场景 1. **非数字字符**: ```text ERROR: invalid input syntax for type numeric: "abc" ``` **解决方案**:清理数据或使用 `CASE` 表达式处理异常值。 2. **精度溢出**: ```text ERROR: numeric field overflow ``` **解决方案**:增加目标类型的精度(如 `NUMERIC(10,2)` → `NUMERIC(15,2)`)。 3. **空字符串转换**: ```text ERROR: invalid input syntax for type numeric: "" ``` **解决方案**:使用 `NULLIF(列名, '')::NUMERIC`。 ### 最佳实践 1. **备份数据**:转换前务必执行 `pg_dump`。 2. **事务处理**:在事务中执行转换以便回滚: ```sql BEGIN; ALTER TABLE ... ; -- 验证数据后提交 COMMIT; ``` 3. **测试环境验证**:先在测试环境模拟转换过程。 > **提示**:对于包含混合格式(如 `'$123.45'`)的列,建议使用正则表达式提取数字部分: > ```sql > USING (REGEXP_REPLACE(列名, '[^\d\.]', '', 'g'))::NUMERIC > ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值