[postgresql] PostgreSQL에없는 경우 열을 추가하는 방법은 무엇입니까?

질문은 간단합니다. x테이블 에 열을 추가하는 방법 y, x열이 존재하지 않는 경우에만 ? 열이 존재하는지 확인하는 방법 만 여기 에서 해결책을 찾았습니다 .

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

이것들을 매개 변수로 전달할 수 없으며 클라이언트 측의 문자열에서 변수 대체를 수행해야하지만 열이 이미 존재하는 경우에만 메시지를 내보내고 그렇지 않은 경우 추가하는 자체 포함 쿼리입니다 다른 오류 (예 : 잘못된 데이터 유형)에서 계속 실패합니다.

외부 소스에서 오는 임의의 문자열 인 경우 이러한 방법 중 하나를 사용하지 않는 것이 좋습니다. 어떤 방법을 사용하든 (클린트 측 또는 서버 측 동적 문자열은 쿼리로 실행 됨) SQL 삽입 공격을 열 때 재난을위한 레시피가 될 것입니다.


답변

포스트 그레스 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(열이 이미 존재 함) 리턴 합니다.
유효하지 않은 테이블 또는 유형 이름에 대한 예외를 발생시킵니다.

왜 다른 버전입니까?

  • 이는 DO명령문 으로 수행 할 수 있지만 DO명령문은 아무것도 리턴 할 수 없습니다. 그리고 반복적으로 사용한다면 함수를 만들 것입니다.

  • I는 사용 객체 식별자 유형 regclassregtype_tbl하고 _type있는 a) SQL 인젝션 및 B) 모두의 즉시 유효성 검사 (최저가 가능한 방법)을 방지한다. 열 이름 _col은 여전히로 삭제해야 EXECUTE합니다 quote_ident(). 이 관련 답변에 대한 자세한 설명 :

  • 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 문 또는 하위 쿼리입니다. 부속 조회는 행을 리턴하는지 판별하기 위해 평가됩니다. 하나 이상의 행을 반환하면 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'); 

다음 동적 SQL 문을 사용하여 테이블을 변경하십시오.

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


답변

Postgre 9.5 이상을 사용하는 사람들에게는 (거의 대부분을 믿습니다) 매우 간단하고 깨끗한 해결책이 있습니다

ALTER TABLE if exists <tablename> add if not exists <columnname> <columntype>


답변

아래 함수는 존재하는 경우 열을 확인하여 적절한 메시지를 반환하고 그렇지 않으면 열을 테이블에 추가합니다.

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


답변

이것은 기본적으로 솔라의 해결책이지만 조금만 정리했습니다. 내가 그의 해결책을 “개선”하고 싶지 않다는 것은 충분히 다르다.

주요 차이점은 EXECUTE 형식을 사용한다는 것입니다. 좀 더 깨끗하다고 ​​생각하지만 PostgresSQL 9.1 이상을 사용해야한다는 것을 의미합니다.

이것은 9.1에서 테스트되었으며 작동합니다. 참고 : schema / table_name / or 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)');