- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我目前正在寻找一种处理(相当简单的)PostgreSQL视图上的插入语句的通用方法,这种方法对于列名更改或添加新列将不脆弱。目标是构建不需要维护的INSTEAD
触发器,并且可以轻松地将其应用于具有相似形式的新视图。
换句话说,这将是一种提供对某些视图的表式访问的公式,该视图将允许它们以表式方式进行访问。当然,这样做的目的不是要让任何人都以为某个表是愚弄人,而是为自己和将要向数据库添加记录的其他人简化事情,如果有的话很多人都会来找我它们上的任何触发代码中断。
想要这样的原因是为了处理创建记录需要已经存在的记录的情况:
CREATE TABLE bar (
bar_id SERIAL PRIMARY KEY,
bar_a CHAR
);
CREATE TABLE foo (
foo_id SERIAL PRIMARY KEY,
foo_a BIGINT,
bar_id BIGINT NOT NULL REFERENCES bar(bar_id)
);
CREATE OR REPLACE VIEW view1 AS
SELECT
foo_id,
bar_id,
foo_a AS num,
bar_a AS let
FROM (foo RIGHT JOIN bar ON foo.bar_id = bar.bar_id);
INSERT INTO bar (let) VALUES ('a');
INSERT INTO foo (num,foo_fk) VALUES (1,currval(bar_bar_id_seq));
-- currval only pays attention to the last insert which happens on your OWN connection,
-- meaning it is safe to use it here
INSERT
上查看。希望触发器不会对更改列名和修改视图敏感,这样在视图上抛出格式正确的
INSERT
会成功,而无需对触发器函数进行频繁的小调整。变化。
INSERT
触发功能更可靠,必须从某个位置挖掘此信息。
view_catalog|view_schema|view_name|table_catalog|table_schema|table_name|source_col|view_col|
------------+-----------+---------+-------------+------------+----------+----------+--------+
db1 | public | view1 | db1 | public | bar | bar_a | let |
db1 | public | view1 | db1 | public | bar | bar_id | ---- |
db1 | public | view1 | db1 | public | foo | foo_a | num |
db1 | public | view1 | db1 | public | foo | foo_fk | bar_id |
db1 | public | view1 | db1 | public | foo | foo_id | foo_id |
view_catalog|view_schema|view_name|table_catalog|table_schema|table_name|column_name
------------+-----------+---------+------------+------------+-----------+-------------
db1 | public | view1 | db1 | public | foo | foo_fk
db1 | public | view1 | db1 | public | foo | foo_a
db1 | public | view1 | db1 | public | foo | foo_id
db1 | public | view1 | db1 | public | bar | bar_a
db1 | public | view1 | db1 | public | bar | bar_id
pg_views.definition
上为适当的视图运行解析操作的情况,如果没有框架,这是不可取的,并且可能会违反
DRY。
WITH (...) INSERT
从根本上是正确的,但对于仅提供其他表中几个字段的简单标识映射的数据库视图而言,使用起来却很麻烦。 (如果视图在源字段上进行计算,确实会变得非常紧张,并且必须在将它们添加到原始列之前对其进行转换,但这不是这里的想法)。
CREATE OR REPLACE VIEW view1 AS
SELECT
foo_id AS foo__foo_id,
bar_id AS bar__bar_id,
foo_a AS foo__foo_a,
bar_a AS bar__bar_a
FROM (foo RIGHT JOIN bar ON foo.bar_id = bar.bar_id);
INSERT
操作硬编码到触发器中同样会很脆弱,因为如果视图的列名设置错误,该函数就会阻塞。我们可以提出一种解决易读性问题的方法,但这实际上会使脆弱性部分更糟,这实际上是主要问题。
INSTEAD
触发器可能只是相当标准的。如果可能的话,我仍然希望有一个更好的解决方案,以便当我不在办公室且其他开发人员仍在工作时,以及在我转到其他职位时,一切都可以顺利进行。
INSTEAD
在每一行上运行,上述触发功能会对性能产生影响(除非我只是缓存映射并适当地更新它,以自己的方式是混乱的)。我要澄清的是,由于事物处于不断变化的状态,因此该触发器主要是出于开发目的的便利,而这将使部署变得更简单,更快捷。如果有人有办法(但是很慢),这只是为了学习Postgre的目的而放在我的口袋里将是一件有用的事情。
something_fk
这样的东西始终转换为
something.something_id
之类的东西)的一致性级别是很好的,因为无论如何,这种事情在整个数据库中应该是规则的。
INSERT
触发器一起使用的视图将不会在源列上执行计算(否则,为了保持直观性,必须在插入值之前找到这些操作的逆函数)。我们不要去那里。
pg_attribute
是一个系统表,其中可能包含一些有用的内容,其中包括有关表列的出现顺序的信息。
information_schema.columns
也可以与
view_column_usage
一起提供某些东西(如上所述)。
最佳答案
对此没有简单的解决方案,也没有解决方案。
您在此处提出的内容意味着您将具有一个触发函数,该函数足够通用,可以动态适应不断变化的视图定义以及基础表中的更改。出于多种原因,这是一个坏主意,我仅举两个理由:
如果您的开发人员精通(特权),可以修改表和视图定义,那么他们也应该知道如何为视图编写相应的INSTEAD OF
触发器。知道DDL但不知道PL / pgSQL的开发人员应发送回PG school。
由于必须查找列名,源表,将视图列映射到表列,将值映射到列,处理开发人员提出的约束,因此如您描述的那样灵活的触发函数将相当复杂。列级或表特权等,等等。因此将很慢。由于INSTEAD OF
触发函数始终执行FOR EACH ROW
,因此它们应精简且快速;您正在为严重的性能瓶颈做好准备。
您的表和视图定义多久更改一次?只需在您的商店中制定一条业务规则,即除非有许多人讨论并同意更改(包括触发器的更改),否则表格和视图不会更改。测试任何建议的更改。记录下来。再测试一下。最后,在推出应用程序之前进行更多测试。
我信任的不是一家商店,那里的开发人员对PostgreSQL的了解显然有限,他们无法对可能破坏应用程序的数据模型进行更改。
改进您的开发人员和您的开发过程,而不是PostgreSQL。
你可以做什么
也就是说,仔细设计表和触发器函数可以大大减少触发器函数的数量。基本规则是保持触发器较小且快速,使触发器仅执行明确定义的事情,例如将INSERT
传播到视图的基础表。INSTEAD OF
触发函数基本上只不过是将在视图上运行的命令转换为在基础表上运行的一个或多个命令。一个视图上的INSTEAD OF INSERT
触发功能与另一视图上的#view#
触发功能非常相似,因此您可以尝试使用模板的方法。模板可能如下所示:
CREATE FUNCTION trf_ioi_#view# () RETURNS trigger AS $$
BEGIN
-- Put in INSERT statements on all the tables making up the view
-- Example: Simple insert:
-- INSERT INTO table (columns...)
-- VALUES (NEW...);
-- Get serial PK from 1 table to insert in other tables
-- INSERT INTO table_PK (columns...)
-- VALUES (NEW...)
-- RETURNING pk INTO tid; (DECLARE tid before BEGIN)
-- INSERT INTO table_FK (FK_column, other columns...)
-- VALUES (tid, NEW...);
RETURN NEW; -- to make trigger proceed; NULL to make trigger fail
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER tr_ioi_#view#
INSTEAD OF INSERT ON #view#
FOR EACH ROW EXECUTE PROCEDURE trf_ioi_#view#;
关于sql - 如何自动将 View 列映射到其原始列以插入源表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31443939/
当需要将原始类型转换为字符串时,例如传递给需要字符串的方法时,基本上有两种选择。 以int为例,给出: int i; 我们可以执行以下操作之一: someStringMethod(Integer.to
我有一个位置估计数据库,并且想要计算每月的内核利用率分布。我可以使用 R 中的 adehabitat 包来完成此操作,但我想使用引导数据库中的样本来估计这些值的 95% 置信区间。今天我一直在尝试引导
我希望使用 FTP 编写大型机作业流。为此,我可以通过 FTP 连接到大型机并运行以下命令: QUOTE TYPE E QUOTE SITE FILETYPE=JES PUT myjob.jcl 那么
我是 WPF 的新手。 目前,我正在为名为“LabeledTextbox”的表单元素制作一个用户控件,其中包含一个标签、一个文本框和一个用于错误消息的文本 block 。 当使用代码添加错误消息时,我
我们正在使用 SignalR(原始版本,而不是 Core 版本)并注意到一些无法解释的行为。我们的情况如下: 我们有一个通过 GenericCommand() 方法接受命令的集线器(见下文)。 这些命
使用 requests module 时,有没有办法打印原始 HTTP 请求? 我不只想要标题,我想要请求行、标题和内容打印输出。是否可以看到最终由 HTTP 请求构造的内容? 最佳答案 Since
与直接访问现有本地磁盘或分区的物理磁盘相比,虚拟磁盘为文件存储提供更好的可移植性和效率。VMware有三种不同的磁盘类型:原始磁盘、厚磁盘和精简磁盘,它们各自分配不同的存储空间。 VMware
我有一个用一些颜色着色器等创建的门。 前段时间我拖着门,它问我该怎么办时,我选择了变体。但现在我决定选择创建原始预制件和门颜色,或者着色器变成粉红色。 这是资源中原始预制件和变体的屏幕截图。 粉红色的
我想呈现原始翻译,所以我决定在 Twig 模板中使用“原始”选项。但它不起作用。例子: {{ form_label(form.sfGuardUserProfile.roules_acceptance)
是否可以在sqlite中制作类似的东西? FOREIGN KEY(TypeCode, 'ARawValue', IdServeur) REFERENCES OTHERTABLE(TypeCode, T
这个问题是一个更具体问题的一般版本 asked here .但是,这些答案无法使用。 问题: geoIP数据的原始来源是什么? 许多网站会告诉我我的 IP 在哪里,但它们似乎都在使用来自不到 5 家公
对于Openshift:如何基于Wildfly创建docker镜像? 这是使用的Dockerfile: FROM openshift/wildfly-101-centos7 # Install exa
结果是 127 double middle = 255 / 2 虽然这产生了 127.5 Double middle = 255 / 2 同时这也会产生 127.5 double middle = (
在此处下载带有已编译可执行文件的源代码(大小:161 KB(165,230 字节)):http://www.eyeClaxton.com/download/delphi/ColorSwap.zip 原
以下几行是我需要在 lua 中使用的任意正则表达式。 ['\";=] !^(?:(?:[a-z]{3,10}\s+(?:\w{3,7}?://[\w\-\./]*(?::\d+)?)?/[^?#]*(
这个问题是一个更具体问题的一般版本 asked here .但是,这些答案无法使用。 问题: geoIP数据的原始来源是什么? 许多网站会告诉我我的 IP 在哪里,但它们似乎都在使用来自不到 5 家公
我正在使用GoLang做服务器api,试图管理和回答所发出的请求。使用net/http和github.com/gorilla/mux。 收到请求时,我使用以下结构创建响应: type Response
tl; dr:我认为我的 static_vector 有未定义的行为,但我找不到它。 这个问题是在 Microsoft Visual C++ 17 上。我有这个简单且未完成的 static_vecto
我试图找到原始 Awk (a/k/a One True Awk) 源代码的“历史”版本。我找到了 Kernighan's occasionally-updated site ,它似乎总是链接到最新版本
我在 python 中使用原始 IPv6 套接字时遇到一些问题。我通过以下方式连接: if self._socket != None: # Close out old sock
我是一名优秀的程序员,十分优秀!