SlideShare a Scribd company logo
Postgres Rules
Heresy
CREATE RULE
Esoteric
Y u no use trigger?
View
View
CREATE TABLE users (
    id     integer,
    name    varchar(40),
    PRIMARY KEY(did)
);

CREATE VIEW myview AS SELECT * FROM users;
View
CREATE TABLE users (
    id     integer,
    name    varchar(40),
    PRIMARY KEY(did)
);

CREATE VIEW myview AS SELECT * FROM users;

                           ==
CREATE RULE "_RETURN" AS ON SELECT TO myview DO INSTEAD
    SELECT * FROM mytab;
Speed
Warning
Warning
Postgres rules
Qualification given and INSTEAD
the query tree from the rule action with the rule qualification and the original query tree's
qualification; and the original query tree with the negated rule qualification added
Qualification given and INSTEAD
the query tree from the rule action with the rule qualification and the original query tree's
qualification; and the original query tree with the negated rule qualification added
Postgres rules
CREATE TABLE counts (
    id    INT4 PRIMARY KEY,
    count INT4 NOT NULL
);
CREATE TABLE counts (
    id    INT4 PRIMARY KEY,
    count INT4 NOT NULL
);

CREATE RULE upsert_counts AS ON INSERT TO counts
    WHERE exists ( SELECT * FROM counts WHERE id = NEW.id )
        DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id;
Qualification given and INSTEAD
the query tree from the rule action with the rule qualification and the original query tree's
qualification; and the original query tree with the negated rule qualification added



          CREATE TABLE counts (
              id    INT4 PRIMARY KEY,
              count INT4 NOT NULL
          );
          CREATE RULE upsert_counts AS ON INSERT TO counts
              WHERE exists ( SELECT * FROM counts WHERE id = NEW.id )
                  DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id;
Qualification given and INSTEAD
the query tree from the rule action with the rule qualification and the original query tree's
qualification; and the original query tree with the negated rule qualification added

CREATE TABLE counts (
    id    INT4 PRIMARY KEY,
    count INT4 NOT NULL
);
CREATE RULE upsert_counts AS ON INSERT TO counts
    WHERE exists ( SELECT * FROM counts WHERE id = NEW.id )
        DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id;
Qualification given and INSTEAD
the query tree from the rule action with the rule qualification and the original query tree's
qualification; and the original query tree with the negated rule qualification added

CREATE TABLE counts (
    id    INT4 PRIMARY KEY,
    count INT4 NOT NULL
);
CREATE RULE upsert_counts AS ON INSERT TO counts
    WHERE exists ( SELECT * FROM counts WHERE id = NEW.id )
        DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id;




INSERT INTO counts (id, count) VALUES (1, 1);
Qualification given and INSTEAD
the query tree from the rule action with the rule qualification and the original query tree's
qualification; and the original query tree with the negated rule qualification added

CREATE TABLE counts (
    id    INT4 PRIMARY KEY,
    count INT4 NOT NULL
);
CREATE RULE upsert_counts AS ON INSERT TO counts
    WHERE exists ( SELECT * FROM counts WHERE id = NEW.id )
        DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id;




INSERT INTO counts (id, count) VALUES (1, 1);                                   # SELECT * FROM counts;
                                                                                 id | count
                                                                                ----+----------
                                                                                  1 |        2
                                                                                (1 row)
Qualification given and INSTEAD
the query tree from the rule action with the rule qualification and the original query tree's
qualification; and the original query tree with the negated rule qualification added

CREATE TABLE counts (
    id    INT4 PRIMARY KEY,
    count INT4 NOT NULL
);
CREATE RULE upsert_counts AS ON INSERT TO counts
    WHERE exists ( SELECT * FROM counts WHERE id = NEW.id )
        DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id;


INSERT INTO counts (id, count) VALUES (1, 1);



                                                                                # SELECT * FROM counts;
                                                                                 id | count
                                                                                ----+----------
                                                                                  1 |        2
                                                                                (1 row)
Qualification given and INSTEAD
the query tree from the rule action with the rule qualification and the original query tree's
qualification; and the original query tree with the negated rule qualification added

CREATE TABLE counts (
    id    INT4 PRIMARY KEY,
    count INT4 NOT NULL
);
CREATE RULE upsert_counts AS ON INSERT TO counts
    WHERE exists ( SELECT * FROM counts WHERE id = NEW.id )
        DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id;


INSERT INTO counts (id, count) VALUES (1, 1);



                                                                                # SELECT * FROM counts;
                                                                                 id | count
BECOMES:
                                                                                ----+----------
INSERT INTO test (id, some_val)                                                   1 |        2
    SELECT 1, 1 WHERE NOT (                                                     (1 row)
        EXISTS ( SELECT * FROM test WHERE id = 1)
    );
UPDATE test
SET some_val = some_val + 1
WHERE id = 1 AND ( EXISTS ( SELECT * FROM test WHERE id = 1 ) );
Postgres rules
CREATE TABLE test (
    id!
      ! INT4 PRIMARY KEY,
    val! INT4 NOT NULL
);
CREATE TABLE test (
    id!
      ! INT4 PRIMARY KEY,
    val! INT4 NOT NULL
);

CREATE TABLE test_log (
   id       !! ! INT4 PRIMARY KEY,
   creation_date! TIMESTAMP NOT NULL,
   val ! ! ! ! INT4 NOT NULL,
! CONSTRAINT test_log_pk PRIMARY KEY(id, creation_date)
);
CREATE TABLE test (
    id!
      ! INT4 PRIMARY KEY,
    val! INT4 NOT NULL
);

CREATE TABLE test_log (
   id       !! ! INT4 PRIMARY KEY,
   creation_date! TIMESTAMP NOT NULL,
   val ! ! ! ! INT4 NOT NULL,
! CONSTRAINT test_log_pk PRIMARY KEY(id, creation_date)
);

CREATE RULE test_logging AS ON INSERT TO test
! DO ALSO INSERT INTO test_log(id, creation_date, val) VALUES(NEW.id, NOW(), NEW.val);
CREATE TABLE test (
    id!
      ! INT4 PRIMARY KEY,
    val! INT4 NOT NULL
);

CREATE TABLE test_log (
   id       !! ! INT4 PRIMARY KEY,
   creation_date! TIMESTAMP NOT NULL,
   val ! ! ! ! INT4 NOT NULL,
! CONSTRAINT test_log_pk PRIMARY KEY(id, creation_date)
);

CREATE RULE test_logging AS ON INSERT TO test
! DO ALSO INSERT INTO test_log(id, creation_date, val) VALUES(NEW.id, NOW(), NEW.val);

INSERT INTO test(id, count) VALUES (1, RANDOM());
CREATE TABLE test (
    id!
      ! INT4 PRIMARY KEY,
    val! INT4 NOT NULL
);

CREATE TABLE test_log (
   id       !! ! INT4 PRIMARY KEY,
   creation_date! TIMESTAMP NOT NULL,
   val ! ! ! ! INT4 NOT NULL,
! CONSTRAINT test_log_pk PRIMARY KEY(id, creation_date)
);

CREATE RULE test_logging AS ON INSERT TO test
! DO ALSO INSERT INTO test_log(id, creation_date, val) VALUES(NEW.id, NOW(), NEW.val);

INSERT INTO test(id, count) VALUES (1, RANDOM());




# SELECT * FROM test;
 id | val
----+------
  1 | 46228
(1 row)
CREATE TABLE test (
    id!
      ! INT4 PRIMARY KEY,
    val! INT4 NOT NULL
);

CREATE TABLE test_log (
   id       !! ! INT4 PRIMARY KEY,
   creation_date! TIMESTAMP NOT NULL,
   val ! ! ! ! INT4 NOT NULL,
! CONSTRAINT test_log_pk PRIMARY KEY(id, creation_date)
);

CREATE RULE test_logging AS ON INSERT TO test
! DO ALSO INSERT INTO test_log(id, creation_date, val) VALUES(NEW.id, NOW(), NEW.val);

INSERT INTO test(id, count) VALUES (1, RANDOM());




# SELECT * FROM test;          # SELECT * FROM test_log;
 id | val                       id |      creation_date! !    | val
----+------                    ----+--------------------------+-----
  1 | 46228                      1 | 2012-05-03 07:02:16.43841 15375
(1 row)                        (1 row)
Use Case
reconciliations_data
financial_operations
                       id
id
                       bank_num
amount
                       start_count
card_number
                       end_count
cashier_id
                       deposit_slip_number
reconciliation_id
                       cashier_id
reconciliations_data
financial_operations
                       id
id
                       bank_num
amount
                       start_count
card_number
                       end_count
cashier_id
                       deposit_slip_number
reconciliation_id
                       cashier_id
Postgres rules
CREATE OR REPLACE VIEW reconciliations AS
  SELECT
  ! rec.*,
  ! fin1.id AS start_id,
  ! fin1.upload_date AS start_date,
  ! fin2.id AS end_id,
  ! fin2.upload_date AS end_date
  FROM
  ! reconciliations_data rec
  LEFT OUTER JOIN
  ! (SELECT
    DISTINCT
       first_value(id) OVER (partition BY reconciliation_id ORDER BY upload_date ASC) AS id,
       first_value(upload_date) OVER (partition BY reconciliation_id ORDER BY upload_date ASC) AS upload_date,
       reconciliation_id
    FROM
       financial_operations) AS fin1 ON (fin1.reconciliation_id = rec.id)
    LEFT OUTER JOIN
  ! (SELECT
       DISTINCT
         first_value(id) OVER (partition BY reconciliation_id ORDER BY upload_date DESC) AS id,
         first_value(upload_date) OVER (partition BY reconciliation_id ORDER BY upload_date DESC) AS upload_date,
         reconciliation_id
       FROM
         financial_operations) AS fin2 ON (fin2.reconciliation_id = rec.id)
reconciliations_data
financial_operations
                       id
id
                       bank_num
amount
                       start_count
card_number
                       end_count
cashier_id
                       deposit_slip_number
reconciliation_id
                       cashier_id
reconciliations_data
 financial_operations
                                                   id
 id
                                                   bank_num
 amount
                                                   start_count
 card_number
                                                   end_count
 cashier_id
                                                   deposit_slip_number
 reconciliation_id
                                                   cashier_id


CREATE OR REPLACE RULE fin_ops_from_recons AS
    ON INSERT TO reconciliations DO INSTEAD
    ( INSERT INTO reconciliations_data (cashier_id, lot_id, lane_id, start_count, end_count, cash_deposited, bank_amount,
bank_returned, deposit_slip_number, created_at, updated_at)
      VALUES (new.cashier_id, new.lot_id, new.lane_id, new.start_count, new.end_count, new.cash_deposited, new.bank_amount,
new.bank_returned, new.deposit_slip_number, new.created_at, new.updated_at)
        RETURNING
!   !  !   currval('reconciliations_id_seq')::integer,
!   !  !   cashier_id,
!   !  !   lot_id,
!   !  !   lane_id,
!   !  !   start_count,
!   !  !   end_count,
!   !  !   cash_deposited,
!   !  !   bank_amount,
!   !  !   bank_returned,
!   !  !   deposit_slip_number,
!   !  !   created_at,
!   !  !   updated_at,
!   !  !   null::varchar,
!   !  !   null::varchar,
!   !  !   null::timestamp,
!   !  !   null::varchar,
!   !  !   null::timestamp;
    ;
reconciliations_data
financial_operations
                       id
id
                       bank_num
amount
                       start_count
card_number
                       end_count
cashier_id
                       deposit_slip_number
reconciliation_id
                       cashier_id
reconciliations_data
         financial_operations
                                                           id
         id
                                                           bank_num
         amount
                                                           start_count
         card_number
                                                           end_count
         cashier_id
                                                           deposit_slip_number
         reconciliation_id
                                                           cashier_id




     UPDATE financial_operations SET reconciliation_id = lastval()
       WHERE financial_operations.remote_creation_date >= (( SELECT financial_operations.remote_creation_date
                FROM financial_operations
               WHERE financial_operations.id::text = new.start_id::text)) AND financial_operations.remote_creation_date <=
(( SELECT financial_operations.remote_creation_date
                FROM financial_operations
               WHERE financial_operations.id::text = new.end_id::text)) AND financial_operations.order_transaction_id IS NOT NULL
AND
             CASE
                  WHEN new.lot_id IS NULL THEN new.cashier_id::text = (SELECT order_transactions.user_id
                     FROM order_transactions
                    WHERE order_transactions.id::text = financial_operations.order_transaction_id::text)::text
                  ELSE ((new.cashier_id::text, new.lot_id) = ( SELECT order_transactions.user_id, order_transactions.lot_id
                     FROM order_transactions
                    WHERE order_transactions.id::text = financial_operations.order_transaction_id::text))
             END;
    );
FIN




      guyren@relevantlogic.com

More Related Content

What's hot (20)

PostgreSQL: Advanced features in practice
PostgreSQL: Advanced features in practicePostgreSQL: Advanced features in practice
PostgreSQL: Advanced features in practice
Jano Suchal
 
The Ring programming language version 1.5.1 book - Part 34 of 180
The Ring programming language version 1.5.1 book - Part 34 of 180The Ring programming language version 1.5.1 book - Part 34 of 180
The Ring programming language version 1.5.1 book - Part 34 of 180
Mahmoud Samir Fayed
 
PHP webboard
PHP webboardPHP webboard
PHP webboard
tumetr1
 
Php forum2015 tomas_final
Php forum2015 tomas_finalPhp forum2015 tomas_final
Php forum2015 tomas_final
Bertrand Matthelie
 
PHP cart
PHP cartPHP cart
PHP cart
tumetr1
 
Hadoop Summit EU 2014
Hadoop Summit EU   2014Hadoop Summit EU   2014
Hadoop Summit EU 2014
cwensel
 
BGOUG15: JSON support in MySQL 5.7
BGOUG15: JSON support in MySQL 5.7BGOUG15: JSON support in MySQL 5.7
BGOUG15: JSON support in MySQL 5.7
Georgi Kodinov
 
Web осень 2012 лекция 6
Web осень 2012 лекция 6Web осень 2012 лекция 6
Web осень 2012 лекция 6
Technopark
 
Web весна 2013 лекция 6
Web весна 2013 лекция 6Web весна 2013 лекция 6
Web весна 2013 лекция 6
Technopark
 
JSON Support in MariaDB: News, non-news and the bigger picture
JSON Support in MariaDB: News, non-news and the bigger pictureJSON Support in MariaDB: News, non-news and the bigger picture
JSON Support in MariaDB: News, non-news and the bigger picture
Sergey Petrunya
 
PHP and MySQL Tips and tricks, DC 2007
PHP and MySQL Tips and tricks, DC 2007PHP and MySQL Tips and tricks, DC 2007
PHP and MySQL Tips and tricks, DC 2007
Damien Seguy
 
dbms lab manual
dbms lab manualdbms lab manual
dbms lab manual
stalinjothi
 
Introduction to type classes in 30 min
Introduction to type classes in 30 minIntroduction to type classes in 30 min
Introduction to type classes in 30 min
Pawel Szulc
 
Introduction to type classes
Introduction to type classesIntroduction to type classes
Introduction to type classes
Pawel Szulc
 
WorkingWithSlick2.1.0
WorkingWithSlick2.1.0WorkingWithSlick2.1.0
WorkingWithSlick2.1.0
Knoldus Inc.
 
Apache Solr Search Mastery
Apache Solr Search MasteryApache Solr Search Mastery
Apache Solr Search Mastery
Acquia
 
Pytables
PytablesPytables
Pytables
rocketcircus
 
Obtain better data accuracy using reference tables
Obtain better data accuracy using reference tablesObtain better data accuracy using reference tables
Obtain better data accuracy using reference tables
Kiran Venna
 
DConf 2016 std.database (a proposed interface & implementation)
DConf 2016 std.database (a proposed interface & implementation)DConf 2016 std.database (a proposed interface & implementation)
DConf 2016 std.database (a proposed interface & implementation)
cruisercoder
 
Spl Not A Bridge Too Far phpNW09
Spl Not A Bridge Too Far phpNW09Spl Not A Bridge Too Far phpNW09
Spl Not A Bridge Too Far phpNW09
Michelangelo van Dam
 
PostgreSQL: Advanced features in practice
PostgreSQL: Advanced features in practicePostgreSQL: Advanced features in practice
PostgreSQL: Advanced features in practice
Jano Suchal
 
The Ring programming language version 1.5.1 book - Part 34 of 180
The Ring programming language version 1.5.1 book - Part 34 of 180The Ring programming language version 1.5.1 book - Part 34 of 180
The Ring programming language version 1.5.1 book - Part 34 of 180
Mahmoud Samir Fayed
 
PHP webboard
PHP webboardPHP webboard
PHP webboard
tumetr1
 
PHP cart
PHP cartPHP cart
PHP cart
tumetr1
 
Hadoop Summit EU 2014
Hadoop Summit EU   2014Hadoop Summit EU   2014
Hadoop Summit EU 2014
cwensel
 
BGOUG15: JSON support in MySQL 5.7
BGOUG15: JSON support in MySQL 5.7BGOUG15: JSON support in MySQL 5.7
BGOUG15: JSON support in MySQL 5.7
Georgi Kodinov
 
Web осень 2012 лекция 6
Web осень 2012 лекция 6Web осень 2012 лекция 6
Web осень 2012 лекция 6
Technopark
 
Web весна 2013 лекция 6
Web весна 2013 лекция 6Web весна 2013 лекция 6
Web весна 2013 лекция 6
Technopark
 
JSON Support in MariaDB: News, non-news and the bigger picture
JSON Support in MariaDB: News, non-news and the bigger pictureJSON Support in MariaDB: News, non-news and the bigger picture
JSON Support in MariaDB: News, non-news and the bigger picture
Sergey Petrunya
 
PHP and MySQL Tips and tricks, DC 2007
PHP and MySQL Tips and tricks, DC 2007PHP and MySQL Tips and tricks, DC 2007
PHP and MySQL Tips and tricks, DC 2007
Damien Seguy
 
Introduction to type classes in 30 min
Introduction to type classes in 30 minIntroduction to type classes in 30 min
Introduction to type classes in 30 min
Pawel Szulc
 
Introduction to type classes
Introduction to type classesIntroduction to type classes
Introduction to type classes
Pawel Szulc
 
WorkingWithSlick2.1.0
WorkingWithSlick2.1.0WorkingWithSlick2.1.0
WorkingWithSlick2.1.0
Knoldus Inc.
 
Apache Solr Search Mastery
Apache Solr Search MasteryApache Solr Search Mastery
Apache Solr Search Mastery
Acquia
 
Obtain better data accuracy using reference tables
Obtain better data accuracy using reference tablesObtain better data accuracy using reference tables
Obtain better data accuracy using reference tables
Kiran Venna
 
DConf 2016 std.database (a proposed interface & implementation)
DConf 2016 std.database (a proposed interface & implementation)DConf 2016 std.database (a proposed interface & implementation)
DConf 2016 std.database (a proposed interface & implementation)
cruisercoder
 

Similar to Postgres rules (20)

Advanced query optimization
Advanced query optimizationAdvanced query optimization
Advanced query optimization
MYXPLAIN
 
SQL Performance Solutions: Refactor Mercilessly, Index Wisely
SQL Performance Solutions: Refactor Mercilessly, Index WiselySQL Performance Solutions: Refactor Mercilessly, Index Wisely
SQL Performance Solutions: Refactor Mercilessly, Index Wisely
Enkitec
 
PostgreSQL10の新機能 ~ロジカルレプリケーションを中心に~
PostgreSQL10の新機能 ~ロジカルレプリケーションを中心に~PostgreSQL10の新機能 ~ロジカルレプリケーションを中心に~
PostgreSQL10の新機能 ~ロジカルレプリケーションを中心に~
Atsushi Torikoshi
 
Sql Tags
Sql TagsSql Tags
Sql Tags
Sutharsan nagarajan
 
7. Nested Subqueries.pdf
7. Nested Subqueries.pdf7. Nested Subqueries.pdf
7. Nested Subqueries.pdf
Sunita Milind Dol
 
Oracle12c For Developers
Oracle12c For DevelopersOracle12c For Developers
Oracle12c For Developers
Alex Nuijten
 
Oracle12 for Developers - Oracle OpenWorld Preview AMIS
Oracle12 for Developers - Oracle OpenWorld Preview AMISOracle12 for Developers - Oracle OpenWorld Preview AMIS
Oracle12 for Developers - Oracle OpenWorld Preview AMIS
Getting value from IoT, Integration and Data Analytics
 
Server Query Language – Getting Started.pptx
Server Query Language – Getting Started.pptxServer Query Language – Getting Started.pptx
Server Query Language – Getting Started.pptx
auzee32
 
SQL Queries and Solutions (Database)
SQL Queries and Solutions (Database)SQL Queries and Solutions (Database)
SQL Queries and Solutions (Database)
SM. Aurnob
 
Dbms record
Dbms recordDbms record
Dbms record
Teja Bheemanapally
 
Writeable CTEs: The Next Big Thing
Writeable CTEs: The Next Big ThingWriteable CTEs: The Next Big Thing
Writeable CTEs: The Next Big Thing
PostgreSQL Experts, Inc.
 
Writing and optimizing T-SQL
Writing and optimizing T-SQLWriting and optimizing T-SQL
Writing and optimizing T-SQL
Vatroslav Mileusnić
 
Subquery.pptx
Subquery.pptxSubquery.pptx
Subquery.pptx
BhagyaLakshmi425734
 
Writeable ct es_pgcon_may_2011
Writeable ct es_pgcon_may_2011Writeable ct es_pgcon_may_2011
Writeable ct es_pgcon_may_2011
David Fetter
 
How to tune a query - ODTUG 2012
How to tune a query - ODTUG 2012How to tune a query - ODTUG 2012
How to tune a query - ODTUG 2012
Connor McDonald
 
Nested queries in database
Nested queries in databaseNested queries in database
Nested queries in database
Satya P. Joshi
 
Sql
SqlSql
Sql
sinavt
 
vnd.openxmlformats-officedocument.presentationml.presentation&rendition=1.pptx
vnd.openxmlformats-officedocument.presentationml.presentation&rendition=1.pptxvnd.openxmlformats-officedocument.presentationml.presentation&rendition=1.pptx
vnd.openxmlformats-officedocument.presentationml.presentation&rendition=1.pptx
jaijsr12345
 
Postgres is easier
Postgres is easierPostgres is easier
Postgres is easier
gisborne
 
SQL Quick Reference Card
SQL Quick Reference CardSQL Quick Reference Card
SQL Quick Reference Card
Techcanvass
 
Advanced query optimization
Advanced query optimizationAdvanced query optimization
Advanced query optimization
MYXPLAIN
 
SQL Performance Solutions: Refactor Mercilessly, Index Wisely
SQL Performance Solutions: Refactor Mercilessly, Index WiselySQL Performance Solutions: Refactor Mercilessly, Index Wisely
SQL Performance Solutions: Refactor Mercilessly, Index Wisely
Enkitec
 
PostgreSQL10の新機能 ~ロジカルレプリケーションを中心に~
PostgreSQL10の新機能 ~ロジカルレプリケーションを中心に~PostgreSQL10の新機能 ~ロジカルレプリケーションを中心に~
PostgreSQL10の新機能 ~ロジカルレプリケーションを中心に~
Atsushi Torikoshi
 
Oracle12c For Developers
Oracle12c For DevelopersOracle12c For Developers
Oracle12c For Developers
Alex Nuijten
 
Server Query Language – Getting Started.pptx
Server Query Language – Getting Started.pptxServer Query Language – Getting Started.pptx
Server Query Language – Getting Started.pptx
auzee32
 
SQL Queries and Solutions (Database)
SQL Queries and Solutions (Database)SQL Queries and Solutions (Database)
SQL Queries and Solutions (Database)
SM. Aurnob
 
Writeable ct es_pgcon_may_2011
Writeable ct es_pgcon_may_2011Writeable ct es_pgcon_may_2011
Writeable ct es_pgcon_may_2011
David Fetter
 
How to tune a query - ODTUG 2012
How to tune a query - ODTUG 2012How to tune a query - ODTUG 2012
How to tune a query - ODTUG 2012
Connor McDonald
 
Nested queries in database
Nested queries in databaseNested queries in database
Nested queries in database
Satya P. Joshi
 
vnd.openxmlformats-officedocument.presentationml.presentation&rendition=1.pptx
vnd.openxmlformats-officedocument.presentationml.presentation&rendition=1.pptxvnd.openxmlformats-officedocument.presentationml.presentation&rendition=1.pptx
vnd.openxmlformats-officedocument.presentationml.presentation&rendition=1.pptx
jaijsr12345
 
Postgres is easier
Postgres is easierPostgres is easier
Postgres is easier
gisborne
 
SQL Quick Reference Card
SQL Quick Reference CardSQL Quick Reference Card
SQL Quick Reference Card
Techcanvass
 
Ad

Recently uploaded (20)

vertical-cnc-processing-centers-drillteq-v-200-en.pdf
vertical-cnc-processing-centers-drillteq-v-200-en.pdfvertical-cnc-processing-centers-drillteq-v-200-en.pdf
vertical-cnc-processing-centers-drillteq-v-200-en.pdf
AmirStern2
 
Murdledescargadarkweb.pdfvolumen1 100 elementary
Murdledescargadarkweb.pdfvolumen1 100 elementaryMurdledescargadarkweb.pdfvolumen1 100 elementary
Murdledescargadarkweb.pdfvolumen1 100 elementary
JorgeSemperteguiMont
 
Can We Use Rust to Develop Extensions for PostgreSQL? (POSETTE: An Event for ...
Can We Use Rust to Develop Extensions for PostgreSQL? (POSETTE: An Event for ...Can We Use Rust to Develop Extensions for PostgreSQL? (POSETTE: An Event for ...
Can We Use Rust to Develop Extensions for PostgreSQL? (POSETTE: An Event for ...
NTT DATA Technology & Innovation
 
Crypto Super 500 - 14th Report - June2025.pdf
Crypto Super 500 - 14th Report - June2025.pdfCrypto Super 500 - 14th Report - June2025.pdf
Crypto Super 500 - 14th Report - June2025.pdf
Stephen Perrenod
 
Artificial Intelligence in the Nonprofit Boardroom.pdf
Artificial Intelligence in the Nonprofit Boardroom.pdfArtificial Intelligence in the Nonprofit Boardroom.pdf
Artificial Intelligence in the Nonprofit Boardroom.pdf
OnBoard
 
FIDO Alliance Seminar State of Passkeys.pptx
FIDO Alliance Seminar State of Passkeys.pptxFIDO Alliance Seminar State of Passkeys.pptx
FIDO Alliance Seminar State of Passkeys.pptx
FIDO Alliance
 
National Fuels Treatments Initiative: Building a Seamless Map of Hazardous Fu...
National Fuels Treatments Initiative: Building a Seamless Map of Hazardous Fu...National Fuels Treatments Initiative: Building a Seamless Map of Hazardous Fu...
National Fuels Treatments Initiative: Building a Seamless Map of Hazardous Fu...
Safe Software
 
High Availability On-Premises FME Flow.pdf
High Availability On-Premises FME Flow.pdfHigh Availability On-Premises FME Flow.pdf
High Availability On-Premises FME Flow.pdf
Safe Software
 
June Patch Tuesday
June Patch TuesdayJune Patch Tuesday
June Patch Tuesday
Ivanti
 
ENERGY CONSUMPTION CALCULATION IN ENERGY-EFFICIENT AIR CONDITIONER.pdf
ENERGY CONSUMPTION CALCULATION IN ENERGY-EFFICIENT AIR CONDITIONER.pdfENERGY CONSUMPTION CALCULATION IN ENERGY-EFFICIENT AIR CONDITIONER.pdf
ENERGY CONSUMPTION CALCULATION IN ENERGY-EFFICIENT AIR CONDITIONER.pdf
Muhammad Rizwan Akram
 
Data Validation and System Interoperability
Data Validation and System InteroperabilityData Validation and System Interoperability
Data Validation and System Interoperability
Safe Software
 
Scaling GenAI Inference From Prototype to Production: Real-World Lessons in S...
Scaling GenAI Inference From Prototype to Production: Real-World Lessons in S...Scaling GenAI Inference From Prototype to Production: Real-World Lessons in S...
Scaling GenAI Inference From Prototype to Production: Real-World Lessons in S...
Anish Kumar
 
cnc-drilling-dowel-inserting-machine-drillteq-d-510-english.pdf
cnc-drilling-dowel-inserting-machine-drillteq-d-510-english.pdfcnc-drilling-dowel-inserting-machine-drillteq-d-510-english.pdf
cnc-drilling-dowel-inserting-machine-drillteq-d-510-english.pdf
AmirStern2
 
“Why It’s Critical to Have an Integrated Development Methodology for Edge AI,...
“Why It’s Critical to Have an Integrated Development Methodology for Edge AI,...“Why It’s Critical to Have an Integrated Development Methodology for Edge AI,...
“Why It’s Critical to Have an Integrated Development Methodology for Edge AI,...
Edge AI and Vision Alliance
 
Bridging the divide: A conversation on tariffs today in the book industry - T...
Bridging the divide: A conversation on tariffs today in the book industry - T...Bridging the divide: A conversation on tariffs today in the book industry - T...
Bridging the divide: A conversation on tariffs today in the book industry - T...
BookNet Canada
 
Supporting the NextGen 911 Digital Transformation with FME
Supporting the NextGen 911 Digital Transformation with FMESupporting the NextGen 911 Digital Transformation with FME
Supporting the NextGen 911 Digital Transformation with FME
Safe Software
 
Oracle Cloud Infrastructure AI Foundations
Oracle Cloud Infrastructure AI FoundationsOracle Cloud Infrastructure AI Foundations
Oracle Cloud Infrastructure AI Foundations
VICTOR MAESTRE RAMIREZ
 
Down the Rabbit Hole – Solving 5 Training Roadblocks
Down the Rabbit Hole – Solving 5 Training RoadblocksDown the Rabbit Hole – Solving 5 Training Roadblocks
Down the Rabbit Hole – Solving 5 Training Roadblocks
Rustici Software
 
FIDO Seminar: Evolving Landscape of Post-Quantum Cryptography.pptx
FIDO Seminar: Evolving Landscape of Post-Quantum Cryptography.pptxFIDO Seminar: Evolving Landscape of Post-Quantum Cryptography.pptx
FIDO Seminar: Evolving Landscape of Post-Quantum Cryptography.pptx
FIDO Alliance
 
FIDO Seminar: Authentication for a Billion Consumers - Amazon.pptx
FIDO Seminar: Authentication for a Billion Consumers - Amazon.pptxFIDO Seminar: Authentication for a Billion Consumers - Amazon.pptx
FIDO Seminar: Authentication for a Billion Consumers - Amazon.pptx
FIDO Alliance
 
vertical-cnc-processing-centers-drillteq-v-200-en.pdf
vertical-cnc-processing-centers-drillteq-v-200-en.pdfvertical-cnc-processing-centers-drillteq-v-200-en.pdf
vertical-cnc-processing-centers-drillteq-v-200-en.pdf
AmirStern2
 
Murdledescargadarkweb.pdfvolumen1 100 elementary
Murdledescargadarkweb.pdfvolumen1 100 elementaryMurdledescargadarkweb.pdfvolumen1 100 elementary
Murdledescargadarkweb.pdfvolumen1 100 elementary
JorgeSemperteguiMont
 
Can We Use Rust to Develop Extensions for PostgreSQL? (POSETTE: An Event for ...
Can We Use Rust to Develop Extensions for PostgreSQL? (POSETTE: An Event for ...Can We Use Rust to Develop Extensions for PostgreSQL? (POSETTE: An Event for ...
Can We Use Rust to Develop Extensions for PostgreSQL? (POSETTE: An Event for ...
NTT DATA Technology & Innovation
 
Crypto Super 500 - 14th Report - June2025.pdf
Crypto Super 500 - 14th Report - June2025.pdfCrypto Super 500 - 14th Report - June2025.pdf
Crypto Super 500 - 14th Report - June2025.pdf
Stephen Perrenod
 
Artificial Intelligence in the Nonprofit Boardroom.pdf
Artificial Intelligence in the Nonprofit Boardroom.pdfArtificial Intelligence in the Nonprofit Boardroom.pdf
Artificial Intelligence in the Nonprofit Boardroom.pdf
OnBoard
 
FIDO Alliance Seminar State of Passkeys.pptx
FIDO Alliance Seminar State of Passkeys.pptxFIDO Alliance Seminar State of Passkeys.pptx
FIDO Alliance Seminar State of Passkeys.pptx
FIDO Alliance
 
National Fuels Treatments Initiative: Building a Seamless Map of Hazardous Fu...
National Fuels Treatments Initiative: Building a Seamless Map of Hazardous Fu...National Fuels Treatments Initiative: Building a Seamless Map of Hazardous Fu...
National Fuels Treatments Initiative: Building a Seamless Map of Hazardous Fu...
Safe Software
 
High Availability On-Premises FME Flow.pdf
High Availability On-Premises FME Flow.pdfHigh Availability On-Premises FME Flow.pdf
High Availability On-Premises FME Flow.pdf
Safe Software
 
June Patch Tuesday
June Patch TuesdayJune Patch Tuesday
June Patch Tuesday
Ivanti
 
ENERGY CONSUMPTION CALCULATION IN ENERGY-EFFICIENT AIR CONDITIONER.pdf
ENERGY CONSUMPTION CALCULATION IN ENERGY-EFFICIENT AIR CONDITIONER.pdfENERGY CONSUMPTION CALCULATION IN ENERGY-EFFICIENT AIR CONDITIONER.pdf
ENERGY CONSUMPTION CALCULATION IN ENERGY-EFFICIENT AIR CONDITIONER.pdf
Muhammad Rizwan Akram
 
Data Validation and System Interoperability
Data Validation and System InteroperabilityData Validation and System Interoperability
Data Validation and System Interoperability
Safe Software
 
Scaling GenAI Inference From Prototype to Production: Real-World Lessons in S...
Scaling GenAI Inference From Prototype to Production: Real-World Lessons in S...Scaling GenAI Inference From Prototype to Production: Real-World Lessons in S...
Scaling GenAI Inference From Prototype to Production: Real-World Lessons in S...
Anish Kumar
 
cnc-drilling-dowel-inserting-machine-drillteq-d-510-english.pdf
cnc-drilling-dowel-inserting-machine-drillteq-d-510-english.pdfcnc-drilling-dowel-inserting-machine-drillteq-d-510-english.pdf
cnc-drilling-dowel-inserting-machine-drillteq-d-510-english.pdf
AmirStern2
 
“Why It’s Critical to Have an Integrated Development Methodology for Edge AI,...
“Why It’s Critical to Have an Integrated Development Methodology for Edge AI,...“Why It’s Critical to Have an Integrated Development Methodology for Edge AI,...
“Why It’s Critical to Have an Integrated Development Methodology for Edge AI,...
Edge AI and Vision Alliance
 
Bridging the divide: A conversation on tariffs today in the book industry - T...
Bridging the divide: A conversation on tariffs today in the book industry - T...Bridging the divide: A conversation on tariffs today in the book industry - T...
Bridging the divide: A conversation on tariffs today in the book industry - T...
BookNet Canada
 
Supporting the NextGen 911 Digital Transformation with FME
Supporting the NextGen 911 Digital Transformation with FMESupporting the NextGen 911 Digital Transformation with FME
Supporting the NextGen 911 Digital Transformation with FME
Safe Software
 
Oracle Cloud Infrastructure AI Foundations
Oracle Cloud Infrastructure AI FoundationsOracle Cloud Infrastructure AI Foundations
Oracle Cloud Infrastructure AI Foundations
VICTOR MAESTRE RAMIREZ
 
Down the Rabbit Hole – Solving 5 Training Roadblocks
Down the Rabbit Hole – Solving 5 Training RoadblocksDown the Rabbit Hole – Solving 5 Training Roadblocks
Down the Rabbit Hole – Solving 5 Training Roadblocks
Rustici Software
 
FIDO Seminar: Evolving Landscape of Post-Quantum Cryptography.pptx
FIDO Seminar: Evolving Landscape of Post-Quantum Cryptography.pptxFIDO Seminar: Evolving Landscape of Post-Quantum Cryptography.pptx
FIDO Seminar: Evolving Landscape of Post-Quantum Cryptography.pptx
FIDO Alliance
 
FIDO Seminar: Authentication for a Billion Consumers - Amazon.pptx
FIDO Seminar: Authentication for a Billion Consumers - Amazon.pptxFIDO Seminar: Authentication for a Billion Consumers - Amazon.pptx
FIDO Seminar: Authentication for a Billion Consumers - Amazon.pptx
FIDO Alliance
 
Ad

Postgres rules

  • 5. Y u no use trigger?
  • 7. View CREATE TABLE users ( id integer, name varchar(40), PRIMARY KEY(did) ); CREATE VIEW myview AS SELECT * FROM users;
  • 8. View CREATE TABLE users ( id integer, name varchar(40), PRIMARY KEY(did) ); CREATE VIEW myview AS SELECT * FROM users; == CREATE RULE "_RETURN" AS ON SELECT TO myview DO INSTEAD SELECT * FROM mytab;
  • 13. Qualification given and INSTEAD the query tree from the rule action with the rule qualification and the original query tree's qualification; and the original query tree with the negated rule qualification added
  • 14. Qualification given and INSTEAD the query tree from the rule action with the rule qualification and the original query tree's qualification; and the original query tree with the negated rule qualification added
  • 16. CREATE TABLE counts ( id INT4 PRIMARY KEY, count INT4 NOT NULL );
  • 17. CREATE TABLE counts ( id INT4 PRIMARY KEY, count INT4 NOT NULL ); CREATE RULE upsert_counts AS ON INSERT TO counts WHERE exists ( SELECT * FROM counts WHERE id = NEW.id ) DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id;
  • 18. Qualification given and INSTEAD the query tree from the rule action with the rule qualification and the original query tree's qualification; and the original query tree with the negated rule qualification added CREATE TABLE counts ( id INT4 PRIMARY KEY, count INT4 NOT NULL ); CREATE RULE upsert_counts AS ON INSERT TO counts WHERE exists ( SELECT * FROM counts WHERE id = NEW.id ) DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id;
  • 19. Qualification given and INSTEAD the query tree from the rule action with the rule qualification and the original query tree's qualification; and the original query tree with the negated rule qualification added CREATE TABLE counts ( id INT4 PRIMARY KEY, count INT4 NOT NULL ); CREATE RULE upsert_counts AS ON INSERT TO counts WHERE exists ( SELECT * FROM counts WHERE id = NEW.id ) DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id;
  • 20. Qualification given and INSTEAD the query tree from the rule action with the rule qualification and the original query tree's qualification; and the original query tree with the negated rule qualification added CREATE TABLE counts ( id INT4 PRIMARY KEY, count INT4 NOT NULL ); CREATE RULE upsert_counts AS ON INSERT TO counts WHERE exists ( SELECT * FROM counts WHERE id = NEW.id ) DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id; INSERT INTO counts (id, count) VALUES (1, 1);
  • 21. Qualification given and INSTEAD the query tree from the rule action with the rule qualification and the original query tree's qualification; and the original query tree with the negated rule qualification added CREATE TABLE counts ( id INT4 PRIMARY KEY, count INT4 NOT NULL ); CREATE RULE upsert_counts AS ON INSERT TO counts WHERE exists ( SELECT * FROM counts WHERE id = NEW.id ) DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id; INSERT INTO counts (id, count) VALUES (1, 1); # SELECT * FROM counts; id | count ----+---------- 1 | 2 (1 row)
  • 22. Qualification given and INSTEAD the query tree from the rule action with the rule qualification and the original query tree's qualification; and the original query tree with the negated rule qualification added CREATE TABLE counts ( id INT4 PRIMARY KEY, count INT4 NOT NULL ); CREATE RULE upsert_counts AS ON INSERT TO counts WHERE exists ( SELECT * FROM counts WHERE id = NEW.id ) DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id; INSERT INTO counts (id, count) VALUES (1, 1); # SELECT * FROM counts; id | count ----+---------- 1 | 2 (1 row)
  • 23. Qualification given and INSTEAD the query tree from the rule action with the rule qualification and the original query tree's qualification; and the original query tree with the negated rule qualification added CREATE TABLE counts ( id INT4 PRIMARY KEY, count INT4 NOT NULL ); CREATE RULE upsert_counts AS ON INSERT TO counts WHERE exists ( SELECT * FROM counts WHERE id = NEW.id ) DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id; INSERT INTO counts (id, count) VALUES (1, 1); # SELECT * FROM counts; id | count BECOMES: ----+---------- INSERT INTO test (id, some_val) 1 | 2 SELECT 1, 1 WHERE NOT ( (1 row) EXISTS ( SELECT * FROM test WHERE id = 1) ); UPDATE test SET some_val = some_val + 1 WHERE id = 1 AND ( EXISTS ( SELECT * FROM test WHERE id = 1 ) );
  • 25. CREATE TABLE test ( id! ! INT4 PRIMARY KEY, val! INT4 NOT NULL );
  • 26. CREATE TABLE test ( id! ! INT4 PRIMARY KEY, val! INT4 NOT NULL ); CREATE TABLE test_log ( id !! ! INT4 PRIMARY KEY, creation_date! TIMESTAMP NOT NULL, val ! ! ! ! INT4 NOT NULL, ! CONSTRAINT test_log_pk PRIMARY KEY(id, creation_date) );
  • 27. CREATE TABLE test ( id! ! INT4 PRIMARY KEY, val! INT4 NOT NULL ); CREATE TABLE test_log ( id !! ! INT4 PRIMARY KEY, creation_date! TIMESTAMP NOT NULL, val ! ! ! ! INT4 NOT NULL, ! CONSTRAINT test_log_pk PRIMARY KEY(id, creation_date) ); CREATE RULE test_logging AS ON INSERT TO test ! DO ALSO INSERT INTO test_log(id, creation_date, val) VALUES(NEW.id, NOW(), NEW.val);
  • 28. CREATE TABLE test ( id! ! INT4 PRIMARY KEY, val! INT4 NOT NULL ); CREATE TABLE test_log ( id !! ! INT4 PRIMARY KEY, creation_date! TIMESTAMP NOT NULL, val ! ! ! ! INT4 NOT NULL, ! CONSTRAINT test_log_pk PRIMARY KEY(id, creation_date) ); CREATE RULE test_logging AS ON INSERT TO test ! DO ALSO INSERT INTO test_log(id, creation_date, val) VALUES(NEW.id, NOW(), NEW.val); INSERT INTO test(id, count) VALUES (1, RANDOM());
  • 29. CREATE TABLE test ( id! ! INT4 PRIMARY KEY, val! INT4 NOT NULL ); CREATE TABLE test_log ( id !! ! INT4 PRIMARY KEY, creation_date! TIMESTAMP NOT NULL, val ! ! ! ! INT4 NOT NULL, ! CONSTRAINT test_log_pk PRIMARY KEY(id, creation_date) ); CREATE RULE test_logging AS ON INSERT TO test ! DO ALSO INSERT INTO test_log(id, creation_date, val) VALUES(NEW.id, NOW(), NEW.val); INSERT INTO test(id, count) VALUES (1, RANDOM()); # SELECT * FROM test; id | val ----+------ 1 | 46228 (1 row)
  • 30. CREATE TABLE test ( id! ! INT4 PRIMARY KEY, val! INT4 NOT NULL ); CREATE TABLE test_log ( id !! ! INT4 PRIMARY KEY, creation_date! TIMESTAMP NOT NULL, val ! ! ! ! INT4 NOT NULL, ! CONSTRAINT test_log_pk PRIMARY KEY(id, creation_date) ); CREATE RULE test_logging AS ON INSERT TO test ! DO ALSO INSERT INTO test_log(id, creation_date, val) VALUES(NEW.id, NOW(), NEW.val); INSERT INTO test(id, count) VALUES (1, RANDOM()); # SELECT * FROM test; # SELECT * FROM test_log; id | val id | creation_date! ! | val ----+------ ----+--------------------------+----- 1 | 46228 1 | 2012-05-03 07:02:16.43841 15375 (1 row) (1 row)
  • 32. reconciliations_data financial_operations id id bank_num amount start_count card_number end_count cashier_id deposit_slip_number reconciliation_id cashier_id
  • 33. reconciliations_data financial_operations id id bank_num amount start_count card_number end_count cashier_id deposit_slip_number reconciliation_id cashier_id
  • 35. CREATE OR REPLACE VIEW reconciliations AS SELECT ! rec.*, ! fin1.id AS start_id, ! fin1.upload_date AS start_date, ! fin2.id AS end_id, ! fin2.upload_date AS end_date FROM ! reconciliations_data rec LEFT OUTER JOIN ! (SELECT DISTINCT first_value(id) OVER (partition BY reconciliation_id ORDER BY upload_date ASC) AS id, first_value(upload_date) OVER (partition BY reconciliation_id ORDER BY upload_date ASC) AS upload_date, reconciliation_id FROM financial_operations) AS fin1 ON (fin1.reconciliation_id = rec.id) LEFT OUTER JOIN ! (SELECT DISTINCT first_value(id) OVER (partition BY reconciliation_id ORDER BY upload_date DESC) AS id, first_value(upload_date) OVER (partition BY reconciliation_id ORDER BY upload_date DESC) AS upload_date, reconciliation_id FROM financial_operations) AS fin2 ON (fin2.reconciliation_id = rec.id)
  • 36. reconciliations_data financial_operations id id bank_num amount start_count card_number end_count cashier_id deposit_slip_number reconciliation_id cashier_id
  • 37. reconciliations_data financial_operations id id bank_num amount start_count card_number end_count cashier_id deposit_slip_number reconciliation_id cashier_id CREATE OR REPLACE RULE fin_ops_from_recons AS ON INSERT TO reconciliations DO INSTEAD ( INSERT INTO reconciliations_data (cashier_id, lot_id, lane_id, start_count, end_count, cash_deposited, bank_amount, bank_returned, deposit_slip_number, created_at, updated_at) VALUES (new.cashier_id, new.lot_id, new.lane_id, new.start_count, new.end_count, new.cash_deposited, new.bank_amount, new.bank_returned, new.deposit_slip_number, new.created_at, new.updated_at) RETURNING ! ! ! currval('reconciliations_id_seq')::integer, ! ! ! cashier_id, ! ! ! lot_id, ! ! ! lane_id, ! ! ! start_count, ! ! ! end_count, ! ! ! cash_deposited, ! ! ! bank_amount, ! ! ! bank_returned, ! ! ! deposit_slip_number, ! ! ! created_at, ! ! ! updated_at, ! ! ! null::varchar, ! ! ! null::varchar, ! ! ! null::timestamp, ! ! ! null::varchar, ! ! ! null::timestamp; ;
  • 38. reconciliations_data financial_operations id id bank_num amount start_count card_number end_count cashier_id deposit_slip_number reconciliation_id cashier_id
  • 39. reconciliations_data financial_operations id id bank_num amount start_count card_number end_count cashier_id deposit_slip_number reconciliation_id cashier_id UPDATE financial_operations SET reconciliation_id = lastval() WHERE financial_operations.remote_creation_date >= (( SELECT financial_operations.remote_creation_date FROM financial_operations WHERE financial_operations.id::text = new.start_id::text)) AND financial_operations.remote_creation_date <= (( SELECT financial_operations.remote_creation_date FROM financial_operations WHERE financial_operations.id::text = new.end_id::text)) AND financial_operations.order_transaction_id IS NOT NULL AND CASE WHEN new.lot_id IS NULL THEN new.cashier_id::text = (SELECT order_transactions.user_id FROM order_transactions WHERE order_transactions.id::text = financial_operations.order_transaction_id::text)::text ELSE ((new.cashier_id::text, new.lot_id) = ( SELECT order_transactions.user_id, order_transactions.lot_id FROM order_transactions WHERE order_transactions.id::text = financial_operations.order_transaction_id::text)) END; );

Editor's Notes

  • #2: This is a presentation about the Rules feature of Postgres.\n\nIn brief, Rules are a sometimes more efficient alternative to triggers, which function by rewriting incoming SQL.\n\nThey can be massively faster than triggers, and they give you great flexibility in creating writable views, but the expectation that they should work like triggers when they don&amp;#x2019;t can induce some subtle and dangerous errors.\n
  • #3: To speak of code in the server to a Rails using audience is of course to engage in heresy. Nevertheless, I believe that for performance, reliability and security reasons, code in the database can be just the thing.\n
  • #4: Here is how we create a Rule\n
  • #5: I should emphasize that Rules are esoteric. Meaning that for most purposes, you don&amp;#x2019;t need Rules. If triggers will work for you and are fast enough, use triggers.\n\nRules are for two specific uses:\n1. Writable views; and\n2. Code that runs on insert, update or delete that runs fast when you are doing a *bulk* insert, update or delete.\n
  • #6: Why not just use a trigger?\n\nIf you do a bulk insert, update or delete, your trigger will run at least once for each affected row. This can be deadly slow. Many developers avoid triggers for this specific reason.\n
  • #7: Worth pointing out that you&amp;#x2019;re probably already employing Rules: Postgres implements views using Rules.\n
  • #8: A Postgres view is just a dummy table with a Rule that runs on SELECT that instead runs the query underlying the view\n
  • #9: So speed is one of the reason to use Rules. A rule will only run once, no matter how man rows you&amp;#x2019;re affecting, so a Rule won&amp;#x2019;t be affected at all by the problem affecting triggers.\n
  • #10: If you&amp;#x2019;re contemplating using Rules, please head a serious warning. You can really do things wrong if you don&amp;#x2019;t really understand how Rules work, or if you don&amp;#x2019;t test carefully.\n
  • #11: Here is the page you have to read, *carefully* if you&amp;#x2019;re contemplating using Rules.\n\nIt&amp;#x2019;s dry as dust. I&amp;#x2019;ve encountered more readable EULAs. But there is information in there you *must* understand. Because your intuitions *will* grievously mislead you otherwise.\n
  • #12: Here, for example, is the crucial point about an INSTEAD rule.\n\nYou *must* remember that a Rule doesn&amp;#x2019;t run its condition and *then* rewrite the query. Instead, it modifies the query and runs that, to similar but by no means identical effect.\n
  • #13: One of the first things many ask about when they discover Rules is how to do an upsert (insert if not present; update if it is).\n\nSo they do something like this&amp;#x2026;\n
  • #14: One of the first things many ask about when they discover Rules is how to do an upsert (insert if not present; update if it is).\n\nSo they do something like this&amp;#x2026;\n
  • #15: One of the first things many ask about when they discover Rules is how to do an upsert (insert if not present; update if it is).\n\nSo they do something like this&amp;#x2026;\n
  • #16: If you really stare at the conversion, you can see why the rule turns an insert of (1, 1) into a result of (1, 2). But it sure isn&amp;#x2019;t obvious from the Rule that this is what will happen.\n
  • #17: If you really stare at the conversion, you can see why the rule turns an insert of (1, 1) into a result of (1, 2). But it sure isn&amp;#x2019;t obvious from the Rule that this is what will happen.\n
  • #18: If you really stare at the conversion, you can see why the rule turns an insert of (1, 1) into a result of (1, 2). But it sure isn&amp;#x2019;t obvious from the Rule that this is what will happen.\n
  • #19: If you really stare at the conversion, you can see why the rule turns an insert of (1, 1) into a result of (1, 2). But it sure isn&amp;#x2019;t obvious from the Rule that this is what will happen.\n
  • #20: If you really stare at the conversion, you can see why the rule turns an insert of (1, 1) into a result of (1, 2). But it sure isn&amp;#x2019;t obvious from the Rule that this is what will happen.\n
  • #21: Here is another example. Because the insert has a dynamic function in it, the query rewrite gives you different results in the log table than what was inserted into the original table.\n
  • #22: Here is another example. Because the insert has a dynamic function in it, the query rewrite gives you different results in the log table than what was inserted into the original table.\n
  • #23: Here is another example. Because the insert has a dynamic function in it, the query rewrite gives you different results in the log table than what was inserted into the original table.\n
  • #24: Here is another example. Because the insert has a dynamic function in it, the query rewrite gives you different results in the log table than what was inserted into the original table.\n
  • #25: Here is another example. Because the insert has a dynamic function in it, the query rewrite gives you different results in the log table than what was inserted into the original table.\n
  • #26: Here is another example. Because the insert has a dynamic function in it, the query rewrite gives you different results in the log table than what was inserted into the original table.\n
  • #27: Let&amp;#x2019;s see a real-world example.\n
  • #28: I&amp;#x2019;ve a set of financial operations (credit card and cash receipts). These are &amp;#x201C;covered&amp;#x201D; by reconciliations. All the operations between a start and end time stamp by a particular operator are covered by the single reconciliation.\n\nThe question becomes how to maintain the relationship? We could include the start and end timestamps in the reconciliations table, but then to determine the reconciliation for a financial operation is a bit of a hassle.\n\nOr we could point a financial operation at its reconciliation, but we need to enforce that the financial operations in a block are all covered by the same reconciliation.\n
  • #29: We put the foreign key on financial_operations because that&amp;#x2019;s reasonably easy to work with from either end of the relationship.\n\nThen we create a reconciliations view that pulls in the results of that relationship.\n
  • #30: We put the foreign key on financial_operations because that&amp;#x2019;s reasonably easy to work with from either end of the relationship.\n\nThen we create a reconciliations view that pulls in the results of that relationship.\n
  • #31: We create a rule in two parts:\n\nThe first updates the reconciliations_data table.\n\nNote the &amp;#x201C;returning&amp;#x201D; clause can go just fine on the first query. You can only have one &amp;#x201C;returning&amp;#x201D;, but it doesn&amp;#x2019;t have to be on the last statement.\n
  • #32: The second part updates the matching financial_operations records.\n\nThe results are simple and effective, and we can update many thousands of financial_operations records with a single insert to the view.\n
  • #33: \n