以数据库不可知的方式查询构建

时间:2009-01-13 14:21:16

标签: c++ sql

在几乎可以使用任何关系数据库的C ++应用程序中,生成查询的最佳方法是什么,可以轻松扩展以允许数据库引擎的怪癖?

换句话说,代码可能需要以各种数据库引擎之间不一致的方式检索数据。什么是在客户端设计代码以生成查询的最佳方式,这种方式将使支持新数据库引擎变得相对轻松。

例如,如果我有(MFC)代码,如下所示:

CString query = "SELECT id FROM table"
results = dbConnection->Query(query);

我们决定支持一些使用“AVEC”代替“FROM”的数据库。现在,只要用户使用该数据库引擎,此查询就会失败。

目前为止的选项:

  • 最差选项:让查询的代码检查数据库类型。
  • 更好的选择:在数据库连接对象上创建查询请求方法,该方法接受唯一的查询“代码”,并根据正在使用的数据库引擎返回相应的查询。
  • Betterer选项:创建一个查询构建器类,允许调用者在不使用任何SQL的情况下构造查询。查询完成后,调用者可以调用“Generate”方法,该方法为活动数据库引擎返回一个查询字符串approrpriate
  • 最佳选择:??

注意:数据库引擎本身是通过我们自己创建的一些薄层抽象出来的。这是查询本身是唯一剩下的问题。

解决方案:
我决定采用“更好”的选项(查询“选择器”)有两个原因。

  1. 调试:如下所述,使用选择器方法可以稍微简化调试,因为查询是预先构建的,并以可读的形式在代码中列出。
  2. 灵活性:我想到有些数据库可能有更好的和完全不同的方法来解决特定的查询。例如,使用Access我每次都会对多个表执行复杂的查询,因为我必须这样做,但在Sql Server上我想设置一个视图。从视图和几个表中选择是完全不同的查询(我认为),这个查询选择器可以轻松处理它。

6 个答案:

答案 0 :(得分:4)

您需要自己的查询编写对象,该对象可以通过特定于数据库的实现继承。

所以你会做类似的事情:

DbAgnosticQueryObject query = new PostgresSQLQuery();
query.setFrom('foo');
query.setSelect('id');
// and so on
CString queryString = query.toString();

一旦你从单个表中过去简单的选择,它就会变得相当复杂。已经有ORM包来处理很多这些细微差别;看着它们而不是自己编写它们可能是值得的。

答案 1 :(得分:1)

最佳选择:选择一个数据库,并为其编码。

您多久会在生产系统的后端更换数据库?即使你这样做了,你还需要担心的不仅仅是轻微的语法问题。 (连接语法等主要内容,甚至数据类型在数据库之间可能存在很大差异。)

现在,如果您正在设计一个商业应用程序,您希望客户在实现它时能够使用多个后端选项之一,那么您可能必须指定“我们支持Oracle,MS SQl或MYSQL “并对这些特定选项进行编码。

答案 2 :(得分:1)

您可以将所有选项缩减为

  

最差选项:让查询的代码检查数据库类型。

这只是你在逻辑上检查数据库类型的问题。

我在实践中看到的最佳选择是

  

更好的选择:在数据库连接对象上创建查询请求方法,该方法接受唯一的查询“代码”,并根据正在使用的数据库引擎返回相应的查询。

根据我的经验,很多更容易独立于其他代码测试查询。如果您的对象通过语法位拼凑查询,则会变得更加困难,因为您必须测试查询创建代码和查询本身。

如果将所有SQL拉出到手动编写和维护的单独文件中,您可以让某人是SQL专家来编写它们(您仍然可以自动测试这些查询)。如果你尝试编写查询生成函数,你基本上会有一个C ++专家编写SQL。

答案 3 :(得分:1)

选择一个ORM,然后开始映射。

如果您要支持多个数据库,您的问题只会变得更糟 并且只考虑正在进行的数据库 - 没有(或几乎没有)SQL的云数据库和对象数据库。

答案 4 :(得分:1)

将您的查询带到代码之外 - 将它们放在数据库或资源文件中,并允许覆盖不同的数据库引擎。

如果你使用SP,它可能更容易,因为SP会抽象你的数据库差异。

答案 5 :(得分:0)

我认为,如果您需要支持多个数据库的能力,那么您想要做的就是创建数据提供者接口(或抽象类)以及相关的具体实现。数据提供程序需要支持您的标准查询运算符以及支持查询操作所需的其他常用支持功能(请参阅.NET 3.5中的IEnumerable扩展方法)。然后,每个具体提供程序将基于目标数据库引擎将这些转换为特定查询。

基本上,您所做的是创建数据库抽象层并让您的代码与之交互。如果你能找到其中一个用于C ++,它可能值得买而不是写。您可能还希望为C ++寻找控制反转控制(IoC)容器,基本上可以执行此操作。我知道有几个用于Java和C#,但我对C ++并不熟悉。