2009-04-08 15 views
3

postgreSQLスキーマの変更を冪等の方法でスクリプト化する方法を探しています。Idempotent PostgreSQL DDLスクリプト

私はこのような何か行うことができますMSSQLで

if(not exists(select * from information_schema.columns where table_name = 'x' and column_name = 'y')) 
begin 
    alter table x add y int 
end 
go 

PostgreSQLは、私がコントロールを使用することはできませんので、MSSQLは、T-SQLと同じ方法でアドホックにPL/pgSQL許可していないようですが構造体をSQLスクリプト内に作成し、psql -f x.sqlを使用して実行します。

オブジェクトが既に存在していてもエラーを無視したくない場合、PostgreSQLはエラーをスローすることがわかります。

私はdbdeployのようなスキーマのバージョン管理テクニックを使用することができましたが、望ましくない副作用を起こさずに一連のファイルをpsqlで実行することが簡単です。

これは可能ですか?

おかげで、 マーク

答えて

2

あなたはplpgsqlを使用することができるはずです。

create language plpgsql; 
create function f() ... as $$ 
<plpgsql code> 
$$language plpgsql; 
select f(); 
3

は免責事項:私は知っている、これは非常に古いですすでに回答があります。

しかし、ここでは、外部リンクなしで完全に冪等のスクリプトを登録したいと思います。


PostgreSQL 9.5以上の冪等の組み込み機能を示す簡単なスクリプトです。このスクリプトは、何度でも実行することができます。 ここに行きます:

--Table 
CREATE TABLE IF NOT EXISTS person (
    id integer NOT NULL, 
    person_name character varying(40) NOT NULL, 
    updated_date date, 
    CONSTRAINT person_pkey PRIMARY KEY (id) 
); 

--Index 
CREATE INDEX IF NOT EXISTS idx_person_name ON person (person_name); 

--Sequence 
CREATE SEQUENCE IF NOT EXISTS seq_person_inc; 

--Function 
CREATE OR REPLACE FUNCTION simple_sum(a_integer int, b_integer int) RETURNS INT 
    AS $$ SELECT a_integer+b_integer $$ 
LANGUAGE SQL; 

--View 
CREATE OR REPLACE VIEW vw_select_1 AS 
    SELECT 1; 

--Role 
DO $$ 
BEGIN 
    CREATE ROLE rick_deckard;  
EXCEPTION 
    WHEN duplicate_object THEN 
     RAISE NOTICE 'Role already exists. Ignoring...';  
END$$; 

--Simple insert 
INSERT INTO person (id, person_name) VALUES (1, 'HAL-9000'); 

--Upsert (insert + update) 
INSERT INTO person (id, person_name) VALUES (1, 'Betrayer') ON CONFLICT ON CONSTRAINT person_pkey DO UPDATE SET person_name = EXCLUDED.person_name; 

--Upsert (ignoring duplicate error) 
INSERT INTO person (id, person_name) VALUES (1, 'HAL-9000') ON CONFLICT ON CONSTRAINT person_pkey DO NOTHING; 

--Upsert (ignoring any error) 
INSERT INTO person (id, person_name) VALUES (1, 'HAL-9000') ON CONFLICT DO NOTHING; 

--Field 
DO $$ 
BEGIN 
    ALTER TABLE person ADD COLUMN id_another_person INTEGER; 
EXCEPTION 
    WHEN duplicate_column THEN 
     RAISE NOTICE 'Field already exists. Ignoring...'; 
END$$; 

--Constraint 
DO $$ 
BEGIN 
    ALTER TABLE person ADD CONSTRAINT person_id_another_person_fkey FOREIGN KEY (id_another_person) REFERENCES person (id); 
EXCEPTION 
    WHEN duplicate_object THEN 
     RAISE NOTICE 'Constraint already exists. Ignoring...'; 
END$$; 

--Trigger 
CREATE OR REPLACE FUNCTION person_trigger_function() RETURNS trigger AS $BODY$ 
BEGIN 
    --Something complex here =) 
    RETURN NEW; 
END; 
$BODY$ 
LANGUAGE plpgsql; 

DO $$ 
BEGIN 
    CREATE TRIGGER person_trigger BEFORE INSERT OR UPDATE ON person FOR EACH ROW EXECUTE PROCEDURE person_trigger_function(); 
EXCEPTION 
    WHEN duplicate_object THEN 
     RAISE NOTICE 'Trigger already exists. Ignoring...'; 
END$$; 

--Drop 
DROP TRIGGER IF EXISTS person_trigger ON person; 
DROP INDEX IF EXISTS idx_person_name; 
ALTER TABLE person DROP COLUMN IF EXISTS person_name; 
ALTER TABLE person DROP CONSTRAINT IF EXISTS person_id_another_person_fkey; 
DROP ROLE IF EXISTS rick_deckard; 
DROP VIEW IF EXISTS vw_select_1; 
DROP FUNCTION IF EXISTS simple_sum(integer, integer); 
DROP FUNCTION IF EXISTS person_trigger_function(); 
DROP TABLE IF EXISTS person; 
DROP SEQUENCE IF EXISTS seq_person_inc; 
関連する問題