postgresql 自動類型轉換


一、錯誤案例

1、賦值錯誤:

ERROR druid.sql.Statement:149 - {conn-10005, pstmt-20005} execute error. UPDATE sys_permission SET parent_id=?  is_leaf=?  internal_or_external=? WHERE id=?

org.postgresql.util.PSQLException: 錯誤: 字段 "is_leaf" 的類型為 integer, 但表達式的類型為 boolean     建議:你需要重寫或轉換表達式  位置:126

解決方法:

update pg_cast set castcontext='a' where castsource ='boolean'::regtype and casttarget='integer'::regtype;  

2、查詢錯誤:

ERROR druid.sql.Statement:149 - {conn-10005, pstmt-20003} execute error. SELECT * FROM QRTZ_FIRED_TRIGGERS WHERE SCHED_NAME = 'quartzScheduler' AND INSTANCE_NAME = ? AND REQUESTS_RECOVERY = ?
org.postgresql.util.PSQLException: 錯誤: 操作符不存在: character varying = boolean
建議:沒有匹配指定名稱和參數類型的操作符. 您也許需要增加明確的類型轉換.

解決方法:

update pg_cast set castcontext='i' where castsource ='boolean'::regtype and casttarget='text'::regtype;
update pg_cast set castcontext='i' where castsource ='boolean'::regtype and casttarget='character'::regtype;
update pg_cast set castcontext='i' where castsource ='boolean'::regtype and casttarget='character varying'::regtype;

用該方法之后應該可以執行轉換了,但是有可能把true轉換成"true"存到數據庫中,這個時候,就需要用實例2的方法

二、知識點總結

PostgreSQL 數據類型直接有3種轉換,隱式轉換,賦值轉換,顯式轉換;對應的轉換類型存在系統表 pg_cast中
三種方式分別對應 i(Implicit),a(Assignment),e(Explicit)

查詢所有轉換:

select castsource::regtype,casttarget::regtype,castcontext,castfunc from pg_cast where castsource='boolean'::regtype;   

三者的轉換關系為 i > a > e;意思是可以隱式轉換的一定可以賦值轉換和顯式轉換;可以賦值轉換的一定可以顯式轉換

可以顯式轉換的不能隱式轉換和賦值轉換。i:主要用戶表達式和賦值,a主要用於賦值。

https://github.com/TheFrancisHe/Postgresql/blob/master/Postgresql%E4%B8%AD%E7%9A%84%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2%26%26pg_cast.md

https://github.com/digoal/blog/blob/master/201801/20180131_01.md

相關文章:

https://blog.csdn.net/qq_39727113/article/details/105371412

三、pg_cast中有的可以進行update,如果沒有的可以create新的cast

實例1:自動將TEXT轉換為TIMESTAMP

   如果沒有內置的轉換函數,我們可能需要自定義轉換函數來支持這種轉換。(如果不需要轉換函數:WITHOUT FUNCTION)

--創建轉換fun
create or replace function cast_text_to_timestamp(text) returns timestamptz as $$  
  select to_timestamp($1, 'yyyy-mm-dd hh24:mi:ss');  
$$ language sql strict ;  

--創建cast規則
create cast (text as timestamptz) with function cast_text_to_timestamp as ASSIGNMENT;

--使用cast進行操作
insert into tbl123 values (1, text '2017-01-01 10:00:00');

 實例2、自動將boolean轉成text類型

//創建fun
create or replace function bool_to_character(boolean) returns text as $$        
  select CAST($1::int as text);
$$ language sql strict;

--這行創建cast會報錯:類型 boolean 到 text 的轉換已經存在,因此只能用update
create  cast (bool as text) with function bool_to_character(boolean) as implicit; 


--更新cast(3種text類型都要處理),先找fun的id,然后再找casttarget
update pg_cast set castcontext='i',castfunc=42127 where castsource ='boolean'::regtype and casttarget='text'::regtype;

--查詢casttarget
select castsource::regtype,casttarget::regtype,castcontext,castfunc from pg_cast where castsource='boolean'::regtype;

--根據fun查詢id:
SELECT oid,proname FROM pg_proc WHERE proname='bool_to_character'

四、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的物理存儲一致。不需要轉換函數。

3、WITH INOUT,表示使用內置的IO函數進行轉換。每一種類型,都有INPUT 和OUTPUT函數。使用這種方法,好處是不需要重新寫轉換函數。

除非有特殊需求,我們建議直接使用IO函數來進行轉換。

4、AS ASSIGNMENT,表示在賦值時,自動對類型進行轉換。例如字段類型為TEXT,輸入的類型為INT,那么可以創建一個 cast(int as text) as ASSIGNMENT。

5、AS IMPLICIT,表示在表達式中,或者在賦值操作中,都對類型進行自動轉換。(包含了AS ASSIGNMENT,它只對賦值進行轉換)

6、注意,AS IMPLICIT需要謹慎使用,為什么呢?因為操作符會涉及到多個算子,如果有多個轉換,目前數據庫並不知道應該選擇哪個?

因此,建議謹慎使用AS IMPLICIT。建議使用AS IMPLICIT的CAST應該是非失真轉換轉換,例如從INT轉換為TEXT,或者int轉換為numeric。

而失真轉換,不建議使用as implicit,例如numeric轉換為int。

本文參考文章:https://www.jb51.net/article/203366.htm


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM