首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >幂等PostgreSQL DDL脚本

幂等PostgreSQL DDL脚本
EN

Stack Overflow用户
提问于 2009-04-08 21:07:17
回答 3查看 5.8K关注 0票数 15

我正在寻找一种以幂等方式编写postgreSQL模式更改脚本的方法。

在MSSQL中,我可以这样做:

代码语言:javascript
复制
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运行一组文件的简单性,而不会产生任何不必要的副作用。

这个是可能的吗?

谢谢,马克

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-06-28 21:54:38

免责声明:我知道,这是一个非常古老的问题,而且已经有了公认的答案。

但我想在这里注册一个完全幂等的脚本,没有外部链接。

演示PostgreSQL 9.5+幂等内置功能的简单脚本。您可以根据需要多次运行此脚本。我们开始吧:

代码语言:javascript
复制
--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;
票数 20
EN

Stack Overflow用户

发布于 2009-04-08 22:15:45

你可能会发现这篇博文很有帮助:http://www.depesz.com/index.php/2008/06/18/conditional-ddl/

票数 7
EN

Stack Overflow用户

发布于 2009-04-08 22:33:05

您应该能够使用plpgsql

代码语言:javascript
复制
create language plpgsql;
create function f() ... as $$
<plpgsql code>
$$language plpgsql;
select f();
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/731851

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档