gpt4 book ai didi

Postgresql 创建日志模式

转载 作者:行者123 更新时间:2023-11-29 12:26:33 25 4
gpt4 key购买 nike

所以我的问题很简单。我有一个模式 prod 有很多表,另一个 log 有完全相同的表和结构(主键改变就是这样)。当我在架构 prod 中执行 UPDATEDELETE 时,我想在 log 架构中记录旧数据。

我在更新或删除后调用了以下函数:

CREATE FUNCTION prod.log_data() RETURNS trigger
LANGUAGE plpgsql AS $$
DECLARE
v RECORD;
column_names text;
value_names text;
BEGIN

-- get column names of current table and store the list in a text var
column_names = '';
value_names = '';
FOR v IN SELECT * FROM information_schema.columns WHERE table_name = quote_ident(TG_TABLE_NAME) AND table_schema = quote_ident(TG_TABLE_SCHEMA) LOOP
column_names = column_names || ',' || v.column_name;
value_names = value_names || ',$1.' || v.column_name;
END LOOP;

-- remove first char ','
column_names = substring( column_names FROM 2);
value_names = substring( value_names FROM 2);

-- execute the insert into log schema
EXECUTE 'INSERT INTO log.' || TG_TABLE_NAME || ' ( ' || column_names || ' ) VALUES ( ' || value_names || ' )' USING OLD;

RETURN NULL; -- no need to return, it is executed after update
END;$$;

烦人的部分是我必须从 information_schema 中获取每一行的列名。我宁愿使用这个:

    EXECUTE 'INSERT INTO log.' || TG_TABLE_NAME || ' SELECT ' || OLD;

但是有些值可以是 NULL 所以这将执行:

INSERT INTO log.user SELECT 2,,,"2015-10-28 13:52:44.785947" instead of INSERT INTO log.user SELECT 2,NULL,NULL,"2015-10-28 13:52:44.785947"

有没有办法将 ",," 转换为 ",NULL,"

谢谢

-昆汀

最佳答案

首先,我必须说,在我看来,使用 PostgreSQL 系统表(如 information_schema)是此类用例的正确方法。特别是您必须编写一次:创建函数 prod.log_data() 并完成。此外,由于未指定元素顺序,在该上下文中使用 OLD 可能很危险(就像 * 一样)。

但是

要回答您的确切问题,我知道的唯一方法是对 OLD 进行一些操作。只需观察您通过连接 ... ' SELECT ' || 将 OLD 转换为 text。默认转换会创建丑陋的双逗号。所以,接下来你可以玩那个文本。最后我建议:

DECLARE
tmp TEXT
...
BEGIN
...
/*to make OLD -> text like (2,,3,4,,)*/
SELECT '' || OLD INTO tmp; /*step 1*/

/*take care of commas at the begining and end: '(,' ',)'*/
tmp := replace(replace(tmp, '(,', '(NULL,'), ',)', ',NULL)'); /*step 2*/

/* replace rest of commas to commas with NULL between them */
SELECT array_to_string(string_to_array(tmp, ',', ''), ',', 'NULL') INTO tmp; /*step 3*/

/* Now we can do EXECUTE*/
EXECUTE 'INSERT INTO log.' || TG_TABLE_NAME || ' SELECT ' || tmp;

当然你也可以一步一步完成1-3

SELECT array_to_string(string_to_array(replace(replace('' || NEW, '(,', '(NULL,'), ',)', ',NULL)'), ',', ''), ',', 'NULL') INTO tmp;

在我看来,这种方法并不比使用 information_schema 好多少,但这是您的决定。

关于Postgresql 创建日志模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33409829/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com