PostgreSQL -如何在函数触发器中设置临时变量,以便以后用于INSERT INTO?[已关闭]

1rhkuytd  于 2022-12-18  发布在  PostgreSQL
关注(0)|答案(1)|浏览(136)

**已关闭。**此问题为not reproducible or was caused by typos。当前不接受答案。

这个问题是由错字或无法再重现的问题引起的。虽然类似的问题在这里可能是on-topic,但这个问题的解决方式不太可能帮助未来的读者。
6天前关闭。
Improve this question
我对PostgreSQL还很陌生,我想我可以从社区的帮助中受益,我正在努力让这个概念发挥作用。
它所要做的就是在数据不存在的情况下将数据插入维表中,然后返回维ID以供以后使用。错误属于CASE语句,因为我还想根据是否存在错误为success分配一个布尔值。(编辑:这里,当我说“错误”时,我指的是数据中的一个字段)。
我得到的错误声明time_stamp不存在。我以为我读到INSERT INTO RETURNING INTO会隐式创建一个临时表。看起来我一定是误解了。有人能帮我找到正确的逻辑吗?谢谢!

CREATE OR REPLACE FUNCTION distribute_process_data() RETURNS TRIGGER AS 
$BODY$ 
BEGIN
    select CURRENT_TIMESTAMP() into time_stamp;

    INSERT INTO
        sources(source, category)
        VALUES(NEW.source, NEW.category) ON CONFLICT (source) DO NOTHING
        RETURNING id INTO source_id;

    INSERT INTO
        mediums(sources_id, medium)
        VALUES(source_id, NEW.medium) ON CONFLICT (sources_id, medium) DO NOTHING
        RETURNING id INTO medium_id;

    INSERT INTO
        countries(country)
        VALUES(NEW.country) ON CONFLICT (country) DO NOTHING
        RETURNING id INTO country_id;

    INSERT INTO
        requests(sources_id, request)
        VALUES(source_id, NEW.request) ON CONFLICT (request) DO NOTHING
        RETURNING id INTO request_id;

    CASE
        WHEN NEW.error IS NOT NULL THEN
            INSERT INTO
                errors(timestamp, processes_id, error)
                VALUES(time_stamp, NEW.id, error)
                RETURNING id INTO error_id;
            select FALSE INTO success;
        ELSE
            select NULL INTO error_id;
            select TRUE INTO success;
    END CASE;

    INSERT INTO
        processes(
            id, timestamp, requests_id, errors_id, sources_id, mediums_id, countries_id, successful,
            date, web_visits, conversions, ad_impressions, ad_clicks, ad_cost, site1_ad_visits,
            site2_ad_visits, site1_ad_visits_bounce_rate, downloads_desktop, downloads_mobile,
            initiated_registrations, completed_registrations, paid_users, revenue
        )
        VALUES(
            NEW.id, time_stamp, request_id, error_id, medium_id, country_id, success,
            NEW.date, NEW.web_visits, NEW.conversions, NEW.ad_impressions, NEW.ad_clicks, NEW.ad_cost,
            NEW.site1_ad_visits, NEW.site2_ad_visits, NEW.site1_ad_visits_bounce_rate, 
            NEW.downloads_desktop, NEW.downloads_mobile, NEW.initiated_registrations, NEW.completed_registrations, 
            NEW.paid_users, NEW.revenue
        )

    RETURN new;

END;
$BODY$ language plpgsql;

我试着使用提供的代码。它不起作用,声明我的“变量”不存在。我期待它同谋创建它们。
值得一提的是,我更喜欢可读性而不是速度,因为我还是一个新用户,将负责维护代码。

lymnna71

lymnna711#

除了表或会话变量之外,没有其他方法可以将变量存储在触发器之外,这些变量既昂贵又危险。另一方面,临时表非常方便,也是临时文件的常见用法。
对于大型服务器来说,存储成本几乎每次都比该高速缓存成本低,大型服务器通常在查询是否应该使用缓存以及何时使用缓存方面有大量的工程工作。
一个例子是动态SQL用于查询,不得到执行多次,而不是静态查询,使用该高速缓存所有的时间,一旦达到postgres缓存限制以前缓存查询得到重新索引和数据库变得非常慢,动态SQL在另一方面执行没有缓存,更慢,并负担得起的正确情况.
您可以在之前尝试使用信息模式对表结构进行一些验证

IF SELECT column_name FROM information_schema.columns WHERE table_name ='countries' AND table_schema='public' IS NULL THEN
    EXECUTE 'ALTER TABLE countries ADD column'|| **column_name** ||' TIMESTAMP; '
ELSE
    EXECUTE  'INSERT INTO countries ('||column_name||') VALUES( now() )';
END IF;

由于动态SQL以外的对象不存在,因此没有其他方法可以无错误地操作结果。
还有另一种方法,你可以使用返回语法来实现更容易,性能和动态使用WITH,下面的代码是可能的插入结果避免声明唯一的变量,还绑定进程到彼此的结果:

WITH query1 AS (
    SELECT 'val' AS var ),
query2 AS (
    INSERT INTO test (name) SELECT query1.var FROM query1 RETURNING id 
),
query3 AS (
    DELETE FROM test WHERE id = (SELECT query2.id FROM query2 )
)
    SELECT * FROM query1 ;

相关问题