为PostgreSQL表创建别名

Phi*_*shy 8 postgresql database-design view plpgsql

我有一张名为赋值的表.我希望能够使用assignments.column或homework.column读取/写入此表中的所有列,我该怎么做?

我知道这不是你通常会做的事情.我需要能够在短时间内提供向后兼容性.

我们有一个iOS应用程序,目前直接对数据库进行postgresql查询.我们正在更新所有应用以使用API​​.在构建API的过程中,开发人员决定更改表的名称,因为我们(愚蠢地)认为我们不需要向后兼容性.

现在,V1.0和API都需要能够写入这个表,所以我以后不必再做一些伏都教来转移/合并数据......我们正在使用Ruby on Rails作为API.

heg*_*mon 14

使用Postgres 9.3,以下内容应该足够了:

创建视图作业AS SELECT*FROM作业;

它的工作原理是因为简单的视图可以自动更新(参见文档).


Erw*_*ter 5

在 Postgres 9.3 或更高版本中,简单VIEW是自动“可更新”的。手册:

简单视图是可自动更新的:系统将允许 在视图上使用INSERTUPDATEDELETE语句,就像在常规表上一样。如果视图满足以下所有条件,则它可以自动更新:

  • 该视图的FROM列表中必须只有一个条目,该条目必须是表或另一个可更新的视图。

  • 视图定义的顶层不得包含WITHDISTINCTGROUP BYHAVINGLIMIT或子句。OFFSET

  • 视图定义不得在顶层包含集合操作(UNION​​ 、INTERSECT或)。EXCEPT

  • 视图的选择列表不得包含任何聚合、窗口函数或集合返回函数。

如果不满足这些条件之一(或者对于现在已经过时的 Postgres 9.2 或更早版本),手动设置可能会完成这项工作。

以您正在进行的工作为基础:

触发功能

CREATE OR REPLACE FUNCTION trg_ia_insupdel()
  RETURNS trigger
  LANGUAGE plpgsql AS
$func$
DECLARE
   _tbl  CONSTANT regclass := 'iassignments_assignments';
   _cols text;
   _vals text;
BEGIN
   CASE TG_OP
   WHEN 'INSERT' THEN
      INSERT INTO iassignments_assignments
      VALUES (NEW.*);

      RETURN NEW;

   WHEN 'UPDATE' THEN
      SELECT INTO _cols, _vals
             string_agg(quote_ident(attname), ', ')   -- incl. pk col!
           , string_agg('n.' || quote_ident(attname), ', ')
      FROM   pg_attribute
      WHERE  attrelid = _tbl        -- _tbl converted to oid automatically
      AND    attnum > 0             -- no system columns
      AND    NOT attisdropped;      -- no dropped (dead) columns

      EXECUTE format('
         UPDATE %s t
         SET   (%s) = (%s)
         FROM  (SELECT ($1).*) n
         WHERE    t.published_assignment_id
             = ($2).published_assignment_id' -- match to OLD value of pk
       , _tbl, _cols, _vals)        -- _tbl converted to text automatically
      USING NEW, OLD;

      RETURN NEW;

   WHEN 'DELETE' THEN
      DELETE FROM iassignments_assignments
      WHERE  published_assignment_id = OLD.published_assignment_id;

      RETURN OLD;
   END CASE;

   RETURN NULL;  -- control should never reach this
END
$func$;
Run Code Online (Sandbox Code Playgroud)

扳机

CREATE TRIGGER insupbef
INSTEAD OF INSERT OR UPDATE OR DELETE ON assignments_published
FOR EACH ROW EXECUTE PROCEDURE trg_ia_insupdel();
Run Code Online (Sandbox Code Playgroud)

笔记

  • assignments_published必须是 a VIEWINSTEAD OF触发器仅允许用于视图。

  • 动态 SQL(在参考资料UPDATE部分中)并不是绝对必要的,只是为了自动覆盖将来对表布局的更改。表和PK的名称仍然是硬编码的。

  • 没有子块更简单,可能更便宜(就像你一样)。

  • 使用(SELECT ($1).*)而不是较短的VALUES ($1.*)来保留列名称。

  • 我的命名约定:我在前面添加trg_触发器函数,后跟表示目标表的缩写,最后分别添加一个或多个标记insupdelfor INSERTUPDATE以及DELETE。触发器的名称是函数名称的副本,去掉了前两部分。这纯粹是一个惯例和品味的问题,但事实证明对我来说很有用,因为名称说明了目的并且仍然很短。

  • 已经提到的相关答案中有更多解释:

  • 更新plpgsql中触发器函数中的多列


Phi*_*shy 0

到目前为止,这就是我使用触发功能的地方,任何反馈将不胜感激。它是http://vibhorkumar.wordpress.com/2011/10/28/instead-of-trigger/Update multiple columns in a trigger function in plpgsql的组合

表:iAssignments_Assignments

列:

published_assignment_id
name
filepath
filename
link
teacher
due date
description
published
classrooms
Run Code Online (Sandbox Code Playgroud)

查看:tasks_published -SELECT * FROM iassignments_assignments

assignments_published 的触发函数

CREATE OR REPLACE FUNCTION assignments_published_trigger_func()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $function$
   BEGIN
      IF TG_OP = 'INSERT' THEN
        EXECUTE format('INSERT INTO %s SELECT ($1).*', 'iassignments_assignments')
        USING NEW;
        RETURN NEW;
      ELSIF TG_OP = 'UPDATE' THEN
        DECLARE
          tbl = 'iassignments_assignments';
          cols text;
          vals text;
        BEGIN
          SELECT INTO cols, vals
           string_agg(quote_ident(attname), ', ')
           ,string_agg('x.' || quote_ident(attname), ', ')
          FROM   pg_attribute
          WHERE  attrelid = tbl
          AND    NOT attisdropped   -- no dropped (dead) columns
          AND    attnum > 0;        -- no system columns

          EXECUTE format('
          UPDATE %s t
          SET   (%s) = (%s)
          FROM  (SELECT ($1).*) x
          WHERE  t.published_assignment_id = ($2).published_assignment_id'
          , tbl, cols, vals)
          USING NEW, OLD;

          RETURN NEW;
        END
      ELSIF TG_OP = 'DELETE' THEN
       DELETE FROM iassignments_assignments WHERE published_assignment_id=OLD.published_assignment_id;
       RETURN NULL;
      END IF;
      RETURN NEW;
    END;
$function$;
Run Code Online (Sandbox Code Playgroud)

扳机

CREATE TRIGGER assignments_published_trigger
INSTEAD OF INSERT OR UPDATE OR DELETE ON
assignments_published FOR EACH ROW EXECUTE PROCEDURE assignments_published_trigger_func();
Run Code Online (Sandbox Code Playgroud)

表:iAssignments_classes

列:

class_assignment_id
guid
assignment_published_id
Run Code Online (Sandbox Code Playgroud)

查看:tasks_class -SELECT * FROM assignments_classes

assignments_class 的触发函数

**一旦收到其他函数的反馈并知道它已创建,我将创建此函数,因此我(希望)需要对此函数进行很少的更改。

扳机

CREATE TRIGGER assignments_class_trigger
INSTEAD OF INSERT OR UPDATE OR DELETE ON
assignments_class FOR EACH ROW EXECUTE PROCEDURE assignments_class_trigger_func();
Run Code Online (Sandbox Code Playgroud)