如何添加列,如果不存在PostgreSQL?

问题很简单。 如何添加列x到表y ,但只有当x列不存在? 我在这里find唯一的解决scheme如何检查列是否存在。

 SELECT column_name FROM information_schema.columns WHERE table_name='x' and column_name='y'; 

下面是使用“DO”语句的简短版本:

 DO $$ BEGIN BEGIN ALTER TABLE <table_name> ADD COLUMN <column_name> <column_type>; EXCEPTION WHEN duplicate_column THEN RAISE NOTICE 'column <column_name> already exists in <table_name>.'; END; END; $$ 

您不能将这些参数作为parameter passing,您需要在客户端的string中进行variablesreplace,但这是一个自包含的查询,如果该列已经存在,则只发出一条消息,如果不存在则添加;将继续失败的其他错误(如无效的数据types)。

如果这些方法是来自外部源的随机string,我不build议使用这些方法中的任何一种。 不pipe你使用什么方法(作为查询执行的cleint-side或者服务器端的dynamicstring),它都会给你带来SQL注入攻击。

使用Postgres 9.6 , if not exists可以使用该选项来完成

 ALTER TABLE table_name ADD COLUMN IF NOT EXISTS column_name INTEGER; 
 CREATE OR REPLACE function f_add_col(_tbl regclass, _col text, _type regtype) RETURNS bool AS $func$ BEGIN IF EXISTS (SELECT 1 FROM pg_attribute WHERE attrelid = _tbl AND attname = _col AND NOT attisdropped) THEN RETURN FALSE; ELSE EXECUTE format('ALTER TABLE %s ADD COLUMN %I %s', _tbl, _col, _type); RETURN TRUE; END IF; END $func$ LANGUAGE plpgsql; 

呼叫:

 SELECT f_add_col('public.kat', 'pfad1', 'int'); 

返回TRUE成功,否则FALSE (列已经存在)。
引发无效表或types名称的例外。

为什么另一个版本

  • 这可以用DO语句来完成,但是DO语句不能返回任何东西。 如果是反复使用,我会创build一个函数。

  • 我使用对象标识符types regclassregtype_tbl_type哪些a)防止SQL注入和b)立即检查(最便宜的方式)的有效性。 列名_col仍然需要使用quote_ident()进行EXECUTE消毒。 更多解释在这个相关的答案:

    • 表名称作为PostgreSQL函数参数
  • format()需要Postgres 9.1+。 对于旧版本手动连接:

     EXECUTE 'ALTER TABLE ' || _tbl || ' ADD COLUMN ' || quote_ident(_col) || ' ' || _type; 
  • 您可以使用模式来限定您的表名,但是您不必这样做。
    你可以在函数调用中加双引号以保留骆驼大小写和保留字(但是你不应该使用这些)。

  • 我查询pg_catalog而不是information_schema 。 详细说明:

    • 如何检查给定模式中是否存在表格
  • 包含像当前接受的答案一样的 EXCEPTION子句的块大大慢了。 这通常更简单和更快。 文档:

提示:包含EXCEPTION子句的块比没有块的块更昂贵。 因此,不要在没有需要的情况下使用EXCEPTION

以下select查询将返回true/false ,使用EXISTS()函数。

EXISTS()
EXISTS的参数是一个任意的SELECT语句或子查询。 子查询被评估以确定它是否返回任何行。 如果返回至less一行,则EXISTS的结果为“true”; 如果子查询不返回任何行,则EXISTS的结果为“false”

 SELECT EXISTS( SELECT column_name FROM information_schema.columns WHERE table_schema='public' and table_name='x' and column_name='y') 

并使用下面的dynamicsql语句来改变你的表

 DO $$ BEGIN IF not EXISTS (SELECT column_name FROM information_schema.columns WHERE table_schema='public' and table_name='x' and column_name='y') THEN alter table x add column y int default null ; else raise NOTICE 'Already exists'; END IF; END $$ 

下面的函数将检查列是否存在返回适当的消息,否则它会将列添加到表中。

 create or replace function addcol(schemaname varchar, tablename varchar, colname varchar, coltype varchar) returns varchar language 'plpgsql' as $$ declare col_name varchar ; begin execute 'select column_name from information_schema.columns where table_schema = ' || quote_literal(schemaname)||' and table_name='|| quote_literal(tablename) || ' and column_name= '|| quote_literal(colname) into col_name ; raise info ' the val : % ', col_name; if(col_name is null ) then col_name := colname; execute 'alter table ' ||schemaname|| '.'|| tablename || ' add column '|| colname || ' ' || coltype; else col_name := colname ||' Already exist'; end if; return col_name; end; $$ 

这基本上是从sola的解决scheme,但只是清理了一下。 不同的是,我不只是想“改善”他的解决scheme(再加上,我觉得这是粗鲁的)。

主要区别在于它使用EXECUTE格式。 我认为这是一个更清洁,但我相信意味着你必须在PostgresSQL 9.1或更新。

这已经过testing9.1和工作。 注意:如果schema / table_name /或data_type无效,将会引发错误。 这可以“固定”,但在许多情况下可能是正确的行为。

 CREATE OR REPLACE FUNCTION add_column(schema_name TEXT, table_name TEXT, column_name TEXT, data_type TEXT) RETURNS BOOLEAN AS $BODY$ DECLARE _tmp text; BEGIN EXECUTE format('SELECT COLUMN_NAME FROM information_schema.columns WHERE table_schema=%L AND table_name=%L AND column_name=%L', schema_name, table_name, column_name) INTO _tmp; IF _tmp IS NOT NULL THEN RAISE NOTICE 'Column % already exists in %.%', column_name, schema_name, table_name; RETURN FALSE; END IF; EXECUTE format('ALTER TABLE %I.%I ADD COLUMN %I %s;', schema_name, table_name, column_name, data_type); RAISE NOTICE 'Column % added to %.%', column_name, schema_name, table_name; RETURN TRUE; END; $BODY$ LANGUAGE 'plpgsql'; 

用法:

 select add_column('public', 'foo', 'bar', 'varchar(30)'); 

可以添加到迁移脚本中调用函数并在完成时删除。

 create or replace function patch_column() returns void as $$ begin if exists ( select * from information_schema.columns where table_name='my_table' and column_name='missing_col' ) then raise notice 'missing_col already exists'; else alter table my_table add column missing_col varchar; end if; end; $$ language plpgsql; select patch_column(); drop function if exists patch_column(); 

你可以通过以下方式来完成。

 ALTER TABLE tableName drop column if exists columnName; ALTER TABLE tableName ADD COLUMN columnName character varying(8); 

所以如果它已经存在,它将会丢弃这个列。 然后将列添加到特定的表。

只需检查查询是否返回了一个column_name。

如果没有,执行这样的事情:

 ALTER TABLE x ADD COLUMN y int; 

在那里你把一些有用的'x'和'y'当然是一个合适的数据types,我用int。