3

我有一段要翻译成 OCL 的 SQL。我不擅长 SQL,所以我想通过这个来提高可维护性。我们正在使用带有 Bold 和模型驱动开发的 Interbase 2009、Delphi 2007。现在我希望这里有人会说好的 SQL 和 OCL :-) 原始 SQL:

Select Bold_Id, MessageId, ScaniaId, MessageType, MessageTime, Cancellation, ChassieNumber, UserFriendlyFormat, ReceivingOwner, Invalidated, InvalidationReason,
(Select Parcel.MCurrentStates From Parcel
Where ScaniaEdiSolMessage.ReceivingOwner = Parcel.Bold_Id) as ParcelState From ScaniaEdiSolMessage
Where MessageType = 'IFTMBP' and
not Exists (Select * From ScaniaEdiSolMessage EdiSolMsg
Where EdiSolMsg.ChassieNumber = ScaniaEdiSolMessage.ChassieNumber and EdiSolMsg.ShipFromFinland = ScaniaEdiSolMessage.ShipFromFinland and EdiSolMsg.MessageType = 'IFTMBF') and
invalidated = 0 Order By MessageTime desc

稍作简化后:

Select Bold_Id, (Select Parcel.MCurrentStates From Parcel 
where ScaniaEdiSolMessage.ReceivingOwner = Parcel.Bold_Id) From ScaniaEdiSolMessage
Where MessageType = 'IFTMBP' and not Exists (Select * From ScaniaEdiSolMessage
EdiSolMsg Where EdiSolMsg.ChassieNumber = ScaniaEdiSolMessage.ChassieNumber and
EdiSolMsg.ShipFromFinland = ScaniaEdiSolMessage.ShipFromFinland and 
EdiSolMsg.MessageType = 'IFTMBF') and invalidated = 0

注意:MessageType 有 2 种情况,“IFTMBP”和“IFTMBF”。

所以要列出的表是 ScaniaEdiSolMessage。它具有以下属性:

  • 消息类型:字符串
  • 底盘编号:字符串
  • ShipFromFinland:布尔值
  • 无效:布尔值

它还有一个指向名为 ReceivingOwner 的表 Parcel 的链接,其中 BoldId 作为键。

所以它似乎列出了 ScaniaEdiSolMessage 的所有行,然后有一个子查询也列出了 ScaniaEdiSolMessage 的所有行并将其命名为 EdiSolMsg。然后它几乎排除了所有行。事实上,上面的查询从 28000 条记录中获得了一次命中。

在 OCL 中很容易列出所有实例:

ScaniaEdiSolMessage.allinstances

也很容易通过选择过滤行,例如:

ScaniaEdiSolMessage.allinstances->select(shipFromFinland and not invalidated)

但我不明白我应该如何制作一个 OCL 来匹配上面的 SQL。

4

3 回答 3

3

听听 Gabriel 和 Stephanie,了解更多 SQL。

你说你想让代码更易于维护,但是了解 SQL 的开发人员的数量远远大于了解 OCL 的开发人员的数量。

如果您在将其转换为 OCL 后明天离开该项目,那么您能够找到可以维护 OCL 的人的机会非常渺茫。但是,您可以找到维护 SQL 的人的机会非常高。

不要仅仅因为你擅长使用圆锤就试图在圆孔中安装方钉:)

于 2011-01-24T13:16:09.500 回答
1

有一个项目Dresden OCL可能会对您有所帮助。

Dresden OCL 提供了一组工具来解析和评估 UML、EMF 和 Java 等各种模型上的 OCL 约束。此外,Dresden OCL 提供了用于 Java/AspectJ 和 SQL 代码生成的工具。Dresden OCL 的工具既可以用作其他项目的库,也可以用作扩展Eclipse 并支持OCL 的插件项目。

我没有使用它,但有一个演示展示了该工具如何从模型和 OCL 约束生成 SQL。我意识到你要求相反,但也许使用这个你可以弄清楚。还有一篇论文描述了同一个人的 OCL->SQL 转换。

于 2012-09-13T22:03:41.620 回答
0

使用 MDriven(Delphi 的 Bold 的继任者)我会这样做:

使用 OCL 到 SQL 时,如果您考虑需要检查的不同信息集,一切都会变得更容易 - 然后使用 ocl 运算符作为 ->intersection 来查找您所追求的集合。

因此,在您的情况下,您可能会有这样的集合:

ScaniaEdiSolMessage.allinstances->select(shipFromFinland and not invalidated)

但你也有这样的一套:

ScaniaEdiSolMessage.allinstances->select(m|m.ReceivingOwner.MessageType = 'IFTMBP')

而且您还有以下标准:

Parcel.allinstances->select(p|p.Messages->exists(m|m.MessageType = 'IFTMBF')).Messages

如果所有这些集合具有相同的结果类型(ScaniaEdiSolMessage 的集合),您可以简单地将它们相交以获得您想要的结果

ScaniaEdiSolMessage.allinstances->select(shipFromFinland and not invalidated)
->intersection(ScaniaEdiSolMessage.allinstances->select(m|m.ReceivingOwner.MessageType = 'IFTMBP'))
->intersection(Parcel.allinstances->select(p|p.Messages->exists(m|m.MessageType = 'IFTMBF')).Messages
    )

看着它,我们可以将其减少一点:

    ScaniaEdiSolMessage.allinstances
    ->select(m|m.shipFromFinland and (not m.invalidated) and
              (m.ReceivingOwner.MessageType = 'IFTMBP'))
    ->intersection(Parcel.allinstances->select(p|
             p.Messages->exists(m|m.MessageType = 'IFTMBF')).Messages
        )
于 2017-12-27T08:50:55.957 回答