如何将文本字段转换为数字字段和空非数字值?

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