我在Stackoverflow的第一篇文章。我正试图“在职”学习Postgresql(12),似乎被一个相当简单的问题卡住了。我有一个12行的简单数据库。在一列(int)中有一个4位数字[代表一年]。我试图创建一个生成的always列,它取CurrentDate,减去前面提到的int列,得到一个Age(int)。
我错过了什么。肯定有一个简单的解决方案。
谢谢詹姆斯
经过几次失败的尝试,我意识到一个函数应该工作。下面是我创建的简单函数。该函数工作,但似乎返回了多于1行。我只需要Asset_Age generated always列来显示资产的年龄:[inservice是具有4位数的现有int列(例如1963年)]
--Function get_age
CREATE OR REPLACE FUNCTION amp.get_age()
RETURNS int
AS $CODE$
BEGIN
RETURN extract (year from current_date)::int - inservice from amp.amp_pumpstations;
End
$CODE$
LANGUAGE PLPGSQL IMMUTABLE.
--------------
--create generated always column
ALTER TABLE IF EXISTS amp.amp_pumpstations
ADD COLUMN asset_age integer GENERATED ALWAYS AS ((amp.get_age())) STORED;
-------------
ERROR: query "SELECT extract(year from current_date)::int - inservice from amp.amp_pumpstations" returned more than one row
CONTEXT: PL/pgSQL function amp.get_age() line 3 at RETURN
SQL state: 21000
2条答案
按热度按时间wgxvkvu91#
CURRENT_DATE
是STABLE
function (value remains constant in a single statement), you should not use that in anIMMUTABLE
function (function result is always the same for the same function arguments)。它今天可能“工作”,但明年你可能会有问题,因为功能可能已经“优化”了。通过扩展,您不能使用GENERATED ALWAYS
列,因为这需要IMMUTABLE
函数。最重要的是,逻辑是错误的,因为
asset_age
is calculated when the row is inserted in the table or its underlying columns updated,所以随着时间的推移,您的资产年龄去不同步。您可以通过从表中删除列
asset_age
并创建一个在需要时计算值的视图来最轻松地解决这个问题:o0lyfsai2#
这可以使用
RETURN QUERY
完成Demo here