sql >> データベース >  >> RDS >> PostgreSQL

Postgresql-レコードが存在しない場合はレコードを挿入し、存在する場合は更新するクリーンな方法

    わかりました、私はなんとかテストケースを作成することができました。その結果、新しい挿入であっても、更新部分は常に実行されます。 COPYはルールシステムをバイパスしているようです。[わかりやすくするために、これを別の返信に入れました]

    DROP TABLE pages CASCADE;
    CREATE TABLE pages
        ( url VARCHAR NOT NULL  PRIMARY KEY
        , html VARCHAR
        , last TIMESTAMP
        );
    
    INSERT INTO pages(url,html,last) VALUES ('www.example.com://page1' , 'meuk1' , '2001-09-18 23:30:00'::timestamp );
    
    CREATE RULE Pages_Upsert AS ON INSERT TO pages
      WHERE EXISTS (SELECT 1 from pages P where NEW.url = P.url)
         DO INSTEAD (
         UPDATE pages SET html=new.html , last = NOW() WHERE url = NEW.url
        );
    
    INSERT INTO pages(url,html,last) VALUES ('www.example.com://page2' , 'meuk2' , '2002-09-18 23:30:00':: timestamp );
    INSERT INTO pages(url,html,last) VALUES ('www.example.com://page3' , 'meuk3' , '2003-09-18 23:30:00':: timestamp );
    
    INSERT INTO pages(url,html,last) SELECT pp.url || '/added'::text, pp.html || '.html'::text , pp.last + interval '20 years' FROM pages pp;
    
    COPY pages(url,html,last) FROM STDIN;
    www.example.com://pageX     stdin   2000-09-18 23:30:00
    \.
    
    SELECT * FROM pages;
    

    結果:

                  url              |    html    |            last            
    -------------------------------+------------+----------------------------
     www.example.com://page1       | meuk1      | 2001-09-18 23:30:00
     www.example.com://page2       | meuk2      | 2011-09-18 23:48:30.775373
     www.example.com://page3       | meuk3      | 2011-09-18 23:48:30.783758
     www.example.com://page1/added | meuk1.html | 2011-09-18 23:48:30.792097
     www.example.com://page2/added | meuk2.html | 2011-09-18 23:48:30.792097
     www.example.com://page3/added | meuk3.html | 2011-09-18 23:48:30.792097
     www.example.com://pageX       | stdin      | 2000-09-18 23:30:00
     (7 rows)
    

    更新:それができることを証明するためだけに:

    INSERT INTO pages(url,html,last) VALUES ('www.example.com://page1' , 'meuk1' , '2001-09-18 23:30:00'::timestamp );
    CREATE VIEW vpages AS (SELECT * from pages);
    
    CREATE RULE Pages_Upsert AS ON INSERT TO vpages
      DO INSTEAD (
         UPDATE pages p0
         SET html=NEW.html , last = NOW() WHERE p0.url = NEW.url
        ;
         INSERT INTO pages (url,html,last)
        SELECT NEW.url, NEW.html, NEW.last
            WHERE NOT EXISTS ( SELECT * FROM pages p1 WHERE p1.url = NEW.url)
        );
    
    CREATE RULE Pages_Indate AS ON UPDATE TO vpages
      DO INSTEAD (
         INSERT INTO pages (url,html,last)
        SELECT NEW.url, NEW.html, NEW.last
            WHERE NOT EXISTS ( SELECT * FROM pages p1 WHERE p1.url = OLD.url)
            ;
         UPDATE pages p0
         SET html=NEW.html , last = NEW.last WHERE p0.url = NEW.url
            ;
        );
    
    INSERT INTO vpages(url,html,last) VALUES ('www.example.com://page2' , 'meuk2' , '2002-09-18 23:30:00':: timestamp );
    INSERT INTO vpages(url,html,last) VALUES ('www.example.com://page3' , 'meuk3' , '2003-09-18 23:30:00':: timestamp );
    
    INSERT INTO vpages(url,html,last) SELECT pp.url || '/added'::text, pp.html || '.html'::text , pp.last + interval '20 years' FROM vpages pp;
    UPDATE vpages SET last = last + interval '-10 years' WHERE url = 'www.example.com://page1' ;
    
    -- Copy does NOT work on views
    -- COPY vpages(url,html,last) FROM STDIN;
    -- www.example.com://pageX    stdin    2000-09-18 23:30:00
    -- \.
    
    SELECT * FROM vpages;
    

    結果:

    INSERT 0 1
    INSERT 0 1
    INSERT 0 3
    UPDATE 1
                  url              |    html    |        last         
    -------------------------------+------------+---------------------
     www.example.com://page2       | meuk2      | 2002-09-18 23:30:00
     www.example.com://page3       | meuk3      | 2003-09-18 23:30:00
     www.example.com://page1/added | meuk1.html | 2021-09-18 23:30:00
     www.example.com://page2/added | meuk2.html | 2022-09-18 23:30:00
     www.example.com://page3/added | meuk3.html | 2023-09-18 23:30:00
     www.example.com://page1       | meuk1      | 1991-09-18 23:30:00
    (6 rows)
    

    このビューは、書き換えシステムが再帰的にならないようにするために必要です。DELETEルールの作成は、読者の練習問題として残されています。



    1. PDOを使用してPHPでMySQLデータベースのリストを取得するにはどうすればよいですか?

    2. Postgresの単純な「ピボット」テーブル

    3. PHPを使用してmySQLiクエリから各行をエコーする方法は?

    4. JPAとHibernateが非レイジーコレクションエラーを初期化する