【问题标题】:macro-like function as filter in postgresql类似宏的函数作为 postgresql 中的过滤器
【发布时间】:2012-12-02 14:21:03
【问题描述】:

我有一个表,里面有一些 RDF 语句,比如Quads(graph, subject, verb, object),我发现自己在做这样的查询:

select * from quads where verb = 'rdf:type' and object = 'smtg:Type'
select * from quads where verb = 'rdf:label' and object = 'bla bla'

我想以这样的形式表达这一点

select * from quads where type('smtg:Type')
select * from quads where label('bla bla')

虽然这似乎是一个“微不足道的”文本替换,但我不知道如何以及是否可以在 postgresql 中实现,尽管我有点认为这是不可能的。

据我所知,我可以使用函数对常量进行硬编码,然后

select * from quads where rdftype() = verb and object = 'smtg:Type'

或者我可以使用函数作为from 参数,例如

select * from typed('smtg:Type')

遗憾的是,前者相当冗长,而后者似乎无法修改为组合,例如我不能做一个假设

select * from quads where type('smtg:Type') and inGraph('mygraph')

有没有办法做我想做的事?这似乎不可能,但我想知道有没有办法。

编辑:一个 sqlfiddle 实例:http://sqlfiddle.com/#!1/40b2c/3

更清楚地说,这似乎不可行的原因是宏函数将返回一个布尔值(它在where 子句中使用,就好像它在select $1=somevalue 的位置一样)但使用“隐式”行参数,它将一次访问多个字段,我在 pg 文档中没有看到这样的例子。

【问题讨论】:

  • 我看不出为什么不能在 PL/pgSQL 函数中完成。但可以肯定的是,我们需要更多信息。请发布确切的表结构(如create table...)和一些示例数据(如insert into ...),您可以在sqlfiddle.com发布带有前两个语句的工作副本
  • 如果 verb 在功能上依赖于 object,那么您应该删除冗余列并规范化您的架构。 verb 上的附加条件在object 上的条件旁边是多余的。如果verb 不能object 推导出来,那么仍然不清楚你如何解决type('#Person')。一般来说,您几乎可以在 plpgsql 中做任何事情。当您遇到无法用普通 SQL 解决的问题时,请在 plpgsql 函数中生成 动态 SQL。在 SO 上搜索 [plpgsql] EXECUTEdynamic-sql 以获取更多信息。
  • verb 在功能上不依赖于对象。我不明白你所说的“解决”是什么意思,很抱歉,type('#Person') 将等同于 verb_and_object_equals_to('type', '#Person') 固定一个参数。

标签: function postgresql database stored-functions


【解决方案1】:

并且后者 [function] 似乎不能修改为组合,例如一世 不能做假设

只要返回类型稳定,您几乎可以在 plpgsql 函数中执行任何操作。

您没有透露如何解决type('smtg:Type')inGraph('mygraph') - 这些应该是函数吗?返回..什么?
但是对于像这样的简单情况,即使是普通的 SQL 函数也应该可以完成这项工作:

CREATE OR REPLACE FUNCTION f_foo (_type text, _graph text DEFAULT NULL)
  RETURNS SETOF quads AS
$func$
   SELECT *
   FROM   quads
   WHERE  CASE WHEN $1 IS NOT NULL THEN ... ELSE ... END
   AND    CASE WHEN $2 IS NOT NULL THEN ... ELSE ... END
   ORDER  BY ...;
$func$  LANGUAGE sql;

在 PostgreSQL 9.2 或更高版本中,您还可以在 SQL 函数中使用参数名称而不是位置参数($1$2、..)。

呼叫:

由于我为第二个参数定义了一个DEFAULT,你可以用一个两个参数调用这个函数:

SELECT * FROM f_foo('smtg:Type');

或者:

SELECT * FROM f_foo('smtg:Type', 'mygraph');

【讨论】:

  • 感谢您的回答,我已经用参数/返回值的更多细节更新了这个问题。正如我所写,集合/表返回函数似乎不可组合,我基本上必须在其中预先编写所有可能的谓词组合。
猜你喜欢
  • 2020-01-09
  • 1970-01-01
  • 2020-03-14
  • 1970-01-01
  • 2012-03-15
  • 2013-02-08
  • 1970-01-01
  • 1970-01-01
  • 2016-12-14
相关资源
最近更新 更多