Create Alias for PostgreSQL Table

前端 未结 3 2328
被撕碎了的回忆
被撕碎了的回忆 2021-02-19 19:57

I have a table called assignments. I would like to be able to read/write to all the columns in this table using either assignments.column or homework.column, how can I do this?<

相关标签:
3条回答
  • 2021-02-19 20:25

    This is where I am with the trigger functions so far, any feedback would be greatly appreciated. It's a combination of http://vibhorkumar.wordpress.com/2011/10/28/instead-of-trigger/ and Update multiple columns in a trigger function in plpgsql

    Table: iassignments_assignments

    Columns:

    published_assignment_id
    name
    filepath
    filename
    link
    teacher
    due date
    description
    published
    classrooms
    

    View: assignments_published - SELECT * FROM iassignments_assignments

    Trigger Function for 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$;
    

    Trigger

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

    Table: iassignments_classes

    Columns:

    class_assignment_id
    guid
    assignment_published_id
    

    View: assignments_class - SELECT * FROM assignments_classes

    Trigger Function for assignments_class

    **I'll create this function once I have received feedback on the other and know it's create, so I (hopefully) need very little changes to this function.

    Trigger

    CREATE TRIGGER assignments_class_trigger
    INSTEAD OF INSERT OR UPDATE OR DELETE ON
    assignments_class FOR EACH ROW EXECUTE PROCEDURE assignments_class_trigger_func();
    
    0 讨论(0)
  • 2021-02-19 20:37

    With Postgres 9.3 the following should be enough:

    CREATE VIEW homework AS SELECT * FROM assignments;

    It works because simple views are automatically updatable (see docs).

    0 讨论(0)
  • 2021-02-19 20:41

    Building on your work in progress:

    Trigger function

    CREATE OR REPLACE FUNCTION trg_ia_insupdel()
      RETURNS TRIGGER 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$ LANGUAGE plpgsql;
    

    Trigger

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

    Notes

    • Dynamic SQL (in the UPDATE section) is not strictly necessary, only to cover future changes to the table layout automatically. The names of the table and the pk are still hard coded.

    • plpgsql assignment operator is :=

    • Simpler and probably cheaper without sub-block (like you had).

    • Using (SELECT ($1).*) instead of the shorter VALUES $1 to preserve column names.

    • My naming convention: I prepend trg_ for trigger functions, followed by an abbreviation indicating the target table and finally one or more of the the tokens ins, up and del for INSERT, UPDATE and DELETE respectively. The name of the trigger is a copy of the function name, stripped of the first two parts. This is purely a matter of convention and taste but has proven useful for me since the names tell the purpose and are still short enough.

    • More explanation in the related answer that has already been mentioned:
      Update multiple columns in a trigger function in plpgsql

    0 讨论(0)
提交回复
热议问题