使用SQL函数而不是SELECT函数的优点

使用SQL函数而不是SELECT函数的优点,sql,postgresql,Sql,Postgresql,在Postgresql 9.0数据库中,我可以使用WHERE子句中的整数(profile_id)为带有SELECT语句的网页创建url 在过去,我只是在方便的时候进行选择,例如在视图中将子查询用作列/字段。但是我最近意识到我可以创建一个SQL函数来做同样的事情。(这是一个SQL函数,不是plpgsql) 我想知道在这种情况下,使用函数而不是选择函数是否有一个优势,主要是在花费的资源方面?请参阅下文,并提前感谢。我在这个网站的其他地方找不到关于这个话题的任何东西。(长时间阅读,第一次来电) 函数如

在Postgresql 9.0数据库中,我可以使用WHERE子句中的整数(profile_id)为带有SELECT语句的网页创建url

在过去,我只是在方便的时候进行选择,例如在视图中将子查询用作列/字段。但是我最近意识到我可以创建一个SQL函数来做同样的事情。(这是一个SQL函数,不是plpgsql)

我想知道在这种情况下,使用函数而不是选择函数是否有一个优势,主要是在花费的资源方面?请参阅下文,并提前感谢。我在这个网站的其他地方找不到关于这个话题的任何东西。(长时间阅读,第一次来电)

函数如下所示

CREATE OR REPLACE FUNCTION msurl(integer)
RETURNS text AS
$BODY$    
SELECT (('https://www.thenameofmywebsite/'::text || 
    CASE
        WHEN prof.type = 1 THEN 'm'::text
        ELSE 'f'::text
    END) || '/handler/'::text) || prof.profile_id AS profile_url
FROM profile prof
WHERE prof.profile_id = $1;
$BODY$
LANGUAGE sql
要获取我的url,我可以使用

SELECT prof.name,     
SELECT (('https://www.thenameofmywebsite/'::text || 
    CASE
        WHEN prof.type = 1 THEN 'm'::text
        ELSE 'f'::text
    END) || '/handler/'::text) || prof.profile_id AS profile_url, prof.start_date
FROM profile prof, 
WHERE prof.profile_id = id_number;
或者更整洁的版本:

SELECT prof.name, msurl(id_number) as profile_url, prof.start_date FROM profile prof;

函数的意义(sql函数)是封装。对于函数,SQL语句的某些片段具有名称、语义——您可以重用它,也可以构建一个库。没有任何其他好处,比如性能—它只会影响代码的可读性。

您使用该函数的方式不会有任何优势—相反,它会大大降低您的选择速度。因为对于从主
select
语句(调用函数的语句)检索到的每一行,您都在同一个表上运行另一个select

当您想要封装构建url的逻辑时,函数确实具有优势。但您需要以不同的方式编写函数,以便通过将要使用的行传递给它来提高效率:

CREATE OR REPLACE FUNCTION msurl(profile)
RETURNS text AS
$BODY$    
SELECT (('https://www.thenameofmywebsite/' || 
    CASE
        WHEN $1.type = 1 THEN 'm'
        ELSE 'f'
    END) || '/handler/' || $1.profile_id:: AS profile_url;
$BODY$
LANGUAGE sql;
另一个选项是分别传递您需要的所有列,但是通过传递行(类型),如果逻辑发生变化,并且您需要表中更多或更少的列,则不需要更改函数签名(以及对它的调用)

然后,您可以使用以下语法调用它:

SELECT prof.name, 
       msurl( (prof) ) as profile_url, 
       prof.start_date 
FROM profile prof;
请注意,将别名传递给函数时,必须将其括在括号中
(prof)
。此处的附加括号不是可选的

这样,函数仍然会为每一行调用,但它不会在
profile
表上运行另一个select

由于Postgres以面向对象的方式处理此类函数,您甚至可以将其作为表的一列来调用:

SELECT prof.name, 
       prof.msurl as profile_url, 
       prof.start_date 
FROM profile prof;

在本例中,由于对结果中的每一行都进行了额外的选择,该函数将对性能产生重大影响。它可以使用STABLE标志内联,但注释中有一个true。最好只编写标量SQL函数而不使用完整的内部选择