여러 유형이 될 수있는 값을 저장하는 올바른 방법


11

나는이 답변의 테이블과 질문 표를.

답변 테이블 값을 가지고 있지만, 문제에 따라이 값이 될 수있다 bit, nvarchar또는 number(지금까지). 질문 의도 응답 값 유형이 무엇을해야 개념을 가지고있다.

최소한 숫자를 비교해야하므로 이러한 Answer 값을 한 지점에서 구문 분석하는 것이 중요합니다 .

좀 더 자세한 내용을 위해 일부 사용자는 질문 및 잠재적 답변 (일반적으로 텍스트 상자 유형 입력에 허용되는 데이터 유형)을 제공합니다. 그런 다음 다른 지정된 사용자가 답변을 제공합니다.

내가 고려한 몇 가지 옵션은 다음과 같습니다.

A. 의도 된 유형에 따라 다르게 구문 분석되는 XML 또는 문자열 (문제에서 추적되는)

B. 응답 테이블을 참조하는 (또는 참조되는) 세 개의 별도 테이블이 의도 한 유형에 따라 조인됩니다. 이 경우 각 질문에 하나의 답변 만 있는지 또는 응용 프로그램에 맡겨야하는지 제약 조건을 설정하는 가장 좋은 방법은 확실하지 않습니다.

C. 응답 테이블에서 원하는 유형에 따라 검색 할 수있는 세 개의 별도 열.

이 접근법의 장단점에 대해 의견을 얻거나 내가 고려하지 않은 대체 접근법에 대해 약간의 정보를 얻는 것이 기뻤습니다.

답변:


2

실제로 프런트 엔드가 데이터에 액세스하는 방법에 따라 다릅니다.

O / R- 매퍼를 사용하는 경우 데이터베이스 디자인이 아닌 클래스의 객체 지향 디자인에 중점을 둡니다. 그런 다음 데이터베이스는 클래스 디자인을 미러링합니다. 정확한 db 디자인은 사용중인 O / R- 매퍼 및 상속 매핑 모델에 따라 다릅니다.

레코드 세트, 데이터 테이블, 데이터 리더 등을 통해 테이블에 직접 액세스하는 경우 간단한 방법은 가변 문화권을 사용하여 값을 문자열로 변환하고 간단한 텍스트 열에 저장하는 것입니다. . 물론 값을 읽을 때 텍스트를 특수한 값 유형으로 다시 변환하려면 동일한 문화권을 다시 사용하십시오.

또는 값 유형 당 하나의 열을 사용할 수 있습니다. 오늘 테라 바이트 드라이브가 있습니다!

XML 열은 가능하지만 간단한 텍스트 열에 비해 더 많은 복잡성을 추가 할 수 있으며 직렬화 / 직렬화와 거의 같은 작업을 수행합니다.

분리 된 조인 테이블은 올바른 정규화 된 작업 방식입니다. 그러나 그것들은 상당히 복잡합니다.

간단하게 유지하십시오.

Questionnaire 데이터베이스 디자인에 대한 내 답변 을 참조하십시오 -어떤 방법이 더 낫습니까? .


4

당신이 말한 것을 바탕으로 다음과 같은 일반적인 스키마를 사용합니다.

CREATE TABLE [dbo].[PollQuestion]
(
    [PollQuestionId] INT NOT NULL PRIMARY KEY IDENTITY,
    [QuestionText] NVARCHAR(150) NOT NULL, -- Some reasonable character limit
    [Created] DATETIME2(2) NOT NULL DEFAULT SYSUTCDATETIME(),
    [Archived] DATETIME2(2) NULL,  -- Remove this if you don't need to hide questions
)
CREATE TABLE [dbo].[PollOption]
(
    [PollOptionId] INT NOT NULL PRIMARY KEY IDENTITY,
    [PollQuestionId] INT NOT NULL,  -- Link to the question here because options aren't shared across questions
    [OptionText] NVARCHAR(50) NOT NULL, -- Some reasonable character limit
    [Created] DATETIME2(2) NOT NULL DEFAULT SYSUTCDATETIME(),
    [Archived] DATETIME2(2) NULL  -- Remove this if you don't need to hide options

    CONSTRAINT [FK_PollOption_PollQuestionId_to_PollQuestion_PollQuestionId] FOREIGN KEY ([PollQuestionId]) REFERENCES [dbo].[PollQuestion]([PollQuestionId])
)
CREATE TABLE [dbo].[PollResponse]
(
    [PollResponseId] INT NOT NULL PRIMARY KEY IDENTITY,
    [PollOptionId] INT NOT NULL,
    [UserId] INT NOT NULL,
    [Created] DATETIME2(2) NOT NULL DEFAULT SYSUTCDATETIME(),
    [Archived] DATETIME2(2) NULL,  -- Remove this if you don't need to hide answers

    CONSTRAINT [FK_PollResponse_PollOptionId_to_PollOption_PollOptionId] FOREIGN KEY ([PollOptionId]) REFERENCES [dbo].[PollOption]([PollOptionId]),
    CONSTRAINT [FK_PollResponse_UserId_to_User_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User]([UserId])
)

데이터가 직접 조작해야하는 것이 아니라 질문에 대한 답변이기 때문에 답변이 숫자, 날짜, 단어 등이면 실제로 신경 쓰지 않아도됩니다. 또한 데이터는 질문과 관련하여 의미가 있습니다. 이러한 nvarchar는 데이터를 저장하기위한 가장 다재다능한 사람이 읽을 수있는 메커니즘입니다.

질문과 잠재적 인 답변은 첫 번째 사용자로부터 수집되어 PollQuestion 및 PollOption 테이블에 삽입됩니다. 질문에 대답하는 두 번째 사용자는 답변 목록 (참 / 거짓 = 2 목록)에서 선택합니다. PollQuestion 테이블을 확장하여 생성자의 질문을 추적하기 위해 필요한 경우 작성자의 사용자 ID를 포함시킬 수도 있습니다.

UI에서 사용자가 선택한 답변은 PollOptionId 값에 연결될 수 있습니다. PollQuestionId와 함께 질문에 대한 답변이 신속하게 유효한지 확인할 수 있습니다. 유효한 경우 응답은 PollResponse 테이블에 입력됩니다.

사용 사례에 따라 몇 가지 잠재적 인 문제가 있습니다. 첫 번째 사용자가 수학 질문을 사용하고 여러 가능한 답변을 제공하지 않으려는 경우. 또 다른 상황은 초기 사용자가 제공하는 옵션이 두 번째 사용자가 선택할 수있는 유일한 옵션이 아닌 경우입니다. 이러한 추가 사용 사례를 지원하기 위해이 스키마를 다음과 같이 재 작업 할 수 있습니다.

CREATE TABLE [dbo].[PollResponse]
(
    [PollResponseId] INT NOT NULL PRIMARY KEY IDENTITY,
    [PollOptionId] INT NULL,
    [PollQuestionId] INT NOT NULL,
    [UserId] INT NOT NULL,
    [AlternateResponse] NVARCHAR(50) NULL, -- Some reasonable character limit
    [Created] DATETIME2(2) NOT NULL DEFAULT SYSUTCDATETIME(),
    [Archived] DATETIME2(2) NULL,  -- Remove this if you don't need to hide answers

    CONSTRAINT [FK_PollResponse_PollOptionId_to_PollOption_PollOptionId] FOREIGN KEY ([PollOptionId]) REFERENCES [dbo].[PollOption]([PollOptionId]),
    CONSTRAINT [FK_PollResponse_UserId_to_User_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User]([UserId])
)

또한 필요에 따라 옵션이 제공되거나 대체 응답이 있지만 (옵션 및 대체 응답)이 아닌지 확인하기 위해 검사 제한 조건을 추가 할 것입니다.

편집 : AlternateResponse의 통신 데이터 유형.

완벽한 세계에서는 제네릭 개념을 사용 하여 AlternateReponse에 대한 다양한 데이터 유형을 처리 할 수 있습니다 . 아아 우리는 완벽한 세상에 살고 있지 않습니다. 내가 생각할 수있는 가장 좋은 방법은 PollQuestion 테이블에 AlternateResponse 데이터 유형을 지정하고 AlternateReponse를 nvarchar로 데이터베이스에 저장하는 것입니다. 아래는 업데이트 된 질문 스키마와 새로운 데이터 유형 테이블입니다.

CREATE TABLE [dbo].[PollQuestion]
(
    [PollQuestionId] INT NOT NULL PRIMARY KEY IDENTITY,
    [QuestionText] NVARCHAR(150) NOT NULL, -- Some reasonable character limit
    [QuestionDataTypeId] INT NOT NULL,
    [Created] DATETIME2(2) NOT NULL DEFAULT SYSUTCDATETIME(),
    [Archived] DATETIME2(2) NULL,  -- Remove this if you don't need to hide questions
    -- Insert FK here for QuestionDataTypeId
)
CREATE TABLE [dbo].[QuestionDataType]
(
    [QuestionDataTypeId] INT NOT NULL PRIMARY KEY IDENTITY,
    [Description] NVARCHAR(50) NOT NULL, -- Some reasonable character limit
)

이 QuestionDataType 테이블에서 선택하여 질문 작성자에 대해 사용 가능한 모든 데이터 유형을 나열 할 수 있습니다. UI는 QuestionDataTypeId를 참조하여 대체 응답 필드에 적합한 형식을 선택할 수 있습니다. TSQL 데이터 형식으로 제한되지 않으므로 "전화 번호"는 데이터 형식이 될 수 있으며 UI에서 적절한 서식 / 마스킹을 얻을 수 있습니다. 또한 필요한 경우 대체 답변에서 모든 종류의 처리 (선택, 유효성 검사 등)를 수행하기 위해 간단한 case 문을 통해 데이터를 적절한 유형으로 캐스트 할 수 있습니다.


0

한 번 봐 가지고 어쨌든, EAV에 대해 그렇게 나쁜 무엇을? EAV 모델에 대한 정보는 Aaron Bertrand가 작성했습니다.

XML 또는 다중 테이블 대신 각 데이터 유형에 대한 열을 갖는 것이 여러 가지면에서 더 나을 것입니다.

구속 조건 부분은 쉽다 :

CHECK 
(
    CASE WHEN col1 IS NOT NULL THEN 1 ELSE 0 END + 
    CASE WHEN col2 IS NOT NULL THEN 1 ELSE 0 END + 
    CASE WHEN col3 IS NOT NULL THEN 1 ELSE 0 END = 1
)

이 사이트에는 태그가있는 기존의 많은 질문과 답변이 있을 수 있으며 아마도 질문자가 해당 용어를 질문에 사용하지 않은 다른 질문과 답변이 있을 수도 있습니다.

나는 모든 장단점을 다룰 것이므로 그 내용을 읽는 것이 좋습니다 (실제로 사람들은 변경되지 않았을 때 사람들이 여기에서 다시 해시하지 못하게합니다).

Aaron Bertrand 님이 남긴 질문 코멘트를 바탕으로 답변


-1

문제가 너무 많이 생각되거나 특정 답변이 다른 답변보다 더 적합한 이유에 대한 추가 제약이 있다고 생각합니다. 현재 DB에서 어떤 방식 으로든 응답을 처리해야한다는 증거는 없지만 로그 필드로 표시됩니다.

NVARCHAR (MAX)을 사용하여 프론트 엔드가 내용 저장 / 검색을 처리하도록합니다. 응답이 올바른 경우 프런트 엔드가 저장할 수있는 IS_CORRECT 비트 필드 일 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.