数据库抽象 - 支持多种语法

时间:2008-10-19 12:00:48

标签: sql database data-access-layer database-abstraction

在我正在研究的PHP项目中,我们需要创建一些DAL扩展来支持多个数据库平台。我们遇到的主要缺陷是不同的平台有不同的语法 - 值得注意的是MySQL和MSSQL完全不同。

最好的解决办法是什么?

以下是我们讨论的一对夫妇:

基于类的SQL构建

这将涉及创建一个允许您逐位构建SQL查询的类。例如:

$stmt = new SQL_Stmt('mysql');
$stmt->set_type('select');
$stmt->set_columns('*');
$stmt->set_where(array('id' => 4));
$stmt->set_order('id', 'desc');
$stmt->set_limit(0, 30);
$stmt->exec();

虽然单个查询确实涉及很多行。

SQL语法重新格式化

此选项更清晰 - 它将读取SQL代码并根据输入和输出语言重新格式化。我可以看到,就解析而言,这是一个慢得多的解决方案。

4 个答案:

答案 0 :(得分:1)

解决方案可能是针对不同平台使用不同的查询集,其ID类似于

MySql:GET_USERS =“SELECT * FROM users”

MsSql:GET_USERS = ...

PgSql:GET_USERS = ...

然后在启动时加载所需的查询集,然后引用

Db的:: loadQueries(平台):

$ users = $ db-> query(GET_USERS)

答案 1 :(得分:1)

这样的方案不会考虑SQL提供的所有丰富性,因此对于每个数据库的所有表,使用代码生成的存储过程会更好。

即使你使用更具数据库模型意识的参数化存储过程(即它们确实加入或者是用户感知的,因此针对每个供应商进行了优化),这仍然是一个很好的方法。我总是将数据库接口层视为为应用程序提供的不仅仅是简单的表,因为这种方法可能带宽密集且往返浪费。

答案 2 :(得分:1)

我建议使用基于类的SQL构建,并推荐DoctrineZend_DbMDB2。是的,如果需要更多行来编写简单的选择,但至少你需要依赖解析器而不需要重新发明轮子。

使用任何DBAL都是速度的折衷,而不仅仅是数据库执行,但是当你第一次使用它们时,它会比你真正熟悉它时更痛苦。此外,我几乎100%确定生成的代码不是最快的SQL查询,但这是我之前所说的权衡。

最终取决于你,所以尽管我不会这样做并且肯定不是不可能的,但问题仍然存在,如果你实际上可以通过实施自己的DBAL来节省时间和资源(从长远来看)。

答案 3 :(得分:1)

如果您有一组支持它的后端,我同意生成存储过程以形成合同是最好的方法。但是,如果您的后端在存储过程方面的能力有限,则此方法不起作用,在这种情况下,您构建一个抽象层来实现SQL或基于抽象/有限的sql语法生成目标特定的sql。