programing

게시물:제약 조건이 없는 경우 제약 조건 추가

jooyons 2023. 5. 10. 20:51
반응형

게시물:제약 조건이 없는 경우 제약 조건 추가

Postgres가 할 말이 있습니까?ALTER TABLE foo ADD CONSTRAINT bar ...제약 조건이 이미 존재하는 경우 오류가 발생하지 않도록 명령을 무시하는 것은 무엇입니까?

가능한 해결책은 새 제약 조건을 작성하기 전에 단순히 DROP IF EXPRESS를 사용하는 것입니다.

ALTER TABLE foo DROP CONSTRAINT IF EXISTS bar;
ALTER TABLE foo ADD CONSTRAINT bar ...;

information_schema 또는 카탈로그를 쿼리하는 것보다 쉬워 보이지만 항상 제약 조건을 다시 만들기 때문에 큰 테이블에서는 느릴 수 있습니다.

2015-07-13 편집: Kev는 답변에서 제약이 존재하지 않고 시행되지 않을 때 내 솔루션이 짧은 창을 만든다고 지적했습니다.이는 사실이지만 두 문을 모두 트랜잭션으로 묶으면 이러한 창을 쉽게 피할 수 있습니다.

이것은 도움이 될 수도 있지만, 약간 더러운 해킹일 수도 있습니다.

create or replace function create_constraint_if_not_exists (
    t_name text, c_name text, constraint_sql text
) 
returns void AS
$$
begin
    -- Look for our constraint
    if not exists (select constraint_name 
                   from information_schema.constraint_column_usage 
                   where table_name = t_name  and constraint_name = c_name) then
        execute constraint_sql;
    end if;
end;
$$ language 'plpgsql'

그런 다음 전화:

SELECT create_constraint_if_not_exists(
        'foo',
        'bar',
        'ALTER TABLE foo ADD CONSTRAINT bar CHECK (foobies < 100);')

업데이트됨:

아래 Webmut의 답변에 따르면 다음과 같습니다.

ALTER TABLE foo DROP CONSTRAINT IF EXISTS bar;
ALTER TABLE foo ADD CONSTRAINT bar ...;

개발 데이터베이스나 유지 관리 기간 동안 이 데이터베이스에 의존하는 앱을 차단할 수 있는 경우에는 문제가 없을 수 있습니다.

그러나 이 환경이 24x7로 운영되는 생동감 넘치는 미션 크리티컬 운영 환경이라면 이런 식으로 제약을 완화하고 싶지 않을 것입니다.몇 밀리초 동안이라도 더 이상 제약 조건을 적용하지 않는 짧은 창이 있으므로 잘못된 값이 무시될 수 있습니다.이로 인해 향후 상당한 비즈니스 비용이 발생할 수 있습니다.

익명 DO 블록 내부의 예외 처리기를 사용하여 중복 개체 오류를 탐지할 수 있습니다.

DO $$
BEGIN

  BEGIN
    ALTER TABLE foo ADD CONSTRAINT bar ... ;
  EXCEPTION
    WHEN duplicate_table THEN  -- postgres raises duplicate_table at surprising times. Ex.: for UNIQUE constraints.
    WHEN duplicate_object THEN
      RAISE NOTICE 'Table constraint foo.bar already exists';
  END;

END $$;

http://www.postgresql.org/docs/9.4/static/sql-do.html http://www.postgresql.org/docs/9.4/static/plpgsql-control-structures.html http://www.postgresql.org/docs/9.4/static/errcodes-appendix.html

테이블 위에서 쿼리를 실행하여 제약 조건의 존재 여부를 확인할 수 있습니다.

SELECT 1 FROM pg_constraint WHERE conname = 'constraint_name'"

제약 조건을 만드는 것은 많은 데이터를 포함하는 테이블에서 비용이 많이 드는 작업일 수 있으므로 제약 조건을 삭제하지 말고 즉시 다시 만드는 것이 좋습니다. 단 한 번만 해당 제약 조건을 만드는 것이 좋습니다.

저는 Mike Stankavich와 매우 유사한 익명 코드 블록을 사용하여 이 문제를 해결하기로 결정했습니다. 하지만 Mike와 달리 (오류를 잡는) 제약 조건이 존재하는지 먼저 확인합니다.

DO $$
BEGIN
    IF NOT EXISTS ( SELECT  constraint_schema
                ,       constraint_name 
                FROM    information_schema.check_constraints 
                WHERE   constraint_schema = 'myschema'
                  AND   constraint_name = 'myconstraintname'
              )
    THEN
        ALTER TABLE myschema.mytable ADD CONSTRAINT myconstraintname CHECK (column <= 100);
    END IF;
END$$; 

information_schema.constraint_column_usage를 사용하여 제약 조건을 확인하는 것은 외부 키에 대해 작동하지 않습니다.pg_constraint를 사용하여 기본 키, 외부또는 고유 제약 조건을 확인합니다.

CREATE OR REPLACE FUNCTION add_constraint(t_name text, c_name text, constraint_sql text)
RETURNS void
AS $$
BEGIN
    IF NOT EXISTS(
            SELECT c.conname
            FROM pg_constraint AS c
            INNER JOIN pg_class AS t ON c.conrelid = t."oid"
            WHERE t.relname = t_name AND c.conname = c_name
    ) THEN

        EXECUTE 'ALTER TABLE ' || t_name || ' ADD CONSTRAINT ' || c_name || ' ' || constraint_sql;

    END IF;
END;
$$
LANGUAGE plpgsql;

예:

SELECT add_constraint('client_grant_system_scopes', 'client_grant_system_scopes_pk', 'PRIMARY KEY (client_grants_id, tenant, "scope");');

SELECT add_constraint('client_grant_system_scopes', 'client_grant_system_scopes_fk', 'FOREIGN KEY (tenant,"scope") REFERENCES system_scope(tenant,"scope") ON DELETE CASCADE;');

SELECT add_constraint('jwt_assertion_issuers', 'jwt_assertion_issuers_issuer_key', 'UNIQUE (issuer);');

의 이점을 활용하여 세부 정보를 줄이고 성능을 향상시키며 스키마 간의 테이블 명명 충돌과 관련된 오류를 방지할 수 있습니다.

DO $$ BEGIN
    IF NOT EXISTS (SELECT FROM pg_constraint 
                   WHERE conrelid = 'foo'::regclass AND conname = 'bar') THEN 
        ALTER TABLE foo ADD CONSTRAINT bar...;
    END IF;
END $$;

이는 다른 스키마의 테이블에도 적용됩니다. 예를 들어 다음과 같습니다.

DO $$ BEGIN
    IF NOT EXISTS (SELECT FROM pg_constraint 
                   WHERE conrelid = 's.foo'::regclass AND conname = 'bar') THEN 
        ALTER TABLE s.foo ADD CONSTRAINT bar...;
    END IF;
END $$;

psql 생성된 쿼리 실행에 대해 meta 명령 \gexec을 사용할 수 있습니다.

SELECT 'ALTER TABLE xx ADD CONSTRAINT abc' WHERE not EXISTS (SELECT True FROM pg_constraint WHERE conname = 'abc') \gexec

제약 조건이 기본 키였기 때문에 이러한 솔루션은 작동하지 않았습니다.이것은 나에게 효과가 있었습니다.

ALTER TABLE <table.name> DROP CONSTRAINT  IF EXISTS <constraint.name> CASCADE;

위에서 언급한 모든 답변을 고려할 때, 삽입하려는 테이블에 제약 조건이 있는지 확인하고 알림이 발생할 경우 아래의 접근 방식이 도움이 됩니다.

DO 
$$ BEGIN
IF NOT EXISTS (select constraint_name 
               from information_schema.table_constraints 
               where table_schema='schame_name' and upper(table_name) = 
upper('table_name')  and upper(constraint_name) = upper('constraint_name'))

THEN

   ALTER TABLE TABLE_NAME ADD CONSTRAINT CONTRAINT_NAME..... ;

ELSE raise NOTICE 'Constraint CONTRAINT_NAME already exists in Table TABLE_NAME';   

END IF;
END
$$;

코드 줄이 왜 이렇게 많은지 모르겠어요?

dbo에서 "Column1", "Column2", "Column3", 카운트(별)를 선택합니다."내 표" 그룹은 "1열", "2열", "3열"로 카운트(*) > 1;

식탁을 바꾸다, 개변하다, 개변하다, 개변하다, 개변하다"MyConstraint_Name"이 있는 경우 "MyTable" 드롭 제약 조건;

ALTER 테이블 대시보드."MyTable" ADD 제약 조건 "MyConstraint_Name" UNIKE("Column1", "Column3", "Column2");

언급URL : https://stackoverflow.com/questions/6801919/postgres-add-constraint-if-it-doesnt-already-exist

반응형