一、錯誤案例
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/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。