PostgreSQL类型转换问题处理思路

目录

 

概述

1.1问题分类

1.2解决思路

第一类问题:insert引发

第一种:单纯的insert值类型不匹对

第二种:需要对insert值做处理

第二类问题:操作符引发


概述

     在PostgreSQL中,默认在进行数据操作及运算时,需要类型统一才能完美操作。当不同类型之间进行操作时,会产生类型自动兼容问题。下面就来介绍一下错误场景及解决方案。

1.1问题分类

在类型自动兼容问题中,我主要将其分为两大类:

第一类:在进行insert时所产生的问题,一般报错为

 column "col" is of type type1 but expression is of type type2

第二类:是进行运算时所产生的问题,一般报错为

   operator does not exist: type1 = type2

对于不同类问题有不同的解决思路,当然,也存在同一思路就行解决两类相关问题,这个需要大家自己仔细研究一下,就可以摸索出其中的规律。

1.2解决思路

首先排查一下,数据库中是否已经存在转换关系,比如boolean to int

如上,数据库中已存在该转换功能,状态为未启用

查询库中是否存在两种类型的强制转换关系

SELECT OID,castsource , (SELECT typname FROM pg_type WHERE oid = castsource) AS castsourcename ,

casttarget , (SELECT typname FROM pg_type WHERE oid = casttarget) AS casttargetname ,

castfunc , (SELECT proname FROM pg_proc WHERE oid = castfunc ) AS castfuncname,

castcontext ,decode(castcontext::text , 'e'::text , '禁止'::text , 'a'::text , '赋值'::text , 'i'::text , '全部'::text )

FROM pg_cast

WHERE castsource IN( SELECT oid FROM pg_type WHERE typname LIKE '%bool%' )

AND casttarget IN( SELECT oid FROM pg_type WHERE typname LIKE '%int%' );

 

 

  oid  | castsource | castsourcename | casttarget | casttargetname | castfunc | castfuncname | castcontext | decode

-------+------------+----------------+------------+----------------+----------+--------------+-------------+--------

 11299 |         16 | bool           |         23 | int4           |     2558 | int4         | e           | 禁止

(1 行记录)

castsource :源数据类型oid

castsourcename : 源数据类型名称

casttarget : 目标类型oid

casttargetname :目标类型名称

castfunc : 类型转换函数 oid

castfuncname : 类型转换函数名称

castcontext : 该类型转换功能状态标识 e(禁止)、a(赋值)、i(全部,包括赋值)

 

如上,该强制转换状态为禁止,更新已有强制转换关系的状态,修改为赋值

UPDATE pg_cast SET castcontext = 'a' WHERE castsource = 16 AND casttarget = 23;

如果数据库中没有存在相应的强制转换,则需要手动创建,参考如下方法。

 

第一类问题:insert引发

该类问题分两种情况进行解决

第一种:单纯的insert值类型不匹对

问题描述:该类问题可以通过create cast(type1 as type2)解决,比如:column "code" is of type numeric but expression is of type character varying

解决方案:create cast(varchar as numeric) with inout as implicit

示例

db1=# create table t_varchar_to_numeric(id serial,code numeric);

CREATE TABLE

db1=# insert into t_varchar_to_numeric(code) values('123'::varchar);

ERROR:  42804: column "code" is of type numeric but expression is of type character varying

第1行insert into t_varchar_to_numeric(code) values('123'::varchar...

                                             ^

提示:  You will need to rewrite or cast the expression.

db1=# create CAST(varchar as numeric) with inout as implicit;

CREATE CAST

db1=# insert into t_varchar_to_numeric(code) values('123'::varchar);

INSERT 0 1

db1=# select * from t_varchar_to_numeric;

 id | code

----+------

  1 |  123

(1 行记录)

第二种:需要对insert值做处理

问题描述:比如,insert boolean类型的值到numeric类型列中,需要对值进行处理,由于insert时在HighGoDB中默认true值为t,false的值为f,而numeric类型无法直接接收t/f,需要将其处理为1/0。

这个时候我们需要自定义一个类型转换调用的函数,在create cast(boolean as numeric)时指定调用自定义函数进行转换。假设函数为cast_boolean2numeric(boolean)。

解决方案

create or replace function cast_boolean2numeric (boolean) returns numeric as

$$

select decode($1::boolean,'f'::boolean,0::numeric,'t'::boolean,1::numeric,true);

$$

language sql strict;    --自定义转换函数

create cast(boolean as numeric) with function cast_boolean2numeric(boolean) as implicit;

示例

 

db1=# create table t_boolean_to_numeric(id serial,ifcode numeric);

CREATE TABLE

db1=# insert into t_boolean_to_numeric(ifcode) values(true::boolean);

ERROR:  42804: column "ifcode" is of type numeric but expression is of type boolean

第1行insert into t_boolean_to_numeric(ifcode) values(true::boolea...

                                              ^

提示:  You will need to rewrite or cast the expression.

db1=# create or replace function cast_boolean2numeric (boolean) returns numeric as

db1-# $$

db1$# select decode($1::boolean,'f'::boolean,0::numeric,'t'::boolean,1::numeric,true);

db1$# $$

db1-# language sql strict;

CREATE FUNCTION

db1=# create cast(boolean as numeric) with function cast_boolean2numeric(boolean) as implicit;

CREATE CAST

db1=# insert into t_boolean_to_numeric(ifcode) values(true::boolean);

INSERT 0 1

db1=# select * from t_boolean_to_numeric;

 id | ifcode

----+--------

  1 |      1

(1 行记录)

 

如果直接使用解决第一种问题的方式来处理此问题,则报错

db1=# create cast(boolean as numeric) with inout as implicit;

CREATE CAST

db1=# insert into t_boolean_to_numeric(ifcode) values(true::boolean);

ERROR:  22P02: invalid input syntax for type numeric: "t"

 

第二类问题:操作符引发

查看数据库中是否存在操作符

 select oprname,oprleft ,(select typname from pg_type where oid = oprleft) as lefttype,

 oprright,(select typname from pg_type where oid = oprleft) as righttype,oprcode

 from pg_operator

 where oprleft in (select oid from pg_type  where typname like '%char%')

and oprright in (select oid from pg_type  where typname like '%bool%')

and oprname = '=';

 

oprname :操作符名称

oprleft :左参数数据类型

oprright : 右参数数据类型

oprcode : 操作符运算函数名

 

 

问题描述:操作引发的问题就是报某某操作符不存在:operator does not exist: type1 = type2

如:operator does not exist: character = boolean

    解决方案:根据报错的操作符详细信息自定义操作符进行解决(CREATE OPERATOR)。

CREATE FUNCTION char_equal_boolean(char,boolean) RETURNS boolean

      AS $$ SELECT $1::boolean = $2::boolean $$

 LANGUAGE SQL;    --自定义操作符调用的函数

 

CREATE OPERATOR =(

     PROCEDURE = char_equal_boolean,

LEFTARG = char,

RIGHTARG = boolean);

COMMENT ON OPERATOR =( char, boolean) IS ' char equals boolean ';

 

示例

db1=#  select '1'::char = true::boolean;

ERROR:  42883: operator does not exist: character = boolean

第1行select '1'::char = true::boolean;

                      ^

提示:  No operator matches the given name and argument type(s). You might need to add explicit type casts.

db1=# CREATE FUNCTION char_equal_boolean(char,boolean) RETURNS boolean

db1-#       AS $$ SELECT $1::boolean = $2::boolean $$

db1-#  LANGUAGE SQL;

CREATE FUNCTION

db1=# CREATE OPERATOR =(

db1(#   PROCEDURE = char_equal_boolean,

db1(#  LEFTARG = char,

db1(# RIGHTARG = boolean);

CREATE OPERATOR

db1=# COMMENT ON OPERATOR =( char, boolean) IS ' char equals boolean ';

COMMENT

db1=#  select '1'::char = true::boolean;

 ?column?

----------

 t

(1 行记录)

 

 

  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Darion@pg

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值