我试图创建一个使文本列均匀化的函数。在函数的情况下,它是一系列regex_replaces。
我相信以下(缩短的)代码应该给我解决方案:
CREATE OR REPLACE FUNCTION clean_data(address_token text) RETURNS
setof text
AS
$$
BEGIN
return case when address_token like '%allee' OR address_token LIKE '%ally' OR address_token LIKE '%aly' then regexp_replace(address_token,'(allee|ally|aly)$', 'alley')
when address_token like '%annex' OR address_token LIKE '%annx' OR address_token LIKE '%anx' then regexp_replace(address_token,'(annex$|annx$|anx$)', 'anex')
when address_token like '%arc' then regexp_replace(address_token ,'arc$', 'arcade')
.
.
.
when address_token like '%wls' then regexp_replace(address_token ,'wls$', 'wells') else address_token;
END;
$$ LANGUAGE plpgsql;
CREATE TABLE newtable AS
select postcode, (clean_data(address1)) as address1 (clean_data(address2)) as address2, (clean_data(address3)) as address3
from oldtable where postcode SIMILAR TO '(a|b)%';
但是当我运行它时,我收到错误消息:
RETURN cannot have a parameter in function returning set
LINE 5: return case when address_token like '%allee' OR address_to...
^
HINT: Use RETURN NEXT or RETURN QUERY.
当我接受其建议并使用' RETURN QUERY'相反,我告诉:
syntax error at or near "case"
LINE 5: return query case when address_token like '%allee' OR addr...
我找不到很有帮助。
编写此函数的正确方法是什么?
我对SQL函数比较新,并且我不是100%肯定:
过去几个小时我一直在谷歌搜索,进展甚微,获得的理解很少,所以任何帮助都会受到赞赏
答案 0 :(得分:1)
关键错误是setof返回多行数据:你的函数一次只能操作一行,所以应该只返回text
。您已将此标记为plpgsql,但由于它只有一个语句,因此它与SQL一样好用:SQL中不需要BEGIN
和END
语句,而您将select
而不是return
结果。虽然您的CASE
语句很长,但这仍然是一个简单的函数,其中一个输入和一个输出为in the docs。
第二个错误是您错过了END
语句的CASE
:您需要结束案例,然后结束plpgsql函数,这样您就会有双端。
CREATE OR REPLACE FUNCTION clean_data(address_token text) RETURNS text
AS
$$
BEGIN
return case when address_token like '%allee' OR address_token LIKE '%ally' OR address_token LIKE '%aly' then regexp_replace(address_token,'(allee|ally|aly)$', 'alley')
.
.
.
when address_token like '%wls' then regexp_replace(address_token ,'wls$', 'wells') else address_token
end;
END;
$$ LANGUAGE plpgsql;
答案 1 :(得分:0)
PostgreSQL手册说:
可以声明SQL函数返回一个集合(即多行) 通过将函数的返回类型指定为SETOF sometype,或 等效地将其声明为RETURNS TABLE(列)
因此,您使用setof返回rows
。在您的情况下,您将返回一个'字段'。所以你应该将你的回报改为RETURNS TEXT
(没有setof),或者如果你需要一个表,你应该将你的案例输出设置成一个记录或行。
答案 2 :(得分:0)
为什么要干扰案例表达。只需按原样使用你的regexp_replace函数,它们已经在你的case语句中体现了谓词。
更好的是将表达式放入表中并循环遍历它们:
PostgreSQL 9.3架构设置:
MAILCHIMP_V3_API_URL/campaigns
查询1 :
create table samples(address_token text);
create table replacements(exp varchar(30), value varchar(30), flags varchar(10));
INSERT INTO samples
(address_token)
VALUES
('DB Ally'),
('SQL Annex'),
('Penny Arc'),
('CPU Wls')
;
INSERT INTO replacements
(exp, value, flags)
VALUES
('(allee|ally|aly)$', 'alley', 'i'),
('(annex$|annx$|anx$)', 'anex', 'i'),
('arc$', 'arcade', 'i'),
('wls$', 'wells', 'i')
;
create or replace function clean_data(address_token text) returns text
as
$$
DECLARE
r record;
result text;
BEGIN
result := address_token;
for r in (select exp, value, flags from replacements) loop
result := regexp_replace(result, r.exp, r.value, r.flags);
end loop;
return result;
end;
$$ LANGUAGE plpgsql;
/
<强> Results 强>:
select * from replacements
查询2 :
| exp | value | flags |
|---------------------|--------|-------|
| (allee|ally|aly)$ | alley | i |
| (annex$|annx$|anx$) | anex | i |
| arc$ | arcade | i |
| wls$ | wells | i |
<强> Results 强>:
select address_token, clean_data(address_token) new_val
from samples