PostgreSQL代码超出EXISTS运算符,甚至对于否定条件也是如此

qij5mzcb  于 5个月前  发布在  PostgreSQL
关注(0)|答案(2)|浏览(38)

对于下面的代码,我已经从db中删除了hist.game_hist表。现在,根据下面的代码,我希望我的代码拾取else条件并避免进入then条件(因为game_hist不存在,它将抛出错误)。
但到目前为止,当我尝试运行这段代码时,我得到的错误是,从那时起条件“hist.game_hist不存在”。

SELECT
    pi.*
FROM stg.stg_game pi

WHERE pi.status != '9'

AND pi.hvr_capture_timestamp::timestamp >
    (CASE
        WHEN EXISTS (
            SELECT 1
            FROM information_schema.tables
            WHERE table_schema = 'hist' AND table_name = 'game_hist'
        )
        THEN COALESCE(
            (SELECT max(dbt_updated_at) - INTERVAL '120 minutes' FROM hist.game_hist),
            '1900-01-01'::timestamp
        )
        ELSE '1900-01-01'::timestamp
    end)

字符串
对于上面的代码,我已经从db中删除了hist.game_hist表。现在,根据下面的代码,我希望我的代码拾取else条件并避免进入then条件(因为game_hist不存在,它将抛出错误)。
但到目前为止,当我尝试运行这段代码时,我得到的错误是,从那时起条件“hist.game_hist不存在”。

w6mmgewl

w6mmgewl1#

您面临的问题来自数据库试图在THEN条件下评估子查询,即使表不存在。您可以使用动态SQL来防止这种情况,只有当表存在时才有条件地运行子查询。尝试此更新的代码。此代码只有当表存在时才有条件地使用PL/pgSQL块和动态SQL执行子查询。它立即设置max_dbt_updated_如果未找到表,则将at设置为默认值,以防止出现您遇到的问题。

DO $$ 
DECLARE
    table_exists BOOLEAN;
    max_dbt_updated_at TIMESTAMP;
BEGIN
    -- Check if the table exists
    SELECT EXISTS (
        SELECT 1
        FROM information_schema.tables
        WHERE table_schema = 'hist' AND table_name = 'game_hist'
    ) INTO table_exists;

    -- Use dynamic SQL to conditionally execute the subquery
    IF table_exists THEN
        EXECUTE 'SELECT COALESCE(max(dbt_updated_at) - INTERVAL ''120 minutes'', ''1900-01-01''::timestamp) FROM hist.game_hist'
        INTO max_dbt_updated_at;
    ELSE
        max_dbt_updated_at := '1900-01-01'::timestamp;
    END IF;

    -- Your main query
    SELECT
        pi.*
    FROM stg.stg_game pi
    WHERE pi.status != '9'
    AND pi.hvr_capture_timestamp::timestamp > max_dbt_updated_at;

END $$;

字符串
希望对你有帮助:)

svmlkihl

svmlkihl2#

下面的查询将生成OP所描述的所需结果:

SELECT pi.*
  FROM stg.stg_game pi
  WHERE pi.status != '9'
    AND pi.hvr_capture_timestamp::timestamp > 
        COALESCE((SELECT (XPATH('/table/row/earliest_ts/text()',
                                QUERY_TO_XML(FORMAT($$SELECT MAX(dbt_updated_at) - INTERVAL '120' MINUTE AS earliest_ts FROM %1$I.%2$I$$,
                                                    ist.table_schema,
                                                    ist.table_name),
                                             FALSE,
                                             FALSE,
                                             '')))[1]::text::timestamp
                    FROM information_schema.tables ist
                   WHERE ist.table_schema = 'hist'
                     AND ist.table_name = 'game_hist'), '1900-01-01'::timestamp);

字符串
这种方法利用了QUERY_TO_XML执行动态SQL的能力。因为它是一个SQL查询而不是PL/pgSQL匿名块,所以它可以直接作为更大的SQL查询的一部分使用。如果hist.game_hist不存在,那么infromation_schema.tables子查询中的SELECT列表不会被计算,子查询返回NULL。此查询还避免了重复捕获时间戳比较的默认值。

相关问题