14

我正在查看一些 询问如何在 Zend Framework 查询中进行连接的问题,但答案总是类似于“只做setIntegrityCheck(FALSE)”。

我的问题是:为什么我需要这样做?

在我看来,禁用“完整性检查”并不是完成这项工作的正确方法。在我的特殊情况下,我正在使用带有一些带有外键的 InnoDB 表的 MySQL 数据库,例如:

CREATE TABLE IF NOT EXISTS `tableA`
(
`id` CHAR(6),
`name` VARCHAR(255),
PRIMARY KEY (`id`)
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS `tableB`
(
`tableA_id` CHAR(6),
`somefield` VARCHAR(255),
PRIMARY KEY (`tableA_id`)
) ENGINE=InnoDB;

ALTER TABLE `tableB` ADD FOREIGN KEY fk1 (`tableA_id`) REFERENCES `tableA` (`id`);

(这是我的数据库的一个非常简化的版本)

而且,我的查询代码如下所示:

$table = new Zend_Db_Table('tableB');
$select = $table->select(TRUE)
  ->join(array('a' => 'tableA'), 'tableB.tableA_id = a.id');
$result = $table->fetchAll($select);

这给了我“选择查询无法加入另一个表”异常,除非我setIntegrity(FALSE)$select.

4

2 回答 2

24

调用setIntegrityCheck(false)是进行连接的正确方法;如果您使用Zend_Db_Tableand Zend_Db_Table_Select,除非您禁用完整性检查,否则您无法加入。

完整性检查只是为了确保查询不使用多个表,并且在到位时,确保Zend_Db_Table_Row可以删除或修改对象然后保存,因为行数据是单个表独有的,而不是来自不同表的数据混合。

表示您想使用多个表,然后指定setIntegrityCheck(false)让 Zend Framework 知道这是有意的。结果是您得到一个无法调用save()delete()打开的锁定行。

这是Zend_Db_Table - Advanced Usage参考指南的引述(跳至示例 27。

Zend_Db_Table_Select主要用于约束和验证,以便它可以强制执行合法SELECT查询的标准。然而,在某些情况下,您可能需要 Zend_Db_Table_Row组件的灵活性并且不需要可写或可删除的行。对于这个特定的用户案例,可以通过将FALSE值传递给setIntegrityCheck()来检索行或行集。结果行或行集将作为“锁定”行返回(意味着save()delete()和任何字段设置方法都会抛出异常)。

另请参阅:Zend_Db_Table_Select 的一对多连接

于 2012-02-25T01:46:19.663 回答
10

好的,我做了一些研究,你必须打电话才能加入,这并不完全正确。setIntegrityCheck(FALSE)

类中的相关代码Zend_Db_Select(即唯一找到该参数最后一个单词的地方)包含以下代码:

if ($this->_integrityCheck !== false) {
    foreach ($fields as $columnEntry) {
        list($table, $column) = $columnEntry;

        // Check each column to ensure it only references the primary table
        if ($column) {
            if (!isset($from[$table]) || $from[$table]['tableName'] != $primary) {
                require_once 'Zend/Db/Table/Select/Exception.php';
                throw new Zend_Db_Table_Select_Exception('Select query cannot join with another table');
            }
        }
    }
}

因此,实际上,它会检查查询中所有选定的字段是否都属于“主表”。查询不一定必须返回相关表中的所有字段。

回到我的问题中的示例,事实证明这确实有效:

$table = new Zend_Db_Table('tableB');
$select = $table->select(TRUE)
  ->join(array('a' => 'tableA'), 'tableB.tableA_id = a.id', NULL); // <-- notice the third parameter here
$result = $table->fetchAll($select);

这个新查询只返回 中的字段tableB,但您可以where在任何表上添加条件,就像您通常使用 SQL 所做的那样,没有问题。

于 2012-02-25T18:49:40.917 回答