首页 > 解决方案 > PostgreSQL 中内联 SQL 函数调度的解决方法

问题描述

目标

我正在尝试让 PostgreSQL 执行诸如函数调度之类的操作,但我愿意接受任何其他解决方案来解决这个问题,因为我希望它是内联。

假设我有两个功能,例如:

create or replace function is_in_view_one(p people) returns boolean as $$
  select p.state = ANY(ARRAY['TX', 'NY', 'CA'])
$$ language sql strict stable;

和:

create or replace function is_in_view_two(p people) returns boolean as $$
  select p.state = ANY(ARRAY['NV', 'FL', 'MT'])
$$ language sql strict stable;

我希望能够写一些代码,或者改编上面的函数,所以我可以写:

select count(*)
from people
where is_in_view(people, 'one');

我想is_in_view根据这些标准完全内联:https://wiki.postgresql.org/wiki/Inlining_of_SQL_functions'

通过域尝试的解决方案

我尝试建立一个使用域作为函数标识符的解决方案,虽然它不起作用,但我认为对 PostgreSQL 类型、强制转换和函数识别更了解的人可能知道如何破解它。

我试着做:

create domain view_one_id as uuid check (value = 'ed744964-6561-11eb-878e-c7ad77d3260a');
create domain view_two_id as uuid check (value = 'fa9fe0f8-6561-11eb-878e-c79c81b46d0c');

create or replace function say_n(v view_one_id) returns integer as $$
  select 1 
$$ language sql strict;

create or replace function say_n(v view_two_id) returns integer as $$
  select 2 
$$ language sql strict;

希望我能做到:

select say_n('ed744964-6561-11eb-878e-c7ad77d3260a') # 1
select say_n('fa9fe0f8-6561-11eb-878e-c79c81b46d0c') # 2

但相反,我得到:

=# select say_n('fa9fe0f8-6561-11eb-878e-c79c81b46d0c');
ERROR:  function say_n(unknown) is not unique
LINE 1: select say_n('fa9fe0f8-6561-11eb-878e-c79c81b46d0c');
               ^
HINT:  Could not choose a best candidate function. You might need to add explicit type casts.

我可以:

=# select say_n('fa9fe0f8-6561-11eb-878e-c79c81b46d0c'::view_two_id);
 say_n 
-------
     2
(1 row)

但是为了与知道如何调用函数并且只调用函数(不提供变量类型转换)的外部工具集成,我对不需要修改此外部工具的解决方案抱有希望。

乐于接受替代品!但是,我觉得这个解决方案可能通过摆弄 theCAST或其他东西来实现。

标签: postgresql

解决方案


如何使用CASE

select p.state = ANY (CASE WHEN $2 = 'one'
                           THEN ARRAY['TX', 'NY', 'CA']
                           ELSE ARRAY['NV', 'FL', 'MT']
                      END)

但是如果你想要效率,你会更好地使用这两个函数,因为上面不能使用索引。


推荐阅读