Postgresql更新特定字符的列函数

时间:2018-01-02 21:53:33

标签: postgresql

我想创建一个更新列并从列中替换特定值的函数。

例如我有一个像

这样的列
  

' 187-2026-00130740 167'

第一个数字187和最后一个数字167是随机数。使用函数我将它们与声明的变量一起使用然后更新并从列中删除它们。

_colid从表中获取所有id作为数组。然后在该数组中预先获取第一个和最后一个数字。之后我用空白更新了这些数字。

我的功能基本上就是这样。

CREATE OR REPLACE FUNCTION fix() RETURNS integer as $$
Declare _colid varchar[] := (SELECT '{{' || string_agg(concat_ws(',',id), '},{') || '}}' as a
FROM News n);
Declare _newsslice varchar[];
Declare _firstnumber varchar;
Declare _lastnumber varchar;
BEGIN
FOREACH _newsslice SLICE 1 IN ARRAY _colid 
LOOP
_firstnumber := (select regexp_replace(substring(split_part(token, '-', 1)from '[0-9]+'), '\s+$', '') AS x FROM news where id = _newsslice[1]::int and length(split_part(token, '-', 1)) < 4);

_lastnumber :=(select regexp_replace(substring(regexp_replace(token, '^. ', '')from '[0-9]+'), '\s+$', ' ') from news where id = _newsslice[1]::int and length(regexp_replace(substring(regexp_replace(token, '^. ', '')from '[0-9]+'), '\s+$', ' ')) < 4);

IF(_firstnumber IS NOT NULL) THEN
  update news set token = regexp_replace(regexp_replace(regexp_replace(trim(from token, ' ', ''),_colnumber,''),_firstnumber , '') where id = _newsslice[1]::int;
END IF;
END LOOP;
RETURN 1;
END; $$
LANGUAGE plpgsql;

这会根据需要更新和删除第一个号码。但是没有删除最后一个号码。我该怎么做,我该怎么做呢?

1 个答案:

答案 0 :(得分:0)

使用SQL而不是函数可以更好地解决这个问题。

update news
set
    token = substring(token from position('-' in token) + 1)
where
    position('-' in token) <= 4;

update news
set
    token = substring(token from 1 for (length(token) - 4 + position(' ' in substring(token from length(token) - 3)))) 
where
    position(' ' in substring(token from length(token) - 3)) > 0;

此解决方案假定:

  • 令牌可能有前缀或后缀,或两者兼而有之。
  • 前缀最多3位数后跟连字符
  • 后缀是一个空格,后跟最多3位数字

我从你的描述和代码中得到了这个。如果例如所有前缀正好是3位数,则实际要求可能更简单。

如果必须将前缀和后缀检查为数字,则可以添加,仍然使用SQL。

SQL解决方案更好,因为:

  • 更短更简单
  • 它避免了我们都犯错误的循环边界条件(我也是)
  • 它会跑得更快

知道你要处理多少行会很有趣。

我倾向于根据需要使用标记创建一个新表,在旧旧表之间进行一些比较,然后删除旧表并重命名新表。这也可能比进行大量更新更快。如果你确实使用了更新方法,请确保之后真空。

我的测试数据是:

create table news
(
    id        int,
    token     varchar(32)
);

insert into news (id, token) values (1, '187-2026-00130740 167');
insert into news (id, token) values (2, '18-2026-00130740 167');
insert into news (id, token) values (3, '1-2026-00130740 167');
insert into news (id, token) values (4, '-2026-00130740 167');
insert into news (id, token) values (5, '2026-00130740 167');
insert into news (id, token) values (6, '187-2026-00130740 16');
insert into news (id, token) values (7, '187-2026-00130740 1');
insert into news (id, token) values (8, '187-2026-00130740 ');
insert into news (id, token) values (9, '187-2026-00130740');

结果是:

 id |     token      
----+----------------
  9 | 2026-00130740
  5 | 2026-00130740 
  1 | 2026-00130740 
  2 | 2026-00130740 
  3 | 2026-00130740 
  4 | 2026-00130740 
  6 | 2026-00130740 
  7 | 2026-00130740 
  8 | 2026-00130740 
(9 rows)