【问题标题】:How to insert stored functions and triggers in a Postgres container如何在 Postgres 容器中插入存储的函数和触发器
【发布时间】:2021-05-23 10:02:24
【问题描述】:

我有一个容器化的 Postgres 数据库,我正在尝试创建一个函数和一个触发器:插入新行时的简单通知。

这可能看起来很愚蠢,但我无法找到如何编写代码,我应该将其推送到 Postgres 容器的何处,以及如何以编程方式将代码插入容器中。

我可以看到如下文件结构

Database/Schemas/public/
|---tables
|  |___requests (tablename)
|  |__Triggers
|
|___Functions
 

我只是(模糊地)在使用 /docker-entrypoint-initdb.d/ 文件夹(Dockerfile 中的一个副本)时找到了一种方法来复制其中的代码。

此注入仅在创建数据库时有效 - 根据 Docker/Postgres 文档。这意味着我必须删除并重新创建数据库。这是错误的,因为我无法对生产数据库进行任何更改。

此外,当我将其他 SQL 命令连接到 .sql 文件中的 CREATE TABLE 命令时,这些命令的执行顺序会导致错误(未知表...)。

我的init.sqlfile 以编程方式复制到 /docker-entrypoint-initdb.d/ 文件夹是:

-- init_table.sql
CREATE TABLE IF NOT EXISTS public.requests (
    id serial PRIMARY KEY,
    ...,
);

-- create_function_notify.sql
CREATE OR REPLACE FUNCTION notify_insert() RETURNS trigger AS
$$
   BEGIN
      PERFORM pg_notify('new_notif', row_to_json(NEW)::text);
      RETURN NEW;
   END;
$$ LANGUAGE plpgsql;


-- create_trigger_new_event.sql
CREATE TRIGGER new_event
   AFTER INSERT
   ON public.requests
   FOR EACH ROW
   EXECUTE PROCEDURE notify_insert();

LANGUAGE plpgsql;

我还尝试了“sh”版本(dixit PG 文档)但没有成功:它在“$$”周围抛出错误。

#/bin/sh

set -e

psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
  CREATE OR REPLACE FUNCTION notify_insert() RETURNS trigger AS
$$
  LANGUAGE plpgsql;
EOSQL

【问题讨论】:

  • "这种注入仅在创建数据库时有效。这是错误的,因为我无法对生产数据库进行任何更改。" - 要做到这一点,你'需要一些数据库迁移工具。而且它是否在与数据库相同的 docker 容器中运行并不重要。
  • "当我将其他 SQL 命令连接到 .sql 文件中的 CREATE TABLE 命令时,这些命令的执行顺序会导致错误(未知表...) i>" - 不,那应该可以。确切的错误信息是什么?请注意,您的示例 sn-p 中有一个流浪 LANGUAGE plpgsql;
  • 确实,在“.sql”文件中,对于函数,我将位置更改为LANGUAGE plpgsql,并删除了触发器无用的位置。为了检查,我在容器上打开了一个端口,使用了 Dbeaver,我可以看到附加到表的触发器和函数。
  • 能否详细介绍一下数据库迁移工具?您的意思是指 Node.js 的 Sequelize 和 Rails 的 ActiveRecord?这是如何关联的?
  • 有很多。一些专用工具,一些内置于框架或 ORM 库中。

标签: postgresql plpgsql stored-functions postgresql-triggers


【解决方案1】:

Dockerfile 指令COPY ./pg_notify.sql /docker-entrypoint-initdb.d/ 为容器化的 Postgres 数据库设置所需的触发器和通知相关功能(仅在创建时)。

按照Bergi的说法,正确的代码是:


-- pg_notify.sql

CREATE TABLE IF NOT EXISTS public.requests (
    id serial PRIMARY KEY,
    app varchar,
    url varchar,
    ip varchar,
    host varchar,
    req_at VARCHAR,
    d BIGINT
);


CREATE OR REPLACE FUNCTION notify_insert() RETURNS trigger 
LANGUAGE plpgsql
AS $$
   BEGIN
      PERFORM pg_notify('new_notification', row_to_json(NEW)::text);
      RETURN NEW;
   END;
$$;

CREATE TRIGGER new_event
   AFTER INSERT
   ON requests
   FOR EACH ROW
   EXECUTE PROCEDURE notify_insert();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-06
    • 2021-12-21
    • 1970-01-01
    • 2021-12-31
    • 1970-01-01
    • 2017-10-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多