PostgreSQL 自定义自动类型转换(CAST)
转载自:https://yq.aliyun.com/articles/228271
背景
PostgreSQL是一个强类型数据库,因此你输入的变量、常量是什么类型,是强绑定的,例如
在调用操作符时,需要通过操作符边上的数据类型,选择对应的操作符。
在调用函数时,需要根据输入的类型,选择对应的函数。
如果类型不匹配,就会报操作符不存在,或者函数不存在的错误。
- postgres=#select'1'+'1';
- ERROR:operatorisnot unique: unknown + unknown
- LINE 1:select'1'+'1';
- ^
- HINT:Couldnot choose a best candidate operator.You might need to add explicit type casts.
那么使用起来是不是很不方便呢?
PostgreSQL开放了类型转换的接口,同时也内置了很多的自动类型转换。来简化操作。
查看目前已有的类型转换:
- postgres=# \dC+
- List of casts
- Source type |Target type |Function|Implicit?|Description
- -----------------------------+-----------------------------+--------------------+---------------+-------------
- "char"| character | bpchar |in assignment |
- "char"| character varying | text |in assignment |
- "char"| integer | int4 |no|
- "char"| text | text | yes |
- abstime | date | date |in assignment |
- abstime | integer |(binary coercible)|no|
- abstime | time without time zone | time |in assignment |
- ................................
- timestamp without time zone | timestamp with time zone | timestamptz | yes |
- timestamp without time zone | timestamp without time zone | timestamp | yes |
- xml | character |(binary coercible)|in assignment |
- xml | character varying |(binary coercible)|in assignment |
- xml | text |(binary coercible)|in assignment |
- (246 rows)
如果你发现有些类型转换没有内置,怎么办呢?我们可以自定义转换。
当然你也可以使用这种语法,对类型进行强制转换:
- CAST(x AS typename)
- or
- x::typename
如何自定义类型转换(CAST)
自定义CAST的语法如下:
- CREATE CAST (source_type AS target_type)
- WITH FUNCTION function_name [(argument_type [,...])]
- [ AS ASSIGNMENT | AS IMPLICIT ]
- CREATE CAST (source_type AS target_type)
- WITHOUT FUNCTION
- [ AS ASSIGNMENT | AS IMPLICIT ]
- CREATE CAST (source_type AS target_type)
- WITH INOUT
- [ AS ASSIGNMENT | AS IMPLICIT ]
解释:
1、WITH FUNCTION,表示转换需要用到什么函数。
2、WITHOUT FUNCTION,表示被转换的两个类型,在数据库的存储中一致,即物理存储一致。例如text和varchar的物理存储一致。不需要转换函数。
- Two types can be binary coercible,
- which means that the conversion can be performed “for free” without invoking any function.
- This requires that corresponding values use the same internal representation.
- For instance, the types text and varchar are binary coercible both ways.
- Binary coercibility isnot necessarily a symmetric relationship.
- For example, the cast from xml to text can be performed for free in the present implementation,
- but the reverse direction requires a function that performs at least a syntax check.
- (Two types that are binary coercible both ways are also referred to as binary compatible.)
3、WITH INOUT,表示使用内置的IO函数进行转换。每一种类型,都有INPUT 和OUTPUT函数。使用这种方法,好处是不需要重新写转换函数。
除非有特殊需求,我们建议直接使用IO函数来进行转换。
- List of functions
- Schema|Name|Result data type |Argument data types |Type
- ------------+-----------------+------------------+---------------------+--------
- pg_catalog | textin | text | cstring | normal
- pg_catalog | textout | cstring | text | normal
- pg_catalog | date_in | date | cstring | normal
- pg_catalog | date_out | cstring | date | normal
- You can define a cast as an I/O conversion cast byusing the WITH INOUT syntax.
- An I/O conversion cast is performed by invoking the output function of the source data type,
- and passing the resulting string to the input function of the target data type.
- In many common cases,this feature avoids the need to write a separate cast functionfor conversion.
- 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。
- 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.
- For example, supposing that foo.f1 is a column of type text,then:
- INSERT INTO foo (f1) VALUES (42);
- will be allowed if the cast from type integer to type text is marked AS ASSIGNMENT,
- otherwise not.
- (We generally use the term assignment cast to describe this kind of cast.)
5、AS IMPLICIT,表示在表达式中,或者在赋值操作中,都对类型进行自动转换。(包含了AS ASSIGNMENT,它只对赋值进行转换)
- If the cast is marked AS IMPLICIT then it can be invoked implicitly in any context,
- whether assignment or internally in an expression.
- (We generally use the term implicit cast to describe this kind of cast.)
- For example, consider this query:
- SELECT 2+4.0;
- The parser initially marks the constants as being of type integer and numeric respectively.
- Thereisno integer + numeric operatorin the system catalogs, but there is a numeric + numeric operator.
- The query will therefore succeed if a cast from integer to numeric is available andis marked AS IMPLICIT —
- which in fact it is.
- The parser will apply the implicit cast and resolve the query asif it had been written
- SELECT CAST (2 AS numeric )+4.0;
6、注意,AS IMPLICIT需要谨慎使用,为什么呢?因为操作符会涉及到多个算子,如果有多个转换,目前数据库并不知道应该选择哪个?
- Now, the catalogs also provide a cast from numeric to integer.
- If that cast were marked AS IMPLICIT —(which it isnot—)
- then the parser would be faced with choosing between the above interpretation and
- the alternative of casting the numeric constant to integer and applying the integer + integer operator.
- Lacking any knowledge of which choice to prefer, it would give up and declare the query ambiguous.
- The fact that only one of the two casts isimplicitis the way in which we teach the parser to prefer resolution of
- a mixed numeric-and-integer expression as numeric;
- there isno built-in knowledge about that.
因此,建议谨慎使用AS IMPLICIT。建议使用AS IMPLICIT的CAST应该是非失真转换转换,例如从INT转换为TEXT,或者int转换为numeric。
而失真转换,不建议使用as implicit,例如numeric转换为int。
- Itis wise to be conservative about marking casts asimplicit.
- An overabundance of implicit casting paths can cause PostgreSQL to choose surprising interpretations of commands,
- or to be unable to resolve commands at all because there are multiple possible interpretations.
- A good rule of thumb is to make a cast implicitly invokable only for information-preserving
- transformations between types in the same general type category.
- For example, the cast from int2 to int4 can reasonably be implicit,
- but the cast from float8 to int4 should probably be assignment-only.
- Cross-type-category casts, such as text to int4, are best made explicit-only.
注意事项 + 例子
不能嵌套转换。例子
1、将text转换为date
错误方法
- create or replace function text_to_date(text) returns date as $$
- select cast($1 as date);
- $$ language sql strict;
- create cast (text as date)withfunction text_to_date(text)asimplicit;
嵌套转换后出现死循环
- postgres=#select text '2017-01-01'+1;
- ERROR: stack depth limit exceeded
- HINT:Increase the configuration parameter "max_stack_depth"(currently 2048kB), after ensuring the platform's stack depth limit is adequate.
- CONTEXT: SQL function "text_to_date" during startup
- SQL function "text_to_date" statement 1
- SQL function "text_to_date" statement 1
- SQL function "text_to_date" statement 1
- ......
正确方法
- create or replace function text_to_date(text) returns date as $$
- select to_date($1,'yyyy-mm-dd');
- $$ language sql strict;
- create cast (text as date)withfunction text_to_date(text)asimplicit;
- postgres=#select text '2017-01-01'+1;
- ?column?
- ------------
- 2017-01-02
- (1 row)
我们还可以直接使用IO函数来转换:
- postgres=# create cast (text as date)with inout asimplicit;
- CREATE CAST
- postgres=#select text '2017-01-01'+1;
- ?column?
- ------------
- 2017-01-02
- (1 row)
参考
https://www.postgresql.org/docs/10/static/sql-createcast.html
PostgreSQL 自定义自动类型转换(CAST)的更多相关文章
- C++程序设计方法3:自动类型转换
方法1:在源类中定义目标类型转换运算符 #include <iostream> using namespace std; class Dst { public: Dst() { cout ...
- 第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; ...
- QVariant类及QVariant与自定义数据类型转换的方法
这个类型相当于是Java里面的Object,它把绝大多数Qt提供的数据类型都封装起来,起到一个数据类型“擦除”的作用.比如我们的 table单元格可以是string,也可以是int,也可以是一个颜色值 ...
- Java自动类型转换
■ 自动类型转换:容量小的数据类型可以自动转换为容量大的数据类型. ■ 特例:可以讲整型常量直接赋给byte,short,char等类型变量,而不需要强制类型转换,只要不超出其表数范围. ■ 强制类型 ...
- BeanUtils中的自动类型转换(二)
javabean package entity; import java.util.Date; /** * 一个测试用: * student,javaBean * @author mzy * 一个标准 ...
- JavaScript系列文章:自动类型转换-续
在上一篇文章中,我们详细讲解了JavaScript中的自动类型转换,由于篇幅限制,没能覆盖到所有的转换规则,这次准备详细讲解一下. 上次我们提到了对象类型参与运算时转换规则: 1). 在逻辑环境中执行 ...
- JavaScript系列文章:自动类型转换
我们都知道,JavaScript是类型松散型语言,在声明一个变量时,我们是无法明确声明其类型的,变量的类型是根据其实际值来决定的,而且在运行期间,我们可以随时改变这个变量的值和类型,另外,变量在运行期 ...
- struts基于ognl的自动类型转换需要注意的地方
好吧,坎坷的过程我就不说了,直接上结论: 在struts2中使用基于ognl的自动类型转换时,Action中的对象属性必须同时添加get/set方法. 例如: 客户端表单: <s:form ac ...
- postgresql 关闭自动提交
1. 简介说明 我们知道oracle中sqlplus里面执行dml语句:是需要提交commit:若错了:也可以回滚rollback: 然而在postgresql里面默认是自动提 ...
随机推荐
- Andorid Studio中运行模拟器--夜神模拟器
这样可以直接在夜神模拟器上运行app然后在androidstudio上查看log…. 1.下载夜神模拟器 2.修改配置 点击右上角的设置图标,对夜神模拟器的分辨率进行选择,手机版的480×800的就差 ...
- 如何正确使用QThread
如何正确使用QThread https://www.2cto.com/kf/201609/550462.html
- 代码统计工具-cloc
官网地址:http://cloc.sourceforge.net/ https://sourceforge.NET/projects/cloc/files/ 下载得到cloc-1.64.exe Clo ...
- Vue(三) v-bind 及 class 与 style 绑定
DOM 元素经常会动态绑定一些 class 类名 或 style 样式,现在介绍使用 v-bind 指令来绑定 class 和 style 的多种方法. 了解 v-bind 指令 在之前已经介绍了指令 ...
- linux c使用socket进行http 通信,并接收任意大小的http响应(五)
http.c data2.c http_url.c http.h data2.h http_url.h主要实现的功能是通过URL结构体来实现HTTP通信,你可以把这三个文件独立出来,作为HTTP通信模 ...
- python之路--面向对象(三)
一 isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象.由于Python中一切都是类,所以 ...
- [Codeforces613E]Puzzle Lover
Problem 给你2*n的格子,每个格子有一个字母,从任意一点出发,不重复的经过上下左右,生成要求的字符串.问有几种不同的走法. Solution 分三段,左U型.中间.右U型. 分别枚举左边和右边 ...
- 脚本自动部署及监控 web
1.编写脚本自动部署反向代理.web.nfs: I.部署nginx反向代理两个web服务,调度算法使用加权轮询 II.所有web服务使用共享存储nfs,保证所有web都对其有读写权限,保证数据一致性: ...
- 福大软工 · BETA 版冲刺前准备(团队)
BETA 版冲刺前准备 队名:第三视角 作业链接 组长博客 应作业要求为了更加顺利地开展beta版本的冲刺,上次的alpha版本展示后,我们组对之前开发过程中存在的各种问题进行了全面的讨论,并对其进行 ...
- 查看selinux与关闭方法
查看当前用户selinux 状态 [root@o- ~]# getenforce Disabled [root@o- ~]# setenforce usage: setenforce [ Enforc ...