2011-06-30 19 views
1

我目前正在研究一个问题,我有一个不雅的解决方案。我将一个记录的多个版本存储在一个表中。一个很好的例子就是文档的版本。我有一个文件的多个条目。我有一个名为Code的专栏,其中存储了对文档唯一的ID。每行还有一个Active字段(布尔值),表示记录是“活动”(最新版本)还是“非活动”。在这种情况下,只有最新版本可以被激活。我这样做是为了方便查询数据(而不是每个文档的顶部)。更新SQL(SQLite)中的值的最新版本

我的数据可能是这样的:

Code  Active VersionNo 
ABYY  0   1 
RRUP  0   1 
RRUP  0   2 
ABYY  0   2 
ABYY  0   3 
ABYY  1   4 
RRUP  1   3 

我的问题是,当我删除记录,我要确保该文件有一个记录(最新一期)标记为活动。这里有三种情况:

  1. 我删档ABYY第4版 - 我想使该文件的版本3活动。
  2. 我删除了文档ABYY的版本3 - 我想确保版本4仍然标记为活动。
  3. (棘手的)我删除了文档ABYY的第3版。后来我决定删除版本4. - 我想要版本2被标记为活动,这意味着你不能只从版本号中减去1。

而是基于关闭特定数据的创建复杂的查询,我宁愿创建设置活跃的领域为0,除了具有最高版本号,它会设置为1的所有文件的通用查询代替。这样,如果我不确定特定文档的数据,我可以重复使用相同的查询作为“清理”脚本。

现在我被困在两个查询上,第二个有点长。这里是我做的:

UPDATE documents 
SET Active = 0 
WHERE Code = 'ABYY'; 

UPDATE documents u 
SET Active = 1 
WHERE id = (SELECT TOP 1 id 
      FROM documents 
      WHERE Code = 'ABYY' 
      ORDER BY VersionNo DESC); 

我可能可以将这些查询合并为一个查询(最好也是简单的)?我正在写这个SQLite(最新版本)。

+0

我认为这不是一个好设计。你可能会认为你通过存储一个活跃的标志来简化你的生活,但是现在的问题表明,没有免费的午餐,并且不用使用最新版本的日期来获取最新版本的文档,在其他地方支付。我会摆脱标志并实施基于版本日期的规则。如果您想忽略它,您可以将版本标记为“已删除”。 – Tim

回答

1

尝试:

UPDATE DOCUMENTS 
    SET active = CASE 
        WHEN id = (SELECT d.id 
           FROM DOCUMENTS d 
           WHERE d.code = DOCUMENTS.code 
          ORDER BY d.versionno DESC 
           LIMIT 1) THEN 1 
        ELSE 0 
       END 
WHERE code = 'ABYY' 
0

你不能折叠查询,至少不是他们编写的方式,因为在第一个UPDATE查询中,你将设置“Active = 0”而另一个设置为“Active = 1” 。

如果您想保存更新所有这些“活动”字段为0,你可以这样做:

UPDATE documents 
SET Active = 0 
WHERE Code = 'ABYY' && Active = 1; 

这应该使它所以目前仅与该代码的活动记录被更改,而不是所有记录该代码(甚至那些已经是Active = 0的代码)。

+0

我试图做的是确保每一个其他项目被标记为零。如果它是在一个查询中完成的,你可以说“其他任何项目”,但如果你是在两个这样做,你真的不能。这就是为什么我把一切都标记为零,然后在第二个查询中我标记了正确的一对一。 – IAmTimCorey

0

这应做到:

UPDATE TheTable 
SET Active=(VersionNo=(SELECT MAX(VersionNo) 
         FROM TheTable AS T1 
         WHERE T1.code=TheTable.code)) 
WHERE code='RRUP' 

此外,正常化整个表,只是删除从外更新where子句:

UPDATE TheTable 
SET Active=(VersionNo=(SELECT MAX(VersionNo) 
         FROM TheTable AS T1 
         WHERE T1.code=TheTable.code))