在使用数据库时,有些应用开发人员可能喜欢使用数值来表示布尔逻辑值,或者在最初定义一个字段的状态时使用的类型,将来不能表达所有的值。
未来则可能需要对字段进行转换,例如数值转换为布尔,或者布尔转换为数值。
还有的时候,一开始可能使用了大量的重复文本,在进行统计时,文本比整型的效率低,在进入仓库后可能需要字典化这些文本(例如APPNAME) , 也会涉及字段类型的转换。
例子:
postgres=# create table tbl(id int, stat numeric(1));
CREATE TABLE
postgres=# insert into tbl select id,0 from generate_series(1,1000) t(id);
INSERT 0 1000
postgres=# insert into tbl select id,1 from generate_series(1001,2000) t(id);
INSERT 0 1000
postgres=# create or replace function n_to_b(numeric) returns boolean as
$$
select $1::int::boolean;
$$
language sql;
CREATE FUNCTION
postgres=# select n_to_b(1);
n_to_b
--------
t
(1 row)
postgres=# select n_to_b(10);
n_to_b
--------
t
(1 row)
postgres=# select n_to_b(0);
n_to_b
--------
f
(1 row)
postgres=# select n_to_b(-1);
n_to_b
--------
t
(1 row)
postgres=# alter table tbl alter column stat type boolean using stat::int::boolean;
ALTER TABLE
postgres=# select * from tbl limit 10;
id | stat
----+------
1 | f
2 | f
3 | f
4 | f
...
字典化
postgres=# create table test(id int, info text);
CREATE TABLE
postgres=# insert into test select id,'string a' from generate_series(1,100000) t(id);
INSERT 0 100000
postgres=# insert into test select id,'string b' from generate_series(1,100000) t(id);
INSERT 0 100000
postgres=# insert into test select id,'string c' from generate_series(1,100000) t(id);
INSERT 0 100000
postgres=# create or replace function fun(text) returns int as
$$
declare
begin
case $1
when 'string a' then return 0;
when 'string b' then return 1;
when 'string c' then return 2;
else return 9999;
end case;
end;
$$
language plpgsql strict;
CREATE FUNCTION
postgres=# select fun('a');
fun
------
9999
(1 row)
postgres=# select fun('string a');
fun
-----
0
(1 row)
postgres=# alter table test alter column info type int using fun(info);
ALTER TABLE
postgres=# select * from test where id=1 limit 5;
id | info
----+------
1 | 0
1 | 1
1 | 2
(3 rows)
还有时,会涉及文本转数值,也可以使用类似的方法:
你可能需要用到to_number或者自定义函数(例如对于带有非数值的字符串,返回一个固定值)
postgres=# select to_number('123ab2','999')
postgres-# ;
to_number
-----------
123
(1 row)
postgres=# select to_number('123ab2','999');
to_number
-----------
123
(1 row)
postgres=# select to_number('1a123ab2','999');
to_number
-----------
11
(1 row)
postgres=# select to_number('1a123ab2','999999999999');
to_number
-----------
11232
(1 row)