如何将文本字段转换为数字字段和空非数字值?
How to convert text field to numeric field and null non-numeric values?
我有一列文本数据,其中包含一堆不同的值...其中许多是数字,但其他不是。
我想将此文本列转换为数字列,并将任何值转换为可以成功完成的数字,但将所有无法转换的文本值设为 NULL。
是否可以在单个 alter table 语句中实现?
更改 table schema_1."tbl_265" 更改列 field_7 输入数字
首先需要设置一个pl/pgsql函数similar to this(因为类型转换的异常无法在纯SQL中处理),但是,是的,转换为数字可以在单个语句中执行无效数字输入的空值。
testdb=# create table t as select '12.34' as c union all select 'asdf';
SELECT 2
testdb=# \pset null .
Null display is ".".
testdb=# create function is_valid_numeric(text) returns boolean language plpgsql immutable as $$
begin
return case when ::numeric is null then false else true end;
exception when others then
return false;
end;$$;
CREATE FUNCTION
testdb=# alter table t alter column c type numeric using case when is_valid_numeric(c) then c::numeric else null end;
ALTER TABLE
testdb=# select * from t;
c
-------
12.34
.
(2 rows)
您也可以尝试使用某种正则表达式测试而不是函数,但总会有一些边缘情况;确保您不会遇到故障的唯一方法是使用 pl/pgsql 函数实际执行转换并处理可能产生的异常。
我认为您无法在一条语句中做到这一点。 Postgres 将尝试将列中的每个值转换为数字,如果无法完成则引发错误,这将中止整个操作。
相反,您可以:
创建一个数据类型为 numeric
的新列
用转换后的值填充它 - 为此,更简洁的方法是创建一个临时转换函数
删除旧字符串列
重命名新的数字列
这里是a demo
-- sample table
create table mytable(id int primary key, col text);
insert into mytable(id, col) values
(1, '123.5'),
(2, 'abc'),
(3, null)
;
-- conversion function
create or replace function cast_to_numeric(v_input text)
returns numeric as $$
declare v_output numeric default null;
begin
begin
v_output := v_input::numeric;
exception when others then return null;
end;
return v_output;
end;
$$ language plpgsql;
-- add a new column and fill it with converted values
alter table mytable add column newcol numeric;
update mytable set newcol = cast_to_numeric(col);
-- swap the columns
alter table mytable drop column col;
alter table mytable rename column newcol to col;
-- check the results
select * from mytable
id | col
-: | ----:
1 | 123.5
2 | null
3 | null
我有一列文本数据,其中包含一堆不同的值...其中许多是数字,但其他不是。
我想将此文本列转换为数字列,并将任何值转换为可以成功完成的数字,但将所有无法转换的文本值设为 NULL。
是否可以在单个 alter table 语句中实现?
更改 table schema_1."tbl_265" 更改列 field_7 输入数字
首先需要设置一个pl/pgsql函数similar to this(因为类型转换的异常无法在纯SQL中处理),但是,是的,转换为数字可以在单个语句中执行无效数字输入的空值。
testdb=# create table t as select '12.34' as c union all select 'asdf';
SELECT 2
testdb=# \pset null .
Null display is ".".
testdb=# create function is_valid_numeric(text) returns boolean language plpgsql immutable as $$
begin
return case when ::numeric is null then false else true end;
exception when others then
return false;
end;$$;
CREATE FUNCTION
testdb=# alter table t alter column c type numeric using case when is_valid_numeric(c) then c::numeric else null end;
ALTER TABLE
testdb=# select * from t;
c
-------
12.34
.
(2 rows)
您也可以尝试使用某种正则表达式测试而不是函数,但总会有一些边缘情况;确保您不会遇到故障的唯一方法是使用 pl/pgsql 函数实际执行转换并处理可能产生的异常。
我认为您无法在一条语句中做到这一点。 Postgres 将尝试将列中的每个值转换为数字,如果无法完成则引发错误,这将中止整个操作。
相反,您可以:
创建一个数据类型为
numeric
的新列用转换后的值填充它 - 为此,更简洁的方法是创建一个临时转换函数
删除旧字符串列
重命名新的数字列
这里是a demo
-- sample table
create table mytable(id int primary key, col text);
insert into mytable(id, col) values
(1, '123.5'),
(2, 'abc'),
(3, null)
;
-- conversion function
create or replace function cast_to_numeric(v_input text)
returns numeric as $$
declare v_output numeric default null;
begin
begin
v_output := v_input::numeric;
exception when others then return null;
end;
return v_output;
end;
$$ language plpgsql;
-- add a new column and fill it with converted values
alter table mytable add column newcol numeric;
update mytable set newcol = cast_to_numeric(col);
-- swap the columns
alter table mytable drop column col;
alter table mytable rename column newcol to col;
-- check the results
select * from mytable
id | col -: | ----: 1 | 123.5 2 | null 3 | null