
# RDS for PostgreSQL自定义数据类型转换
#### 简介
PostgreSQL数据类型有三种转换方式：隐式转换，赋值转换，显式转换。对应的转换类型在系统表"pg_cast"中分别对应：i（Implicit）、a（Assignment）、e（Explicit）。
- 隐式转换（Implicit）：同一类型间，低字节到高字节为隐式转换，比如int到bigint。
- 赋值转换（Assignment）：同一类型间，高字节到低字节为赋值转换，比如smallint到int。
- 显式转换（Explicit）：不同类型间，称为显式转换。
 
#### 基本使用
1. 在进行数据类型转换前，可以通过如下命令查看RDS for PostgreSQL是否已经支持数据类型转换。
   ```
   select * from pg_catalog.pg_cast ;
   oid  | castsource | casttarget | castfunc | castcontext | castmethod 
   -------+------------+------------+----------+-------------+------------
    11277 |         20 |         21 |      714 | a           | f
    11278 |         20 |         23 |      480 | a           | f
    11279 |         20 |        700 |      652 | i           | f
    11280 |         20 |        701 |      482 | i           | f
   ......
   ```
   
2. 通过如下命令查询**int4** 是否支持转换**text。**
   ```
   select * from pg_catalog.pg_cast where castsource = 'int4'::regtype and casttarget = 'bool'::regtype;
     oid  | castsource | casttarget | castfunc | castcontext | castmethod 
   -------+------------+------------+----------+-------------+------------
    11311 |         23 |         16 |     2557 | e           | f
   (1 row)
   ```
   此时查出结果是默认支持的，转换类型是隐式转换。
   如果没有内置的转换函数，需要自定义转换函数来支持这种转换，具体参考[自定义类型转换]。
   
 
 #### 自定义类型转换
- 通过双冒号方式进行强制转换
  ```
  select '10'::int,'2023-10-05'::date;
   int4 |    date    
  ------+------------
     10 | 2023-10-05
  (1 row)
  ```
  
- 通过类型转换函数**CAST** 进行转换
  ```
  select CAST('10' as int),CAST('2023-10-05' as date);
   int4 |    date    
  ------+------------
     10 | 2023-10-05
  (1 row)
  ```
  
- 自定义类型转换 具体语法及使用可查看：<https://www.postgresql.org/docs/14/sql-createcast.html>
  ![](https://support.huaweicloud.com/bestpractice-rds-pg/public_sys-resources/notice_3.0-zh-cn.png)
  由于新增自定义类型转换会影响RDS for PostgreSQL已有的执行计划，一般不建议自定义类型转换。
  - 时间与字符类型的转换 **CREATE CAST(varchar as date) WITH INOUT AS IMPLICIT;**
    
  
  - boolean类型与数值类型转换 **create cast(boolean as numeric) with INOUT AS IMPLICIT;**
    
  
  - 数值类型与字符类型转换 **create cast(varchar as numeric) with INOUT AS IMPLICIT;**
    
  
  
  示例：将**text** 转换为**date**
  ```
  create or replace function public.text_to_date(text) returns date as 
  $$          
    select to_date($1,'yyyy-mm-dd');  
  $$ 
  language sql strict;  
  create cast (text as date) with function public.text_to_date(text) as implicit;  
  select text '2023-09-09' + 1;
    ?column?  
  ------------
   2023-09-10
  (1 row)
  ```
  
 
