使用连接设置Zend Select中的完整性检查

时间:2012-02-25 00:57:18

标签: zend-framework zend-db-select

我在查看some questions询问如何在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,否则这会给我“选择查询无法加入其他表格”例外。

2 个答案:

答案 0 :(得分:23)

调用setIntegrityCheck(false)是进行加入的正确方法;如果您使用Zend_Db_TableZend_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(),任何字段设置方法都会抛出异常。)

另请参阅:One-to-Many Joins with Zend_Db_Table_Select

答案 1 :(得分:9)

好的,我做了一些研究,而且非常真实你需要调用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一样,没有问题。