185

質問は簡単です。xテーブルに列を追加する方法はありますが、列が存在しない場合yのみですか? ここで、列が存在するかどうかを確認する方法xのみを見つけました。

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

11 に答える 11

521

Postgres 9.6では、これはオプションを使用して実行できます。if not exists

ALTER TABLE table_name ADD COLUMN IF NOT EXISTS column_name INTEGER;
于 2016-08-02T13:33:07.760 に答える
147

「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;
$$

これらをパラメーターとして渡すことはできません。クライアント側の文字列で変数置換を行う必要がありますが、これは自己完結型のクエリであり、列が既に存在する場合にのみメッセージを発行し、存在しない場合は追加し、他のエラー (無効なデータ型など) では引き続き失敗します。

これらが外部ソースからのランダムな文字列である場合、これらのメソッドのいずれも実行することはお勧めしません。どの方法 (クエリとして実行されるクライアント側またはサーバー側の動的文字列) を使用しても、SQL インジェクション攻撃にさらされるため、災害のレシピとなります。

于 2012-09-26T18:59:08.023 に答える
26

Postgres9.6が追加されまし ALTER TABLE tbl ADD COLUMN IF NOT EXISTS column_nameた。
したがって、これは現在ほとんど時代遅れです。古いバージョンやバリエーションで、列名以外のものをチェックするために使用する場合があります。


CREATE OR REPLACE function f_add_col(_tbl regclass, _col  text, _type regtype)
  RETURNS bool
  LANGUAGE plpgsql AS
$func$
BEGIN
   IF EXISTS (SELECT 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$;

電話:

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

true成功した場合は戻ります。それ以外のfalse場合(列は既に存在します)。
無効なテーブルまたはタイプ名の例外を発生させます。

なぜ別のバージョン?

  • DOこれはステートメントを使用して実行できますが、DOステートメントは何も返すことができません。そして、繰り返し使用する場合は、関数を作成します。

  • 私はオブジェクト識別子タイプ regclassを使用regtype_tbl_typea)SQLインジェクションを防止し、b)両方の有効性を即座にチェックします(可能な限り最も安価な方法)。列名_colは、でサニタイズする必要がEXECUTEありquote_ident()ます。見る:

  • format()Postgres9.1以降が必要です。古いバージョンの場合、手動で連結します。

      EXECUTE 'ALTER TABLE ' || _tbl || ' ADD COLUMN ' || quote_ident(_col) || ' ' || _type;
    
  • テーブル名をスキーマ修飾することはできますが、そうする必要はありません。
    関数呼び出しで識別子を二重引用符で囲んで、キャメルケースと予約語を保持できます(ただし、これは使用しないでください)。

  • pg_catalogの代わりにクエリを実行しますinformation_schema。詳細な説明:

  • 句を含むブロックEXCEPTIONはかなり遅くなります。
    これはより簡単で高速です。マニュアル:

ヒント

句を含むブロックは、EXCEPTION句を含まないブロックよりも出入りするのにかなりの費用がかかります。したがって、必要なく使用しないでくださいEXCEPTION

于 2012-09-26T19:41:49.213 に答える
1

以下の関数は、存在する場合は列をチェックし、適切なメッセージを返します。そうでない場合は、列をテーブルに追加します。

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;
$$
于 2012-09-26T10:28:45.677 に答える
1

これは基本的には sola のソリューションですが、少しクリーンアップしただけです。彼のソリューションを「改善」したかっただけではないほど十分に異なっています(さらに、それは失礼だと思います)。

主な違いは、EXECUTE 形式を使用することです。これは少しきれいだと思いますが、PostgresSQL 9.1 以降を使用している必要があることを意味すると思います。

これは 9.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)');
于 2012-09-26T14:23:31.383 に答える
0

移行スクリプトに追加して関数を呼び出し、完了したら削除できます。

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();
于 2014-03-12T13:57:14.647 に答える
-2

次の方法でそれを行うことができます。

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

そのため、列が既に存在する場合は削除されます。次に、列を特定のテーブルに追加します。

于 2016-03-29T04:51:47.810 に答える
-4

クエリが column_name を返したかどうかを確認するだけです。

そうでない場合は、次のように実行します。

ALTER TABLE x ADD COLUMN y int;

「x」と「y」に役立つもの、そしてもちろん、int を使用した適切なデータ型を配置する場所。

于 2012-09-26T08:23:34.483 に答える