0

一个示例案例场景 - 我有一个带有一个问题和多个答案的表单作为复选框,因此您可以选择多个。存储答案的表格如下:

QuestionAnswers
(
  UserID int,
  QuestionID int,
  AnswerID int
)

使用存储过程将这些答案更新到数据库的最佳方法是什么?在不同的工作中,我看到了所有范围,从简单地删除所有以前的答案和插入新的答案,到传递要删除的答案列表和要添加到存储过程的答案列表。

在我目前的项目中,性能和可扩展性非常重要,所以我想知道最好的方法是什么?

谢谢!安德烈

4

6 回答 6

1

如果我可以选择表设计,并且以下陈述是正确的:

  • 您知道每个问题的最大选择数/
  • 每个选项都是一个简单的选中/未选中。
  • 每个答案都被分类为正确/错误,而不是按某种比例标记。(比如 70% 是对的。)

然后考虑性能,我会考虑下表而不是您提供的表:

QuestionAnswers
(
  UserID int,
  QuestionID int,
  Choice1 bool,
  Choice2 bool,
  ...
  ChoiceMax bool
)

是的,就规范化而言,它很丑陋,但非规范化会购买性能并简化查询——一个问题只需更新/插入一次。(而且我会先更新并仅在受影响的行等于零时插入。)

检测答案是否正确也会更简单——使用下表:

QuestionCorrectAnswers
(
  QuestionID int,
  Choice1 bool,
  Choice2 bool,
  ...
  ChoiceMax bool
)

您需要做的只是QuestionCorrectAnswers使用与用户回答的选项组合相同的选项来查找行。

于 2009-12-20T22:36:15.787 回答
0

It is a simple solution: Every [Answer] should have integer value (bit) and this value is unique for current Question. For example, you have Question1 and four predefined answers:

[Answer] [Bit value]

answer1 0x00001

answer2 0x00002

answer3 0x00004

answer4 0x00008 ...

So, you SQL INSERT/UPDATE will be:

declare @checkedMask int
set @checkedMask = 0x00009 -- answer 1 and answer 4 are checked
declare @questionId int
set @questionId = 1

-- delete

delete
--select r.* 
r 
from QuestionResult r 
    inner join QuestionAnswer a  
        on r.QuestionId = a.QuestionId and r.AnswerId = a.AnswerId
where r.QuestionId = @questionId
 and (a.mask & @checkedMask) = 0

-- insert

insert QuestionResult (AnswerId, QuestionId)
    select
        AnswerId,
        QuestionId
    from QuestionAnswer a
       where a.QuestionId = @questionId
         and (a.mask & @checkedMask) > 0
         and not exists(select AnswerId from QuestionResult r 
                where r.QuestionId = @questionId and r.AnswerId = a.AnswerId)
于 2009-12-26T19:53:13.543 回答
0

如果问题始终相同,那么您将永远不会删除任何内容 - 只需对所有更改的答案运行更新查询。

Update QuestionAnswers
SET AnswerID = @AnswerID
WHERE UserID = @UserID AND QuestionID = @QuestionID

如果由于某种原因您仍然需要执行一些删除/插入操作 - 我会检查哪些 QuestionID 已经存在(对于给定的 UserID),因此您至少需要执行删除/插入操作。

更新比删除快得多然后插入,而且您不会使任何标识列飙升。

我假设您在进入页面时从 DB 加载 QuestionAnswers,因此用户可以看到他/她上次给出的答案 - 如果您已经在内存中拥有必要的数据,以确定要删除、插入和更新的内容。

于 2009-12-20T21:11:17.893 回答
0

我不同意摄政王的答案是非规范化的。只要每个答案不依赖于另一列,并且仅依赖于键,它就处于第三范式。它与具有以下客户名称字段的表没有什么不同:

CustomerName
(
    name_prefix
    name_first
    name_mi
    name_last
    name_suffix
    city
    state
    zip
)

如同

QuestionAnswers
(
   Q1answer1
   Q1answer2
   Q1answerN
)

名称的“问题”和可能填写或未填写的多个答案与表格的“问题”和可能选择或未选择的多个答案之间确实没有区别。

于 2010-03-02T15:05:01.267 回答
0

Andrey:如果用户 (userid=1) 选择问题 1(questionid=1) 的选项 a(answerid=1) & b(answerid=2) 之后切换到 c (a-id=3) & d(a- id=4),您必须检查,然后删除旧的并添加新的。如果您选择采用另一种方法,您将不会检查特定记录是否存在(以便您可以更新它),您只需删除旧记录并插入新记录。无论如何,由于您没有存储任何身份列,我会采用后一种方法。

于 2009-12-20T21:19:40.847 回答
0

抱歉恢复旧线程。我原以为唯一现实的解决方案是删除该问题的所有回复,并在选中复选框的位置创建新行。就更新而言,每个答案都有一列可能是有效的,但这种方法的不灵活性并不是一种选择。您需要能够为问题添加选项,而无需重新设计数据库。

只需删除并重新插入。这就是数据库的设计目的,存储和检索大量数据行。

于 2010-06-24T02:23:36.960 回答