source

고유성 제약 조건을 조건부로 적용할 수 있습니까?

nicesource 2023. 11. 5. 14:43
반응형

고유성 제약 조건을 조건부로 적용할 수 있습니까?

내 데이터베이스에는 사용자 테이블이 있습니다.모든 활성 사용자는 고유한 사용자 이름을 가집니다.사용자를 비활성화하고 사용 중인 사용자 이름을 해제할 수 있지만 동일한 테이블에 보관하고 싶습니다.

고유성 제약 조건만 조건부로 적용할 수 있는 방법이 있습니까?

다음과 같은 열을 추가합니다.isactive. 가 고유한 제약 조건을 만듭니다.(username, isactive).

그러면 활성 사용자 이름과 비활성 사용자 이름을 동시에 가질 수 있습니다.두 개의 활성 사용자 이름을 가질 수 없습니다.

비활성화된 이름을 여러 개 사용하려면NULL의 가치를 위하여isactive.NULL값은 고유 인덱스에서 반복될 수 있습니다.

아니요, UNIECIAL 제약 조건은 "조건부"일 수 없습니다.

하나의 옵션은 다음을 설정하는 것입니다.username열에서 NULL로 이동합니다.UNIUIC 제약 조건은 NULL 값을 가진 여러 행을 허용합니다.

당신은 그것을 당신이 전시하기 원하는 어떤 문자열로도 번역할 수 있습니다.응용 프로그램 또는 SQL에서

SELECT IFNULL(t.username,'USER DELETED') AS username
  FROM mytable t

기록/보관 목적으로 이 행들을 유지하는 경우, 아마도 업데이트를 원하지 않을 것입니다.usernamecolumn. (값을 변경할 경우usernamecolumn(열) 그러면 다음 문장에서 이전 사용자 이름과 동일한 값의 행을 삽입할 수 있습니다.)

대신 테이블에 추가 열을 추가하여 "사용자 삭제" 조건을 나타낼 수 있습니다.예를 들어,

user_deleted TINYINT(1) UNSIGNED DEFAULT 0 COMMENT 'boolean' 

당신은 이 컬럼을 확인하고 반환할 수 있습니다.'USER DELETED'사용자 이름 열 대신 상수.user_deleted부울이 설정됨:

SELECT IF(u.user_deleted,'USER DELETED',u.username) AS username

(논리적인 "사용자 삭제" 조건을 나타내려면 1 값을 사용합니다.)

이 접근 방식의 가장 큰 장점은username열을 수정할 필요가 없습니다.usernamevalue, UNIECIAL 제약 조건을 사용하면 사용자 이름이 중복된 새 행이 삽입되지 않습니다.

동일한 결과를 얻기 위한 다른 방법.질문에 실제로 필요하지 않을 수도 있습니다.참고로 말입니다.

  1. 삽입/업데이트 시 트리거 만들기
  2. 현재(NEW) 레코드 값으로 중복된 레코드가 있는지 확인합니다.
    a. 중복 카운트를 통해 이를 확인하거나 동일한 값을 가진 다른 레코드를 확인할 수 있지만 기본 키가 다릅니다.
  3. 발견된 경우 신호를 올려 오류를 던집니다.

조건이 복잡하여 고유성을 결정하는 경우 가장 적합합니다.또한 성능 비용도 고려해야 합니다.

견본

DELIMITER $$

CREATE TRIGGER `my_trigger` BEFORE INSERT/UPDATE
    ON `usertable`
    FOR EACH ROW BEGIN

    IF EXISTS (SELECT 1 FROM usertable WHERE userid <> NEW.userid AND username = NEW.username AND isactive = 1) THEN 
        SELECT CONCAT(NEW.username, ' exists !') INTO @error_text; 



     SIGNAL SQLSTATE '45000' SET message_text = @error_text; 
    END IF;
    END$$

DELIMITER ;

FORMER_NAME이라는 다른(고유하지 않은) 필드를 만들고 사용자가 비활성화되면 원래 이름을 해당 필드로 이동합니다.가능하지 않은 특별한 고유성 제약이 필요 없습니다.

아니요, 고유 인덱스(따라서 이름)가 있는 경우 중복을 가질 수 없습니다.각 레코드를 고유하게 만들기 위해 추가 열을 추가합니다.또는 값을 고유하게 변경합니다.

권장되지 않지만 예를 들어 "USER DELETED 2013/08/17:233805" 타임스탬프를 추가할 수 있습니다.

이것이 제가 비슷한 문제를 만났을 때의 해결책입니다.

열을 비활성으로 추가하므로 고유 키는 다음과 같습니다. (username, inactive)

inactive, inactive = 0은 사용자가 활성임을 의미하며 inactive > 0은 사용자가 활성임을 의미합니다.

사용자를 비활성화 할 때는 평소처럼 1개가 아닌 비활성 = user_id만 설정하면 됩니다!

이제 비활성 사용자에게는 중복된 사용자 이름을 허용하지만 활성 사용자에게는 고유한 사용자 이름만 허용합니다.

nullable 기능을 제공하는 생성된 열을 추가하여 @gordon-linoff 답변을 확장했습니다.나는 나중에 코드를 작성할 때 이 null 동작을 실수로 잊어버림으로써 혼란스럽지 않고 엉망이 되지 않는 읽고 쓸 수 있는 확실한 true 및 false 값을 가진 true not null active 열을 가지고 싶습니다.그래서 나는 특정 이름을 가진 열을 계산한 다음 제약 조건에 그 값을 사용하므로 nullable 고유의 active 동작을 얻지만 active 열을 내가 원하는 대로 사용할 수 있습니다.

isactive BOOL NOT NULL,
_isactive_constraint_key_ BOOL AS (CASE WHEN isactive IS true THEN true END),
CONSTRAINT active_user UNIQUE(username, _isactive_constraint_key)

언급URL : https://stackoverflow.com/questions/18293543/can-i-conditionally-enforce-a-uniqueness-constraint

반응형