게시물:제약 조건이 없는 경우 제약 조건 추가
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);')
업데이트됨:
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
'programing' 카테고리의 다른 글
| 문자열 배열에서 모든 빈 요소 제거 (0) | 2023.05.10 |
|---|---|
| 동일한 라인에 새 출력 인쇄 (0) | 2023.05.10 |
| 여러 시작 프로젝트 간의 Visual Studio 지연? (0) | 2023.05.10 |
| jQuery를 사용하여 입력이 비어 있는지 확인합니다. (0) | 2023.05.10 |
| Mongoose 스키마 선택사항 필드 (0) | 2023.05.10 |