내 애플리케이션의 구성 테이블에 단일 행을 저장하고 싶습니다. 이 테이블에 행을 하나만 포함 할 수 있도록 강제하고 싶습니다.
단일 행 제약 조건을 적용하는 가장 간단한 방법은 무엇입니까?
내 애플리케이션의 구성 테이블에 단일 행을 저장하고 싶습니다. 이 테이블에 행을 하나만 포함 할 수 있도록 강제하고 싶습니다.
단일 행 제약 조건을 적용하는 가장 간단한 방법은 무엇입니까?
Name
?
ar
s 의견 에 대한 응답이었습니다 . 문제는 이름 / 값 쌍을 저장하는 경우 값이 문자열이어야 하며 데이터베이스에서 유효성 검사 를 시행 할 수단이 없다는 것 입니다. OP가 원하는대로 각 설정에 대해 별도의 열이 있는 단일 행 테이블을 사용하면 제약 조건 확인을 통해 각 구성 설정에 대한 유효성 검사를 쉽게 시행 할 수 있습니다 .
답변:
열 중 하나가 하나의 값만 포함 할 수 있는지 확인한 다음 기본 키로 만들거나 고유성 제약 조건을 적용합니다.
CREATE TABLE T1(
Lock char(1) not null,
/* Other columns */,
constraint PK_T1 PRIMARY KEY (Lock),
constraint CK_T1_Locked CHECK (Lock='X')
)
주로 구성을 저장하기 위해 다양한 데이터베이스에 이러한 테이블이 많이 있습니다. 구성 항목이 int 여야하는 경우 DB에서 int 만 읽을 수 있다는 사실을 아는 것이 훨씬 좋습니다.
comp.databases.theory
, 유즈넷 그룹 (Google 그룹을 통해 볼 수 있음 )의 축약 형 으로 최근에 많이 읽지 않았 음을 인정합니다. SQL보다 관계 이론에 더 중점을 두었지만 dportas / sqlvogel도 같은 그룹을 자주 사용한다는 것을 알게되었습니다. TTM은 The Third Manifesto 에 대한 참조 였는데 , 이것은 SQL보다는 관계 이론에 대해 (다시) 이야기하는 좋은 책입니다.
나는 항상 나를 위해 잘 작동했던 Damien의 접근 방식을 사용하지만 한 가지 추가합니다.
CREATE TABLE T1(
Lock char(1) not null DEFAULT 'X',
/* Other columns */,
constraint PK_T1 PRIMARY KEY (Lock),
constraint CK_T1_Locked CHECK (Lock='X')
)
"DEFAULT 'X'"를 추가하면 잠금 열을 처리 할 필요가 없으며 테이블을 처음로드 할 때 잠금 값이 무엇인지 기억할 필요가 없습니다.
Lock char(1) not null CONSTRAINT DF_T1_Lock DEFAULT 'X'
이 전략을 다시 생각할 수 있습니다. 비슷한 상황에서 필자는 과거 정보를 위해 이전 구성 행을 그대로 두는 것이 매우 중요하다는 사실을 종종 발견했습니다.
이를 위해 실제로 추가 열 creation_date_time
(삽입 또는 업데이트 날짜 / 시간)과 현재 날짜 / 시간으로 올바르게 채워지는 삽입 또는 삽입 / 업데이트 트리거가 있습니다.
그런 다음 현재 구성을 가져 오려면 다음과 같이 사용합니다.
select * from config_table order by creation_date_time desc fetch first row only
(DBMS 맛에 따라 다름).
이렇게하면 복구 목적으로 기록을 유지하고 (테이블이 너무 커지지 만 가능성이 적을 경우 정리 절차를 시작할 수 있음) 최신 구성으로 계속 작업 할 수 있습니다.
SELECT TOP 1 ... ORDER BY creation_date_time DESC
INSTEAD OF 트리거 를 구현 하여 데이터베이스 내에서 이러한 유형의 비즈니스 논리를 적용 할 수 있습니다 .
트리거는 테이블에 레코드가 이미 있는지 확인하는 논리를 포함 할 수 있으며 있다면 삽입을 ROLLBACK합니다.
이제 더 큰 그림을보기 위해 한 걸음 뒤로 물러서서 아마도이 정보를 예를 들어 구성 파일이나 환경 변수에 저장할 수있는 더 적합한 대안이 있는지 궁금합니다.
IsActive라는 이름의 기본 키에 비트 필드를 사용합니다. 따라서 최대 2 개의 행이있을 수 있으며 유효한 행을 가져 오는 SQL은 다음과 같습니다. select * from Settings where IsActive = 1 if the table named Settings.
다음은 Y 또는 N (예 : 애플리케이션 잠금 상태)을 보유하는 하나의 행만 포함 할 수있는 잠금 유형 테이블에 대해 생각 해낸 솔루션입니다.
하나의 열이있는 테이블을 만듭니다. 한 열에 검사 제약을 두어 Y 또는 N 만 넣을 수 있습니다. (또는 1 또는 0, 또는 무엇이든)
테이블에 "정상"상태로 한 행을 삽입합니다 (예 : N은 잠기지 않음을 의미 함).
그런 다음 SIGNAL (DB2) 또는 RAISERROR (SQL Server) 또는 RAISE_APPLICATION_ERROR (Oracle) 만있는 테이블에 INSERT 트리거를 만듭니다. 따라서 애플리케이션 코드가 테이블을 업데이트 할 수 있지만 INSERT는 실패합니다.
DB2 예 :
create table PRICE_LIST_LOCK
(
LOCKED_YN char(1) not null
constraint PRICE_LIST_LOCK_YN_CK check (LOCKED_YN in ('Y', 'N') )
);
--- do this insert when creating the table
insert into PRICE_LIST_LOCK
values ('N');
--- once there is one row in the table, create this trigger
CREATE TRIGGER ONLY_ONE_ROW_IN_PRICE_LIST_LOCK
NO CASCADE
BEFORE INSERT ON PRICE_LIST_LOCK
FOR EACH ROW
SIGNAL SQLSTATE '81000' -- arbitrary user-defined value
SET MESSAGE_TEXT='Only one row is allowed in this table';
나를 위해 작동합니다.
오래된 질문이지만 작은 열 유형의 IDENTITY (MAX, 1)을 사용하는 것은 어떻습니까?
CREATE TABLE [dbo].[Config](
[ID] [tinyint] IDENTITY(255,1) NOT NULL,
[Config1] [nvarchar](max) NOT NULL,
[Config2] [nvarchar](max) NOT NULL
(Name, Value)
이름에 기본 키가있는 열 이 있는 테이블을 사용하지 않는 이유는 무엇입니까? 그런 다음select Value from Table where Name = ?
행이 반환되지 않거나 한 행이 반환되지 않을 것이라는 확신을 가질 수 있습니다.