我创建了一个不可变函数,如下所示:
CREATE OR REPLACE FUNCTION GetCurrentDate()
RETURNS DATE
AS $p$
BEGIN
RETURN CURRENT_TIMESTAMP::DATE;
END;
$p$ LANGUAGE plpgsql IMMUTABLE SECURITY DEFINER;
我在 UNIQUE INDEX 的 WHERE 子句中使用它,例如:
CREATE UNIQUE INDEX PersonPhoness_UK_PhoneNo_CountryID
ON person_phones (phone_no, country_id)
WHERE GetCurrentDate()
BETWEEN effective_from_date AND effective_till_date;
添加另一行时,此唯一索引有时不会捕获重复项。
新添加行的
effective_from_dt
始终为 CURRENT_DATE
。但是,如果我将函数更改为:,它就会起作用
CREATE OR REPLACE FUNCTION GetCurrentDate()
RETURNS DATE
AS $p$
BEGIN
RETURN CURRENT_DATE;
END
$p$;
所以我想了解其中的区别。
第一个版本有点慢:
CURRENT_TIMESTAMP
伪函数没有任何影响,所以它是无用的。不过虽然没什么用,但是却有一个开销。也许如果函数的所有者与应用程序用户是同一用户,则上下文不会更改。但出于安全原因,这是错误的配置。所以两个函数返回相同的结果,但首先做了一些无用的操作,然后应该会慢一点。
当您想要“重命名”内置函数时,最好是使用 SQL 语言来代替函数。这是零开销。为任何 PL/pgSQL 函数的任何执行启动 PL/pgSQL 运行时都会产生一些开销:
所以
CREATE OR REPLACE FUNCTION GetCurrentDate()
RETURNS DATE
AS $$ SELECT CURRENT_DATE $$
LANGUAGE SQL STABLE;
更好。它内联在查询中(未执行),因此开销为零。
在 PL/pgsql 中,我们以两种方式 CAST 数据。
Cast()
功能:CAST(value as cast_data_type)
::
) : value::cast_data_type
所以,当你写下类似的内容时:
CURRENT_TIMESTAMP::DATE
cast(CURRENT_TIMESTAMP as DATE)
现在我们知道默认的
CURRENT_TIMESTAMP
格式是 YYYY-MM-DD hh:mm:ss.nnnnnn+/-tz
和 CURRENT_DATE
格式是 YYYY-MM-DD
。
那么,你告诉我什么需要更多时间? @JitendraLoyal
CURRENT_TIMESTAMP::DATE
和 CURRENT_DATE
的效果完全相同。 CURRENT_TIMESTAMP::DATE
比首先获得
timestamptz
然后强制它到
date
有点慢 - 这是毫无意义的绕道。任一表达式都只是
STABLE
,而不是
IMMUTABLE
,因为任一表达式都取决于执行会话的
timezone
设置。
关于您的索引CURRENT_DATE
(或任何返回时间点的函数)在索引定义中没有任何意义。按照您的方式,一行将在某一天进入部分索引,但在另一天则不会。任意后果...显然,Postgres 不允许这样做。
索引定义中使用的所有函数和运算符都必须是 “不可变”,也就是说,它们的结果必须仅取决于它们的 争论并且绝不受任何外部影响(例如 另一张桌子或当前时间)。这一限制确保了 索引的行为是明确定义的。使用用户定义的函数 在索引表达式或
WHERE
子句中,请记住标记 创建函数时它是不可变的。
粗体强调我的。当试图违反该规则时,CREATE INDEX
会回答:
错误:索引谓词中的函数必须标记为 IMMUTABLE您想使用
IMMUTABLE
函数包装来强制执行您的破碎概念。仅当事实确实如此时才这样做。或者当你确切地知道自己在用善意的谎言做什么时。你的谎言不是善意的。每当会话使用不同的
timezone
设置运行时,您(可以)在同一时间点获得不同的
date
,并且会发生任意事情。在您真正意识到功能损坏之前,这种情况可能会持续很长时间。所以你有两个级别的破损。幸运的是,不久之后它就浮出了水面。您在一个函数定义中看到错误,而在另一个函数定义中没有看到错误,这纯粹是巧合。要么都是疯子。请原谅我的法语。
首先用简单的英语
准确地定义您的要求。然后寻找合适的工具来实施......
旁白