MySQL에서 NULL이 아닌 제약 조건을 생성하여 fieldA와 fieldB를 둘 다 NULL로 지정할 수없는 가장 좋은 방법은 무엇입니까? 다른 필드가 NULL이 아닌 값을 가지고있는 한, 어느 것이 든 자체적으로 NULL인지 상관하지 않습니다. 둘 다 NULL이 아닌 값을 가지고 있다면 더 좋습니다.MySQL에서 또는 null이 아닌 제약 조건
내가 SQL 서버에서 비슷한 짓을했는지답변
MySQL 5.5는 SIGNAL을 도입 했으므로 Bill Karwin의 대답에서 추가 열은 필요하지 않습니다. Bill은 업데이트를위한 트리거가 필요하다고 지적하여이를 포함 시켰습니다.
CREATE TABLE foo (
FieldA INT,
FieldB INT
);
DELIMITER //
CREATE TRIGGER InsertFieldABNotNull BEFORE INSERT ON foo
FOR EACH ROW BEGIN
IF (NEW.FieldA IS NULL AND NEW.FieldB IS NULL) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '\'FieldA\' and \'FieldB\' cannot both be null';
END IF;
END//
CREATE TRIGGER UpdateFieldABNotNull BEFORE UPDATE ON foo
FOR EACH ROW BEGIN
IF (NEW.FieldA IS NULL AND NEW.FieldB IS NULL) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '\'FieldA\' and \'FieldB\' cannot both be null';
END IF;
END//
DELIMITER ;
INSERT INTO foo (FieldA, FieldB) VALUES (NULL, 10); -- OK
INSERT INTO foo (FieldA, FieldB) VALUES (10, NULL); -- OK
INSERT INTO foo (FieldA, FieldB) VALUES (NULL, NULL); -- gives error
UPDATE foo SET FieldA = NULL; -- gives error
, 나는 그것이 MySQL을 직접 작동하는지 모르겠지만, :
ALTER TABLE tableName ADD CONSTRAINT constraintName CHECK ((fieldA IS NOT NULL) OR (fieldB IS NOT NULL));
가 적어도 나는 그 구문 믿습니다.
그러나 테이블간에 check 제약 조건을 만들 수는 없으므로 하나의 테이블에서만 열을 확인할 수 있습니다.
이 같은 제약 조건에 대한 표준 구문이지만, MySQL은 행복하게 제약 조건을 무시 이후
ALTER TABLE `generic`
ADD CONSTRAINT myConstraint
CHECK (
`FieldA` IS NOT NULL OR
`FieldB` IS NOT NULL
)
@Sklivvz : MySQL의 5.0.51a와 함께 테스트, 나는 그것이 CHECK 제약 조건을 구문 분석하지만 실행하지 않는 것을 발견 그것. (NULL, NULL)을 오류없이 삽입 할 수 있습니다. MyISAM과 InnoDB를 모두 테스트했습니다. SHOW CREATE TABLE을 사용하면 테이블을 정의 할 때 오류가 없더라도 CHECK 제약 조건이 테이블 정의에 없다는 것을 알 수 있습니다.
"CHECK 절은 모든 저장소 엔진에서 구문 분석되지만 무시됩니다."라는 MySQL manual과 일치합니다.
그래서 MySQL의 경우 트리거를 사용하여이 규칙을 적용해야합니다. 유일한 문제는 MySQL 트리거가 오류를 발생 시키거나 INSERT 작업을 중단 할 수 없다는 것입니다. 트리거에서 오류를 유발할 수있는 한 가지 방법은 NOT NULL 열을 NULL로 설정하는 것입니다.
CREATE TABLE foo (
FieldA INT,
FieldB INT,
FieldA_or_FieldB TINYINT NOT NULL;
);
DELIMITER //
CREATE TRIGGER FieldABNotNull BEFORE INSERT ON foo
FOR EACH ROW BEGIN
IF (NEW.FieldA IS NULL AND NEW.FieldB IS NULL) THEN
SET NEW.FieldA_or_FieldB = NULL;
ELSE
SET NEW.FieldA_or_FieldB = 1;
END IF;
END//
INSERT INTO foo (FieldA, FieldB) VALUES (NULL, 10); -- OK
INSERT INTO foo (FieldA, FieldB) VALUES (10, NULL); -- OK
INSERT INTO foo (FieldA, FieldB) VALUES (NULL, NULL); -- gives error
이전에 비슷한 트리거가 필요합니다.
빌, 이에 대한 답변을 고쳤습니다. – Sklivvz
'NOT NULL' 칼럼을 사용하여 에러를 강제하는 대신, 'SET NEW.FieldA = 1/0'과 같이 할 수 있습니다. 0으로 나누기 오류가 발생합니다 . 매우 유용한 * 오류 메시지는 아니지만 최소한 특수 열을 추가 할 필요는 없습니다. MySQL이 적절한'CHECK' 제약 조건을 지원하거나 최소한 트리거로부터 에러를 던질 수있는 더 좋은 방법을 원합니다. : – friedo
@friedo : OP의 질문은 특별한 null이 아닌 조건을 적용하는 것에 관한 것이므로 null 위반 오류 메시지가 적절할 것이라고 생각했습니다 .MySQL 트리거에서 수행 할 수있는 또 다른 트릭은 트리거의 정수 변수를 선언하고 문자열을 할당하면 사용하는 문자열을 포함하는 오류 메시지가 발생합니다. :) –
이 질문에 대한 대답은 아니지만 몇 가지 추가 정보가 있습니다.
여러 열을 다루는 모두가 null 또는 하나가 null가 아닌 경우 확인, 나는 일반적으로 COALESCE()
사용 - 목록이 증가하는 경우는, 간단한 읽기 쉽게 유지 보수의 :
COALESCE(a, b, c, d) IS NULL -- True if all are NULL
COALESCE(a, b, c, d) IS NOT NULL -- True if any one is not null
이 사용할 수 있습니다 너의 방아쇠.
표준 SQL 구문이므로 다른 SQL 기반 데이터베이스에서도 사용할 수 있습니다. (PostgreSQL에서는 확실히 작동합니다.) – Neall
MySQL 설명서에 "CHECK 절은 모든 저장소 엔진에서 구문 분석되지만 무시됩니다." 나는 그것을 시도하고 그것은 사실입니다. –
InnoDB 테이블의 경우에도 무시됩니까? 그거 끔찍해. – Neall