CURRENT_TIMESTAMP::DATE 和 CURRENT_DATE 有什么区别?

问题描述 投票:0回答:3

我创建了一个不可变函数,如下所示:

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$;

所以我想了解其中的区别。

postgresql indexing plpgsql volatility
3个回答
0
投票

第一个版本有点慢:

  1. 执行强制转换时间戳 -> 日期
  2. 将执行上下文从当前用户切换到函数所有者。上下文对
    CURRENT_TIMESTAMP
    伪函数没有任何影响,所以它是无用的。不过虽然没什么用,但是却有一个开销。也许如果函数的所有者与应用程序用户是同一用户,则上下文不会更改。但出于安全原因,这是错误的配置。

所以两个函数返回相同的结果,但首先做了一些无用的操作,然后应该会慢一点。

当您想要“重命名”内置函数时,最好是使用 SQL 语言来代替函数。这是零开销。为任何 PL/pgSQL 函数的任何执行启动 PL/pgSQL 运行时都会产生一些开销:

所以

CREATE OR REPLACE FUNCTION GetCurrentDate()
RETURNS DATE
AS $$ SELECT CURRENT_DATE $$
LANGUAGE SQL STABLE;

更好。它内联在查询中(未执行),因此开销为零。


0
投票

在 PL/pgsql 中,我们以两种方式 CAST 数据。

  1. 使用
    Cast()
    功能:
    CAST(value as cast_data_type)
  2. 使用演员运算符 (
    ::
    ) :
    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

供参考:

Pl/pgSQL 类型转换


0
投票

回答板块中的问题

CURRENT_TIMESTAMP::DATE
CURRENT_DATE
的效果完全相同。 CURRENT_TIMESTAMP::DATE
 比首先获得 
timestamptz
 然后强制它到 
date
 有点慢 - 这是毫无意义的绕道。任一表达式都只是 
STABLE
,而不是 
IMMUTABLE
,因为任一表达式都取决于执行会话的 
timezone
 设置。

关于您的索引

整个方法完全是无稽之谈。

CURRENT_DATE

(或任何返回时间点的函数)在索引定义中没有任何意义。按照您的方式,一行将在某一天进入部分索引,但在另一天则不会。任意后果...

显然,Postgres 不允许这样做。

说明书:

索引定义中使用的所有函数和运算符都必须是 “不可变”,也就是说,它们的结果必须仅取决于它们的 争论并且

绝不受任何外部影响(例如 另一张桌子或当前时间)。这一限制确保了 索引的行为是明确定义的。使用用户定义的函数 在索引表达式或 WHERE

 子句中,请记住标记
创建函数时它是不可变的。

粗体强调我的。当试图违反该规则时,CREATE INDEX

 会回答:

错误:索引谓词中的函数必须标记为 IMMUTABLE

您想使用

IMMUTABLE

 函数包装来强制执行您的破碎概念。仅当事实确实如此时才这样做。或者当你确切地知道自己在用善意的谎言做什么时。

你的谎言不是善意的。每当会话使用不同的

timezone

 设置运行时,您(可以)在同一时间点获得不同的 
date
,并且会发生任意事情。在您真正意识到功能损坏之前,这种情况可能会持续很长时间。

所以你有两个级别的破损。幸运的是,不久之后它就浮出了水面。您在一个函数定义中看到错误,而在另一个函数定义中没有看到错误,这纯粹是巧合。要么都是疯子。请原谅我的法语。

首先用简单的英语

准确地定义您的要求。然后寻找合适的工具来实施......

旁白

  • SECURITY DEFINER

    对此完全没用。只会增加成本和可能的安全隐患,而没有任何收益。

  • 尽可能避免混合大小写的标识符。参见:

    • PostgreSQL 列名区分大小写吗?
  • 如果没有语言声明,您问题中的第二个函数定义是不完整的。如果没有

    波动性标签IMMUTABLE

    ,它一开始就不会被
    CREATE INDEX
    接受。

© www.soinside.com 2019 - 2024. All rights reserved.