【问题标题】:Translate SQL to OCL?将 SQL 转换为 OCL?
【发布时间】:2011-03-02 08:51:27
【问题描述】:

我有一段 SQL 想要翻译成 OCL。我不擅长 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。

【问题讨论】:

  • 你在做一些斯堪尼亚卡车的事情?:) 你想做的对我来说似乎不太好。首先,SQL 基于关系代数和面向对象环境中一阶谓词的 OCL。这让他们都以不同的方式看待世界。例如。 SQL 中的简单导航是关于选择和加入的。在 OCL 中,您会经历从一个对象到其他对象的关联。面向对象和关系的不匹配可能会在未来给你带来很多问题......
  • 是的,应用程序中有一些卡车的东西。许多 SQL 表达式相对容易转换为 OCL,即使后者是面向对象的(OCL 也可以过滤事物)。我不知道你在考虑什么样的不匹配问题,但为了简单起见,我希望尽可能在 OCL 中。
  • 为什么不学习至少足够的 SQL 来维护你所拥有的东西。我同意加布里埃尔的观点。或者也许找到一个说 OCL 而不是/除了 SQL 的数据库

标签: sql delphi ocl bold-delphi


【解决方案1】:

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

您说您希望使代码更易于维护,但是了解 SQL 的开发人员的数量远远大于了解 OCL 的开发人员的数量。

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

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

【讨论】:

  • 嗯,这只是一个偏好问题。我们有尽可能使用 OCL 的政策。 OCL 的原因是简单,它是 Bold 框架的基础。但我同意,了解 SQL 的人比了解 OCL 的人多。
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

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

    使用 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
            )
    

    【讨论】:

    • allinstances 不是 OCL 工具;你可能是指 allInstances()
    • Bold 可能不严格遵循 OCL 标准,因此 allinstances 实际上可以正常工作。这个问题已经超过7年了。快速检查代码表明原始 SQL 是相同的 :)
    • @EdWillink - 你是对的 - 即使方法不接受参数,OCL 括号中的括号也是强制性的。然而,在 OCL 的 MDriven 实现中,我们允许在没有参数时省略它们。
    猜你喜欢
    • 1970-01-01
    • 2014-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-02
    • 2019-09-08
    • 2021-12-17
    • 2011-05-26
    相关资源
    最近更新 更多