PostgreSQL整型int與布林boolean的自動轉換設定(含自定義cast與cast規則介紹)
標籤
PostgreSQL , cast , 資料型別轉換 , 自動型別轉換 , 隱式轉換 , 顯示轉換 , 整型 , 布林 , int , boolean
背景
在使用資料庫時,經常會遇到一些因為客戶端輸入的型別與資料庫定義的型別不匹配導致的錯誤問題。
例如資料庫定義的是布林型別,而輸入的是整型:
postgres=# create table cas_test(id int, c1 boolean);
CREATE TABLE
postgres=# set VERBOSITY verbose
postgres=# insert into cas_test values (1, int `1`);
ERROR: 42804: column "c1" is of type boolean but expression is of type integer
LINE 1: insert into cas_test values (1, int `1`);
^
HINT: You will need to rewrite or cast the expression.
LOCATION: transformAssignedExpr, parse_target.c:591
又或者資料庫定義的是時間,使用者輸入的是字串:
postgres=# create table tbl123(id int, crt_time timestamp);
CREATE TABLE
postgres=# insert into tbl123 values (1, text `2017-01-01 10:00:00`);
ERROR: column "crt_time" is of type timestamp without time zone but expression is of type text
LINE 1: insert into tbl123 values (1, text `2017-01-01 10:00:00`);
^
HINT: You will need to rewrite or cast the expression.
從錯誤提示來看,資料庫已經很清晰的告訴你為什麼了。那麼怎麼讓資料庫自動轉換呢?
PostgreSQL有一個語法,支援資料型別的轉換(賦值、引數、表示式 等位置的自動轉換)。
postgres=# h create cast
Command: CREATE CAST
Description: define a new cast
Syntax:
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 ]
資料庫內建了很多轉換法則:
postgres=# dC
List of casts
Source type | Target type | Function | Implicit?
-----------------------------+-----------------------------+---------------------------+---------------
abstime | date | date | in assignment
abstime | integer | (binary coercible) | no
abstime | timestamp without time zone | timestamp | yes
........
integer | boolean | bool | no
型別的自動轉換實際上也是有一定的規則的,例如 賦值、引數 算是兩種規則。具體含義見如下文件:
我們看到整型轉布林是有內建的轉換規則的,那麼為什麼沒有自動轉呢?
postgres=# dC
List of casts
Source type | Target type | Function | Implicit?
-----------------------------+-----------------------------+---------------------------+---------------
integer | boolean | bool | no
和自動轉換的規則有關,no表示不會自動轉換,只有當我們強制指定轉換時,才會觸發轉換的動作:
postgres=# select cast ((int `1`) as boolean);
bool
------
t
(1 row)
pg_cast裡面的context轉換為可讀的內容(e表示no, a表示assignment, 否則表示implicit)
如果讓資料庫賦值時自動將字串轉換為時間,自動將整型轉換為布林
1、如果資料庫已經內建了轉換規則,那麼可以通過更新系統表的方式,修改自動轉換規則。
例如,將這個INT轉BOOLEAN的規則,修改為assignment的規則。
postgres=# update pg_cast set castcontext=`a` where castsource =`integer`::regtype and casttarget=`boolean`::regtype;
UPDATE 1
修改後,我們再檢視這個轉換規則,就變成這樣了
dC
List of casts
Source type | Target type | Function | Implicit?
-----------------------------+-----------------------------+---------------------------+---------------
integer | boolean | bool | in assignment
現在你可以將int自動寫入為BOOLEAN了。
postgres=# create table cas_test(id int, c1 boolean);
CREATE TABLE
postgres=# insert into cas_test values (1, int `1`);
INSERT 0 1
2、如果系統中沒有兩種型別轉換的CAST規則,那麼我們需要自定義一個。
例如
postgres=# create cast (text as timestamp) with inout as ASSIGNMENT;
CREATE CAST
List of casts
Source type | Target type | Function | Implicit?
-----------------------------+-----------------------------+---------------------------+---------------
text | timestamp without time zone | (binary coercible) | in assignment
這樣就可以自動將TEXT轉換為TIMESTAMP了。
postgres=# insert into tbl123 values (1, text `2017-01-01 10:00:00`);
INSERT 0 1
postgres=# select * from tbl123;
id | crt_time
----+---------------------
1 | 2017-01-01 10:00:00
(1 row)
刪掉這個轉換,就會報錯。
postgres=# drop cast (text as timestamp);
DROP CAST
postgres=# insert into tbl123 values (1, text `2017-01-01 10:00:00`);
ERROR: column "crt_time" is of type timestamp without time zone but expression is of type text
LINE 1: insert into tbl123 values (1, text `2017-01-01 10:00:00`);
^
HINT: You will need to rewrite or cast the expression.
3、如果沒有內建的轉換函式,我們可能需要自定義轉換函式來支援這種轉換。
例子
自定義一個函式,用於輸入TEXT,返回TIMESTAMPTZ
postgres=# 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 ;
CREATE FUNCTION
建立規則
postgres=# create cast (text as timestamptz) with function cast_text_to_timestamp as ASSIGNMENT;
CREATE CAST
postgres=# dC
List of casts
Source type | Target type | Function | Implicit?
-----------------------------+-----------------------------+---------------------------+---------------
text | timestamp with time zone | cast_text_to_timestamp | in assignment
現在,輸入TEXT,就可以自定轉換為timestamptz了。
postgres=# create table tbl1234(id int, crt_time timestamptz);
CREATE TABLE
postgres=# insert into tbl1234 values (1, text `2017-01-01 10:10:10`);
INSERT 0 1
當然,這些型別實際上內部都有內部的儲存格式,大多數時候,如果儲存格式通用,就可以直接使用INOUT來轉換,不需要寫轉換函式。
僅僅當兩種型別在資料庫的內部儲存格式不一樣的時候,需要顯示的寫函式來轉換。
參考
相關文章
- PostgreSQL自定義自動型別轉換(CAST)SQL型別AST
- 型別轉換(cast)型別AST
- JAVA int 強制型別轉換錯誤提示(Cannot cast from Object to int)Java型別ASTObject
- C++強制型別轉換:static_cast、dynamic_cast、const_cast、reinterpret_castC++型別AST
- Golang 型別轉換庫 castGolang型別AST
- static_cast與dynamic_cast到底是什麼?AST
- C++中dynamic_cast與static_cast淺析與例項演示C++AST
- java基礎:型別轉換castJava型別AST
- C++中型別轉換static_castC++型別AST
- MySQL CAST與CONVERT 函式的用法MySqlAST函式
- 自定義Mybatis自動生成程式碼規則MyBatis
- Golang:cast安全且易用的型別轉換工具GolangAST型別
- C++之static_cast,dynamic_cast,const_castC++AST
- 7.41 CASTAST
- c++ static_cast顯式型別轉換C++AST型別
- [C++]變數宣告與定義的規則C++變數
- C 語言之布林型別介紹型別
- reinterpret_cast 和 static_cast 的區別AST
- C++ 型別轉換詳解 -- const_castC++型別AST
- javascript型別系統——布林Boolean型別JavaScript型別Boolean
- Oracle中CAST函式使用簡介OracleAST函式
- teradata CASTAST
- oracle cast 用法OracleAST
- dynamic_castAST
- (轉)Go 每日一庫之 castGoAST
- Oracle的Cast的用法OracleAST
- PostgreSQL整型相除規範SQL
- SMART原則的定義和含義
- Laravel 自定義規則Laravel
- 利用Sonar定製自定義掃描規則
- Laravel 自動轉換長整型雪花 ID 為字串Laravel字串
- GIS中的座標系定義與轉換 (轉)
- C++中static_cast, dynamic_cast, const_cast用法/使用情況及區別解析C++AST
- 關於hextoraw()與utl_raw.cast_to_raw及rawtohex()AST
- Python基本資料型別:布林型別(Boolean)Python資料型別Boolean
- SQL中的cast()函式SQLAST函式
- const_cast的用法AST
- mysql的varchar(N)和int(N)的含義及其與char區別MySql