Cách thích hợp để lưu trữ một giá trị có thể có nhiều loại khác nhau


11

Tôi có một bảng câu trả lời và một bảng câu hỏi .

Bảng Answers có giá trị, nhưng tùy thuộc vào câu hỏi, giá trị này có thể là một bit, nvarcharhoặc number(cho đến nay). Các câu hỏi có một khái niệm về những gì dự định kiểu giá trị câu trả lời của nó nên được.

Điều quan trọng là phải phân tích các giá trị Trả lời này tại điểm này hay điểm khác vì ít nhất, các số sẽ cần phải được so sánh.

Đối với một chút bối cảnh, các câu hỏi và câu trả lời tiềm năng (thường là loại dữ liệu được phép cho đầu vào loại hộp văn bản) được cung cấp bởi một số người dùng trong một cuộc khảo sát về các loại. Các câu trả lời sau đó được cung cấp bởi người dùng được chỉ định khác.

Một vài lựa chọn tôi đã xem xét là:

A. XML hoặc chuỗi được phân tích cú pháp khác nhau tùy thuộc vào loại dự định (được theo dõi trong câu hỏi)

B. Ba bảng riêng biệt tham chiếu (hoặc được tham chiếu bởi) bảng Trả lời và được nối để dựa trên loại dự định. Trong trường hợp này, tôi không chắc chắn về cách tốt nhất để thiết lập các ràng buộc để đảm bảo mỗi câu hỏi chỉ có một câu trả lời hoặc nếu điều đó nên để lại cho ứng dụng.

C. Ba cột riêng biệt trên bảng Trả lời có thể được truy xuất dựa trên loại dự định.

Tôi rất vui khi nhận được một số thông tin về ưu và nhược điểm của các phương pháp này hoặc các phương pháp thay thế mà tôi đã không cân nhắc.

Câu trả lời:


2

Nó thực sự phụ thuộc vào cách front-end của bạn truy cập dữ liệu.

Nếu bạn đang sử dụng một trình ánh xạ O / R, hãy tập trung vào thiết kế hướng đối tượng của các lớp của bạn, chứ không phải vào thiết kế cơ sở dữ liệu. Cơ sở dữ liệu sau đó chỉ phản chiếu thiết kế lớp. Thiết kế db chính xác phụ thuộc vào mô hình ánh xạ kế thừa O / R và ánh xạ kế thừa mà bạn đang sử dụng.

Nếu bạn đang truy cập các bảng trực tiếp thông qua các bộ bản ghi, bảng dữ liệu, trình đọc dữ liệu hoặc tương tự, một việc đơn giản cần làm là chuyển đổi các giá trị thành một chuỗi bằng cách sử dụng văn hóa bất biến và lưu trữ nó trong một cột văn bản đơn giản . Và, tất nhiên, sử dụng lại cùng một nền văn hóa để chuyển đổi văn bản trở lại các loại giá trị chuyên biệt khi đọc các giá trị.

Ngoài ra, bạn có thể sử dụng một cột cho mỗi loại giá trị. Chúng tôi có ổ đĩa terabyte ngày hôm nay!

Một cột XML là có thể, nhưng có lẽ sẽ tăng thêm độ phức tạp so với cột văn bản đơn giản và thực hiện khá nhiều điều tương tự, cụ thể là tuần tự hóa / giải tuần tự hóa.

Các bảng tham gia tách biệt là cách làm bình thường hóa chính xác; tuy nhiên, chúng cũng thêm một số phức tạp.

Giữ cho nó đơn giản.

Xem thêm câu trả lời của tôi về thiết kế cơ sở dữ liệu Câu hỏi - cách nào tốt hơn? .


4

Dựa trên những gì bạn đã nói tôi sẽ sử dụng lược đồ chung sau:

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])
)

Bạn không thực sự quan tâm nếu câu trả lời là số, ngày, từ, v.v. bởi vì dữ liệu là câu trả lời cho câu hỏi không phải là thứ bạn cần để thao tác trực tiếp. Hơn nữa, dữ liệu chỉ có ý nghĩa trong bối cảnh cho câu hỏi. Vì vậy, một nvarchar là cơ chế dễ đọc nhất của con người để lưu trữ dữ liệu.

Câu hỏi và câu trả lời tiềm năng sẽ được thu thập từ người dùng đầu tiên và chèn vào bảng PollQuestion và PollOption. Người dùng thứ hai trả lời các câu hỏi sẽ chọn từ danh sách các câu trả lời (true / false = list of 2). Bạn cũng có thể mở rộng bảng PollQuestion để bao gồm id người dùng của người tạo nếu thích hợp để theo dõi các câu hỏi họ tạo.

Trên giao diện người dùng của bạn, câu trả lời mà người dùng chọn có thể được gắn với giá trị PollOptionId. Cùng với PollQuestionId, bạn có thể xác minh rằng câu trả lời nhanh chóng hợp lệ cho câu hỏi. Phản hồi của họ nếu hợp lệ sẽ được nhập vào bảng PollResponse.

Có một vài vấn đề tiềm ẩn tùy thuộc vào chi tiết về trường hợp sử dụng của bạn. Nếu người dùng đầu tiên muốn sử dụng câu hỏi toán học và bạn không muốn đưa ra nhiều câu trả lời có thể. Một tình huống khác là nếu các tùy chọn mà người dùng ban đầu cung cấp không phải là các tùy chọn duy nhất mà người dùng thứ hai có thể chọn. Bạn có thể làm lại lược đồ này như sau để hỗ trợ các trường hợp sử dụng bổ sung này.

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])
)

Tôi cũng có thể sẽ thêm một ràng buộc kiểm tra để đảm bảo rằng một tùy chọn được cung cấp hoặc một phản hồi thay thế, nhưng không phải cả hai (tùy chọn và phản hồi thay thế), tùy thuộc vào nhu cầu của bạn.

Chỉnh sửa: Giao tiếp kiểu dữ liệu cho AlternateResponse.

Trong một thế giới hoàn hảo, chúng tôi có thể sử dụng các khái niệm về Generics để xử lý kiểu dữ liệu khác nhau cho AlternateReponse. Than ôi chúng ta không sống trong một thế giới hoàn hảo. Sự thỏa hiệp tốt nhất mà tôi có thể nghĩ đến là chỉ định kiểu dữ liệu AlternateResponse nên có trong bảng PollQuestion và lưu trữ AlternateReponse trong cơ sở dữ liệu dưới dạng nvarchar. Dưới đây là lược đồ câu hỏi được cập nhật và bảng kiểu dữ liệu mới:

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
)

Bạn có thể liệt kê tất cả các loại dữ liệu có sẵn cho người tạo câu hỏi bằng cách chọn từ bảng Câu hỏi Loại này. Giao diện người dùng của bạn có thể tham chiếu Câu hỏiDataTypeId để chọn định dạng phù hợp cho trường phản hồi thay thế. Bạn không bị giới hạn ở các loại dữ liệu TSQL, vì vậy "Số điện thoại" có thể là loại dữ liệu và bạn sẽ nhận được định dạng / mặt nạ phù hợp trên giao diện người dùng. Ngoài ra nếu được yêu cầu, bạn có thể chuyển dữ liệu của mình sang các loại thích hợp thông qua một câu lệnh tình huống đơn giản để thực hiện bất kỳ loại xử lý nào (chọn, xác nhận, v.v.) trên các câu trả lời thay thế.


0

Có một cái nhìn về những gì là xấu về EAV, dù sao? của Aaron Bertrand cho một số thông tin về mô hình EAV.

Có thể sẽ tốt hơn theo nhiều cách để có một cột cho từng loại dữ liệu thay vì có XML hoặc nhiều bảng.

Phần ràng buộc là dễ dàng:

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
)

Có rất nhiều câu hỏi và câu trả lời hiện có trên trang web này được gắn thẻ , và có lẽ những câu hỏi khác mà người hỏi không biết sử dụng thuật ngữ đó trong câu hỏi của họ.

Tôi đặc biệt khuyên bạn nên đọc qua những điều đó, vì chúng có thể sẽ bao gồm tất cả các ưu và nhược điểm (điều này ngăn mọi người khỏi băm chúng ở đây, khi thực tế chúng không thay đổi).

Trả lời dựa trên ý kiến ​​câu hỏi của Aaron Bertrand


-1

Tôi nghĩ rằng vấn đề được đưa ra quá nhiều suy nghĩ hoặc có một số hạn chế bổ sung trong lý do tại sao một số câu trả lời nhất định có thể được đánh giá cao hơn những người khác. Hiện tại dường như không có bằng chứng nào cho thấy Câu trả lời sẽ phải được DB xử lý theo bất kỳ cách nào mà chỉ là trường nhật ký.

Tôi sẽ đi với một NVARCHAR (MAX) và sau đó chỉ để giao diện xử lý với việc lưu trữ / truy xuất nội dung. Có thể là trường bit IS_CORRECT nơi giao diện có thể lưu trữ nếu Câu trả lời đúng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.