【问题标题】:Zend Framework - Problem with Database Table Recursive Cascading DeletesZend Framework - 数据库表递归级联删除问题
【发布时间】:2010-12-22 10:29:38
【问题描述】:

我的情况可能有点不正常,但我在 MySQL 数据库中定义了外键,同时在 Zend_Db_Table 类中强制执行引用完整性。这些表使用 InnoDB 存储引擎。

删除记录时,Zend 框架将通过表模型中的$_referenceMap 正确识别直接子级并删除它们。但是,如果有直接孩子的任何孩子,我会从数据库中收到关于违反该外键的引用完整性的错误:SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint failsZend_Db_Table_Abstract 似乎没有以递归方式强制执行引用完整性。

有没有其他人遇到过这种情况?是Zend Framework bug吗?解决方法?修复?


更新

将近一周后,我没有回答这个问题。我想我必须自己扩展 Zend_Db_Table_Row_Abstract 类来完成这个。

【问题讨论】:

  • @OMG Ponies:感谢您添加mysql-error-1451 标签

标签: mysql zend-framework zend-db-table referential-integrity mysql-error-1451


【解决方案1】:

我最终扩展了Zend_Db_Table_Abstract 类来实现这一点。 _cascadeDelete 公共函数调用数据库适配器 delete 函数。我进行了更改,以便改为调用来自Zend_Db_Table_Row_Abstractdelete 函数。这使得记录删除是递归的。

更新:我添加了代码,将删除时设置为self::SET_NULL

这是我修改后的_cascadeDelete

/**
 * Called by parent table's class during delete() method.
 *
 * @param  string $parentTableClassname
 * @param  array  $primaryKey
 * @return int    Number of affected rows
 */
public function _cascadeDelete($parentTableClassname, array $primaryKey)
{
    $this->_setupMetadata();
    $rowsAffected = 0;
    foreach ($this->_getReferenceMapNormalized() as $map) {
        if ($map[self::REF_TABLE_CLASS] == $parentTableClassname && isset($map[self::ON_DELETE])) {
            switch ($map[self::ON_DELETE]) {
                case self::CASCADE:
                    $select = $this->select();
                    for ($i = 0; $i < count($map[self::COLUMNS]); ++$i) {
                        $col = $this->_db->foldCase($map[self::COLUMNS][$i]);
                        $refCol = $this->_db->foldCase($map[self::REF_COLUMNS][$i]);
                        $type = $this->_metadata[$col]['DATA_TYPE'];
                        $select->where($this->_db->quoteIdentifier($col, true) . ' = ?',
                            $primaryKey[$refCol], $type);
                    }
                    $rows = $this->fetchAll($select);
                    $rowsAffected += count($rows);
                    foreach ($rows as $row) {
                        $row->delete();
                    }
                    break;
                case self::SET_NULL: {
                    $update = array();
                    $where = array();
                    for ($i = 0; $i < count($map[self::COLUMNS]); ++$i) {
                        $col = $this->_db->foldCase($map[self::COLUMNS][$i]);
                        $refCol = $this->_db->foldCase($map[self::REF_COLUMNS][$i]);
                        $type = $this->_metadata[$col]['DATA_TYPE'];
                        $update[$col] = null;
                        $where[] = $this->_db->quoteInto(
                            $this->_db->quoteIdentifier($col, true) . ' = ?',
                            $primaryKey[$refCol], $type);
                    }
                    $rowsAffected += $this->update($update, $where);
                    break;
                }
                default:
                    // no action
                    break;
            }
        }
    }
    return $rowsAffected;
}

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-27
  • 2018-01-13
  • 2021-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多