Postgresql

我無法理解 SQL / TimeScaleDB 中的語法錯誤問題

  • June 29, 2022

這不會編譯:

SELECT add_compression_policy(
   hypertable => 'exchange.candles',
   compress_after => INTERVAL ((SELECT now()::DATE::timestamp - (SELECT min(last_ts) FROM exchange.capture_tracker))),
   if_not_exists => TRUE);

問題似乎SELECT如下INTERVAL

但這編譯:

WITH delay AS (SELECT now()::DATE::timestamp - (SELECT min(last_ts) FROM exchange.capture_tracker) myinterval)
SELECT add_compression_policy(
   hypertable => 'exchange.candles',
   compress_after => myinterval,
   if_not_exists => TRUE) FROM delay;

我的同事和我不明白為什麼。

誰能解釋一下?

解釋

功能 interval()並沒有按照您的想法執行。您可以使用這樣的類型名稱來轉換一個值(類型化或非類型化):

test=> SELECT interval '5 days 20:32:32.06';
     interval      
--------------------
5 days 20:32:32.06

但是您不能將其用作函式(後跟括號)。這僅適用於一些基本類型。看:

在 Postgres 14 中註冊了兩個名為“interval”的函式,一個取,time另一個取. 不是你想要的:interval``integer

test=> SELECT (proargtypes::regtype[])[:] FROM pg_proc WHERE proname = 'interval';
       proargtypes         
----------------------------
{"time without time zone"}
{interval,integer}

你似乎想要一個演員表,但你不需要一開始,因為你複雜的表達的結果interval已經是。

解決方案

解開:

SELECT add_compression_policy(hypertable     => 'exchange.candles'
                           , compress_after => (SELECT current_date - min(last_ts) FROM exchange.capture_tracker)
                           , if_not_exists  => TRUE);

now()::DATE::timestamp燒到CURRENT_DATE. 後者是date代替timestamp,但表達式的結果是一樣的。(取決於timezone您目前會話的設置。)

或者,更簡單:

SELECT add_compression_policy(hypertable     => 'exchange.candles'
                           , compress_after => current_date - min(last_ts)
                           , if_not_exists  => TRUE)
FROM   exchange.capture_tracker;

由於對錶的唯一引用是min(last_ts),因此即使表為空,它也始終返回單行。結果與上述相同。

引用自:https://dba.stackexchange.com/questions/313897