[sql-server] SQL Server : 단일 행을 포함하도록 테이블을 제한하는 방법은 무엇입니까?

내 애플리케이션의 구성 테이블에 단일 행을 저장하고 싶습니다. 이 테이블에 행을 하나만 포함 할 수 있도록 강제하고 싶습니다.

단일 행 제약 조건을 적용하는 가장 간단한 방법은 무엇입니까?



답변

열 중 하나가 하나의 값만 포함 할 수 있는지 확인한 다음 기본 키로 만들거나 고유성 제약 조건을 적용합니다.

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 만 읽을 수 있다는 사실을 아는 것이 훨씬 좋습니다.


답변

나는 항상 나를 위해 잘 작동했던 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'”를 추가하면 잠금 열을 처리 할 필요가 없으며 테이블을 처음로드 할 때 잠금 값이 무엇인지 기억할 필요가 없습니다.


답변

이 전략을 다시 생각할 수 있습니다. 비슷한 상황에서 필자는 과거 정보를 위해 이전 구성 행을 그대로 두는 것이 매우 중요하다는 사실을 종종 발견했습니다.

이를 위해 실제로 추가 열 creation_date_time(삽입 또는 업데이트 날짜 / 시간)과 현재 날짜 / 시간으로 올바르게 채워지는 삽입 또는 삽입 / 업데이트 트리거가 있습니다.

그런 다음 현재 구성을 가져 오려면 다음과 같이 사용합니다.

select * from config_table order by creation_date_time desc fetch first row only

(DBMS 맛에 따라 다름).

이렇게하면 복구 목적으로 기록을 유지하고 (테이블이 너무 커지지 만 가능성이 적을 경우 정리 절차를 시작할 수 있음) 최신 구성으로 계속 작업 할 수 있습니다.


답변

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