将SQL转换为OCL?

时间:2010-06-10 19:52:17

标签: sql delphi ocl bold-delphi

我有一段SQL要转换为OCL。我不擅长SQL,所以我希望通过这种方式提高可维护性。我们正在使用Interbase 2009,Delphi 2007与Bold和modeldriven开发。现在我希望有人在这里说好的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有两种情况,'IFTMBP'和'IFTMBF'。

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

  • MessageType:String
  • ChassiNumber:String
  • ShipFromFinland:Boolean
  • 无效:布尔

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

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

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

ScaniaEdiSolMessage.allinstances

也可以通过选择来轻松过滤行,例如:

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

但是我不明白我应该如何使OCL与上面的SQL匹配。

3 个答案:

答案 0 :(得分:3)

听Gabriel和Stephanie,了解更多SQL。

您声明要使代码更易于维护,但理解SQL的开发人员数量远远超过了解OCL的开发人员数量。

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

不要试图在圆孔中安装方形钉,因为你对圆锤很好:)

答案 1 :(得分:1)

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

  

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

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

答案 2 :(得分:0)

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

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

所以在你的情况下,你可能会有这样的一组:

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
        )