postgresql 触发器内的PL/pgSQL选择语句使用where NEW返回空值

ewm0tg9j  于 2023-02-18  发布在  PostgreSQL
关注(0)|答案(2)|浏览(180)

我正在创建一个触发器,该触发器在表上执行INSERT时触发,并且我希望记录插入的表的结构,因此我编写了以下函数

CREATE OR REPLACE FUNCTION update_table_log_received()
RETURNS TRIGGER AS $$
DECLARE
  added_column TEXT;
  target_table_name TEXT;
  old_column text;
BEGIN
  -- Check if a new column has been added
  IF (TG_OP = 'INSERT') THEN
    added_column := NEW."COLUMN_NAME";
    target_table_name := NEW."TABLE_NAME";
  END IF;
    SELECT column_name into old_column
                   FROM information_schema."columns"
                   WHERE table_schema = 'items' 
                   and table_name = LOWER(NEW."TABLE_NAME")
                  and column_name = LOWER(NEW."COLUMN_NAME");
if (coalesce(old_column,'')='' or old_column='' or old_column = added_column) THEN
  -- If a new column has been added
  IF (Lower(added_column) != 'sync') then
    
    -- Add the new column to the target table
        EXECUTE 'ALTER TABLE items.' || LOWER(target_table_name)|| ' ADD COLUMN ' || LOWER(added_column) || ' VARCHAR(50)';
  END IF;
end if;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

由该触发器执行:

CREATE TRIGGER update_table_log_received_trigger
AFTER INSERT
ON items."TABLE_LOG_RECEIVED"
FOR EACH ROW
EXECUTE FUNCTION update_table_log_received();

返回的异常如下:
!错误:关系y的列x已存在其中:指令SQL修改表项。添加列x变量字符(50)
我现在的问题是,它不应该通过If检查(我粘贴的代码后,许多修改,我有两个if条件,做同样的事情,只是因为),我调试和记录的语句,注意到我的函数内的选择查询返回空显然。我也试图使用“USING NEW”,但我不是Maven,所以我不能使它工作
是声明的变量没有从“NEW”记录填充的问题,还是我执行了错误的选择语句?
EDIT:tl;dr对于我的问题,我希望每当Database 2中的同一个表(具有相同的结构)从Database 1中更改时,无论是添加列还是更改列,我都要更新该表,此时我停留在添加列的第一个问题上。
我将表的结构作为字符串记录到一个新表中,并将其与Database 2同步,然后让触发器从Database 1中更改相同的已更改表,希望现在这样做更有意义。
记录所有表结构的Database 1 log_table:x1c 0d1x db2 log_table_received,其是每当插入新值时执行触发器的log_table的副本;

14ifxucb

14ifxucb1#

请尝试以下语法:

CREATE OR REPLACE FUNCTION update_table_log_received()
RETURNS TRIGGER AS $$
DECLARE
  added_column TEXT;
  target_table_name TEXT;
  old_column text;
BEGIN
  -- Check if a new column has been added
  IF (TG_OP = 'INSERT') THEN
    added_column := new."column_name";
    target_table_name := new."table_name";
  END IF;

  if not exists(select 1 from information_schema."columns" where table_name = target_table_name and column_name = added_column) 
  then 
      EXECUTE 'ALTER TABLE items.' || LOWER(target_table_name)|| ' ADD COLUMN ' || LOWER(added_column) || ' VARCHAR(50)';
  end if; 
  
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

我试过我的DB这是工程。你可以改变一些细节自己。

mcvgt66p

mcvgt66p2#

已修复;问题应为:

  • 如何在postgresql函数中选择表和表列。

参考文件:How to add column if not exists on PostgreSQL?
如何检查给定模式中是否存在表
How to get a list column names and datatypes of a table in PostgreSQL?
基本上,information_schema只能由所有者访问,即用户或(i)查询时看到结果,但在脚本内部执行时返回FALSE更多详细信息,请单击此处:https://stackoverflow.com/a/24089729/15170264
为安全起见,在使用CTE修复后完全触发以查询pg_catalog,还在我的执行查询中添加了ADD COLUMN IF NOT EXISTS

CREATE OR REPLACE FUNCTION update_table_log_received()
RETURNS TRIGGER AS $$
DECLARE
  added_column TEXT;
  target_table_name TEXT;
  old_column varchar;
    old_table varchar;
BEGIN
  -- Check if a new column has been added
  IF (TG_OP = 'INSERT') THEN
    added_column := NEW."COLUMN_NAME";
    target_table_name := NEW."TABLE_NAME";
  END IF;
 /*
  * --------------- --CTE to find Columns of table "Target_table_name" from pg_catalog
  */

    WITH cte_tables AS (
   SELECT
    pg_attribute.attname AS column_name,
    pg_catalog.format_type(pg_attribute.atttypid, pg_attribute.atttypmod) AS data_type
FROM
    pg_catalog.pg_attribute
INNER JOIN
    pg_catalog.pg_class ON pg_class.oid = pg_attribute.attrelid
INNER JOIN
    pg_catalog.pg_namespace ON pg_namespace.oid = pg_class.relnamespace
WHERE
    pg_attribute.attnum > 0
    AND NOT pg_attribute.attisdropped
    AND pg_namespace.nspname = 'items'
    AND pg_class.relname = 'trace'
ORDER BY
    attnum ASC
)
select column_name into old_column from cte_tables where 
column_name=LOWER(added_column);

 
  if (old_column is null )  then 
    -- Add the new column to the target table
        old_column := added_column;
        EXECUTE 'ALTER TABLE items.' || LOWER(target_table_name)|| ' ADD COLUMN IF NOT EXISTS ' || LOWER(added_column) || ' VARCHAR(50)';
    else
        old_column := added_column || 'already exists ! ';
  END IF;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

create TRIGGER update_table_log_received_trigger
AFTER INSERT
ON items."TABLE_LOG_RECEIVED"
FOR EACH ROW
EXECUTE FUNCTION update_table_log_received();

变量old_column存储else条件消息,但不返回它,如果它是一个简单的函数,则会返回它。

相关问题