转载自:https://yq.aliyun.com/articles/228271

背景

PostgreSQL是一个强类型数据库,因此你输入的变量、常量是什么类型,是强绑定的,例如

在调用操作符时,需要通过操作符边上的数据类型,选择对应的操作符。

在调用函数时,需要根据输入的类型,选择对应的函数。

如果类型不匹配,就会报操作符不存在,或者函数不存在的错误。


  1. postgres=#select'1'+'1';
  2. ERROR:operatorisnot unique: unknown + unknown
  3. LINE 1:select'1'+'1';
  4. ^
  5. HINT:Couldnot choose a best candidate operator.You might need to add explicit type casts.

那么使用起来是不是很不方便呢?

PostgreSQL开放了类型转换的接口,同时也内置了很多的自动类型转换。来简化操作。

查看目前已有的类型转换:


  1. postgres=# \dC+
  2. List of casts
  3. Source type |Target type |Function|Implicit?|Description
  4. -----------------------------+-----------------------------+--------------------+---------------+-------------
  5. "char"| character | bpchar |in assignment |
  6. "char"| character varying | text |in assignment |
  7. "char"| integer | int4 |no|
  8. "char"| text | text | yes |
  9. abstime | date | date |in assignment |
  10. abstime | integer |(binary coercible)|no|
  11. abstime | time without time zone | time |in assignment |
  12. ................................
  13. timestamp without time zone | timestamp with time zone | timestamptz | yes |
  14. timestamp without time zone | timestamp without time zone | timestamp | yes |
  15. xml | character |(binary coercible)|in assignment |
  16. xml | character varying |(binary coercible)|in assignment |
  17. xml | text |(binary coercible)|in assignment |
  18. (246 rows)

如果你发现有些类型转换没有内置,怎么办呢?我们可以自定义转换。

当然你也可以使用这种语法,对类型进行强制转换:


  1. CAST(x AS typename)
  2. or
  3. x::typename

如何自定义类型转换(CAST)

自定义CAST的语法如下:


  1. CREATE CAST (source_type AS target_type)
  2. WITH FUNCTION function_name [(argument_type [,...])]
  3. [ AS ASSIGNMENT | AS IMPLICIT ]
  4. CREATE CAST (source_type AS target_type)
  5. WITHOUT FUNCTION
  6. [ AS ASSIGNMENT | AS IMPLICIT ]
  7. CREATE CAST (source_type AS target_type)
  8. WITH INOUT
  9. [ AS ASSIGNMENT | AS IMPLICIT ]

解释:

1、WITH FUNCTION,表示转换需要用到什么函数。

2、WITHOUT FUNCTION,表示被转换的两个类型,在数据库的存储中一致,即物理存储一致。例如text和varchar的物理存储一致。不需要转换函数。


  1. Two types can be binary coercible,
  2. which means that the conversion can be performed “for free” without invoking any function.
  3. This requires that corresponding values use the same internal representation.
  4. For instance, the types text and varchar are binary coercible both ways.
  5. Binary coercibility isnot necessarily a symmetric relationship.
  6. For example, the cast from xml to text can be performed for free in the present implementation,
  7. but the reverse direction requires a function that performs at least a syntax check.
  8. (Two types that are binary coercible both ways are also referred to as binary compatible.)

3、WITH INOUT,表示使用内置的IO函数进行转换。每一种类型,都有INPUT 和OUTPUT函数。使用这种方法,好处是不需要重新写转换函数。

除非有特殊需求,我们建议直接使用IO函数来进行转换。


  1. List of functions
  2. Schema|Name|Result data type |Argument data types |Type
  3. ------------+-----------------+------------------+---------------------+--------
  4. pg_catalog | textin | text | cstring | normal
  5. pg_catalog | textout | cstring | text | normal
  6. pg_catalog | date_in | date | cstring | normal
  7. pg_catalog | date_out | cstring | date | normal

  1. You can define a cast as an I/O conversion cast byusing the WITH INOUT syntax.
  2. An I/O conversion cast is performed by invoking the output function of the source data type,
  3. and passing the resulting string to the input function of the target data type.
  4. In many common cases,this feature avoids the need to write a separate cast functionfor conversion.
  5. An I/O conversion cast acts the same as a regular function-based cast; only the implementation is different.

4、AS ASSIGNMENT,表示在赋值时,自动对类型进行转换。例如字段类型为TEXT,输入的类型为INT,那么可以创建一个 cast(int as text) as ASSIGNMENT。


  1. If the cast is marked AS ASSIGNMENT then it can be invoked implicitly when assigning a value to a column of the target data type.
  2. For example, supposing that foo.f1 is a column of type text,then:
  3. INSERT INTO foo (f1) VALUES (42);
  4. will be allowed if the cast from type integer to type text is marked AS ASSIGNMENT,
  5. otherwise not.
  6. (We generally use the term assignment cast to describe this kind of cast.)

5、AS IMPLICIT,表示在表达式中,或者在赋值操作中,都对类型进行自动转换。(包含了AS ASSIGNMENT,它只对赋值进行转换)


  1. If the cast is marked AS IMPLICIT then it can be invoked implicitly in any context,
  2. whether assignment or internally in an expression.
  3. (We generally use the term implicit cast to describe this kind of cast.)
  4. For example, consider this query:
  5. SELECT 2+4.0;
  6. The parser initially marks the constants as being of type integer and numeric respectively.
  7. Thereisno integer + numeric operatorin the system catalogs, but there is a numeric + numeric operator.
  8. The query will therefore succeed if a cast from integer to numeric is available andis marked AS IMPLICIT —
  9. which in fact it is.
  10. The parser will apply the implicit cast and resolve the query asif it had been written
  11. SELECT CAST (2 AS numeric )+4.0;

6、注意,AS IMPLICIT需要谨慎使用,为什么呢?因为操作符会涉及到多个算子,如果有多个转换,目前数据库并不知道应该选择哪个?


  1. Now, the catalogs also provide a cast from numeric to integer.
  2. If that cast were marked AS IMPLICIT —(which it isnot—)
  3. then the parser would be faced with choosing between the above interpretation and
  4. the alternative of casting the numeric constant to integer and applying the integer + integer operator.
  5. Lacking any knowledge of which choice to prefer, it would give up and declare the query ambiguous.
  6. The fact that only one of the two casts isimplicitis the way in which we teach the parser to prefer resolution of
  7. a mixed numeric-and-integer expression as numeric;
  8. there isno built-in knowledge about that.

因此,建议谨慎使用AS IMPLICIT。建议使用AS IMPLICIT的CAST应该是非失真转换转换,例如从INT转换为TEXT,或者int转换为numeric。

而失真转换,不建议使用as implicit,例如numeric转换为int。


  1. Itis wise to be conservative about marking casts asimplicit.
  2. An overabundance of implicit casting paths can cause PostgreSQL to choose surprising interpretations of commands,
  3. or to be unable to resolve commands at all because there are multiple possible interpretations.
  4. A good rule of thumb is to make a cast implicitly invokable only for information-preserving
  5. transformations between types in the same general type category.
  6. For example, the cast from int2 to int4 can reasonably be implicit,
  7. but the cast from float8 to int4 should probably be assignment-only.
  8. Cross-type-category casts, such as text to int4, are best made explicit-only.

注意事项 + 例子

不能嵌套转换。例子

1、将text转换为date

错误方法


  1. create or replace function text_to_date(text) returns date as $$
  2. select cast($1 as date);
  3. $$ language sql strict;
  4. create cast (text as date)withfunction text_to_date(text)asimplicit;

嵌套转换后出现死循环


  1. postgres=#select text '2017-01-01'+1;
  2. ERROR: stack depth limit exceeded
  3. HINT:Increase the configuration parameter "max_stack_depth"(currently 2048kB), after ensuring the platform's stack depth limit is adequate.
  4. CONTEXT: SQL function "text_to_date" during startup
  5. SQL function "text_to_date" statement 1
  6. SQL function "text_to_date" statement 1
  7. SQL function "text_to_date" statement 1
  8. ......

正确方法


  1. create or replace function text_to_date(text) returns date as $$
  2. select to_date($1,'yyyy-mm-dd');
  3. $$ language sql strict;
  4. create cast (text as date)withfunction text_to_date(text)asimplicit;

  1. postgres=#select text '2017-01-01'+1;
  2. ?column?
  3. ------------
  4. 2017-01-02
  5. (1 row)

我们还可以直接使用IO函数来转换:


  1. postgres=# create cast (text as date)with inout asimplicit;
  2. CREATE CAST
  3. postgres=#select text '2017-01-01'+1;
  4. ?column?
  5. ------------
  6. 2017-01-02
  7. (1 row)

参考

https://www.postgresql.org/docs/10/static/sql-createcast.html

本文为云栖社区原创内容,未经允许不得转载,如需转载请发送邮件至yqeditor@list.alibaba-inc.com;如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:yqgroup@service.aliyun.com 进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。

PostgreSQL 自定义自动类型转换(CAST)的更多相关文章

  1. C++程序设计方法3:自动类型转换

    方法1:在源类中定义目标类型转换运算符 #include <iostream> using namespace std; class Dst { public: Dst() { cout ...

  2. 第17课-数据库开发及ado.net 聚合函数,模糊查询like,通配符.空值处理.order by排序.分组group by-having.类型转换-cast,Convert.union all; Select 列 into 新表;字符串函数;日期函数

    第17课-数据库开发及ado.net 聚合函数,模糊查询like,通配符.空值处理.order by排序.分组group by-having.类型转换-cast,Convert.union all;  ...

  3. QVariant类及QVariant与自定义数据类型转换的方法

    这个类型相当于是Java里面的Object,它把绝大多数Qt提供的数据类型都封装起来,起到一个数据类型“擦除”的作用.比如我们的 table单元格可以是string,也可以是int,也可以是一个颜色值 ...

  4. Java自动类型转换

    ■ 自动类型转换:容量小的数据类型可以自动转换为容量大的数据类型. ■ 特例:可以讲整型常量直接赋给byte,short,char等类型变量,而不需要强制类型转换,只要不超出其表数范围. ■ 强制类型 ...

  5. BeanUtils中的自动类型转换(二)

    javabean package entity; import java.util.Date; /** * 一个测试用: * student,javaBean * @author mzy * 一个标准 ...

  6. JavaScript系列文章:自动类型转换-续

    在上一篇文章中,我们详细讲解了JavaScript中的自动类型转换,由于篇幅限制,没能覆盖到所有的转换规则,这次准备详细讲解一下. 上次我们提到了对象类型参与运算时转换规则: 1). 在逻辑环境中执行 ...

  7. JavaScript系列文章:自动类型转换

    我们都知道,JavaScript是类型松散型语言,在声明一个变量时,我们是无法明确声明其类型的,变量的类型是根据其实际值来决定的,而且在运行期间,我们可以随时改变这个变量的值和类型,另外,变量在运行期 ...

  8. struts基于ognl的自动类型转换需要注意的地方

    好吧,坎坷的过程我就不说了,直接上结论: 在struts2中使用基于ognl的自动类型转换时,Action中的对象属性必须同时添加get/set方法. 例如: 客户端表单: <s:form ac ...

  9. postgresql 关闭自动提交

    1. 简介说明             我们知道oracle中sqlplus里面执行dml语句:是需要提交commit:若错了:也可以回滚rollback: 然而在postgresql里面默认是自动提 ...

随机推荐

  1. Andorid Studio中运行模拟器--夜神模拟器

    这样可以直接在夜神模拟器上运行app然后在androidstudio上查看log…. 1.下载夜神模拟器 2.修改配置 点击右上角的设置图标,对夜神模拟器的分辨率进行选择,手机版的480×800的就差 ...

  2. 如何正确使用QThread

    如何正确使用QThread https://www.2cto.com/kf/201609/550462.html

  3. 代码统计工具-cloc

    官网地址:http://cloc.sourceforge.net/ https://sourceforge.NET/projects/cloc/files/ 下载得到cloc-1.64.exe Clo ...

  4. Vue(三) v-bind 及 class 与 style 绑定

    DOM 元素经常会动态绑定一些 class 类名 或 style 样式,现在介绍使用 v-bind 指令来绑定 class 和 style 的多种方法. 了解 v-bind 指令 在之前已经介绍了指令 ...

  5. linux c使用socket进行http 通信,并接收任意大小的http响应(五)

    http.c data2.c http_url.c http.h data2.h http_url.h主要实现的功能是通过URL结构体来实现HTTP通信,你可以把这三个文件独立出来,作为HTTP通信模 ...

  6. python之路--面向对象(三)

    一 isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象.由于Python中一切都是类,所以 ...

  7. [Codeforces613E]Puzzle Lover

    Problem 给你2*n的格子,每个格子有一个字母,从任意一点出发,不重复的经过上下左右,生成要求的字符串.问有几种不同的走法. Solution 分三段,左U型.中间.右U型. 分别枚举左边和右边 ...

  8. 脚本自动部署及监控 web

    1.编写脚本自动部署反向代理.web.nfs: I.部署nginx反向代理两个web服务,调度算法使用加权轮询 II.所有web服务使用共享存储nfs,保证所有web都对其有读写权限,保证数据一致性: ...

  9. 福大软工 · BETA 版冲刺前准备(团队)

    BETA 版冲刺前准备 队名:第三视角 作业链接 组长博客 应作业要求为了更加顺利地开展beta版本的冲刺,上次的alpha版本展示后,我们组对之前开发过程中存在的各种问题进行了全面的讨论,并对其进行 ...

  10. 查看selinux与关闭方法

    查看当前用户selinux 状态 [root@o- ~]# getenforce Disabled [root@o- ~]# setenforce usage: setenforce [ Enforc ...