如何添加列,如果不存在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
regclass
和regtype
为_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。