【发布时间】: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