2012-02-25 10 views
10

Estaba mirando somequestions que pregunta cómo hacer uniones en las consultas de Zend Framework, pero la respuesta es siempre algo así como "solo haz setIntegrityCheck(FALSE)".setIntegrityCheck en Zend Selecciona con une

Mi pregunta es: ¿Por qué necesito hacer esto?

Me parece incapacitante "comprobaciones de integridad" no es la forma correcta de hacer este trabajo. En mi caso particular, estoy usando una base de datos MySQL con algunas tablas InnoDB con claves externas, así por ejemplo:

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`); 

(esta es una versión muy simplificada de mi DB)

Y, mi consulta código es el siguiente:

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

esto me está dando la "consulta de selección no puede unirse con otra mesa" excepción a menos que añado el setIntegrity(FALSE) a mi $select.

Respuesta

9

Ok, he hecho un poco de investigación, y no es del todo cierto que usted tiene que llamar setIntegrityCheck(FALSE) con el fin de hacer une.

El código correspondiente en la clase Zend_Db_Select (es decir, el único lugar para encontrar la última palabra a este argumento), contiene este código:

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'); 
      } 
     } 
    } 
} 

Así que, en realidad, se comprueba para ver si todo los campos seleccionados en la consulta pertenecen a la "tabla principal". Una consulta no necesariamente tiene que devolver todos los campos en las tablas involucradas.

Volviendo al ejemplo de mi pregunta, resulta que esto hace trabajo:

$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); 

Esta nueva consulta sólo devuelve los campos de tableB, pero se puede añadir where condiciones en cualquiera de las tablas, como lo haría normalmente con SQL, sin ningún problema.

+0

Sí, eso funciona, pero como ha señalado, no puede obtener ninguno de los datos de las tablas combinadas en su conjunto de resultados. Como los datos aún SON de la tabla principal, entonces no ha violado la integridad del resultado, "todos sus datos pertenecen a la tabla principal". Sin embargo, es útil si solo desea obtener filas que tengan la clave externa de la tabla A. Gracias por señalarlo. – drew010

+0

con comprobación de integridad deshabilitada. Pude recuperar de tablas primarias y combinadas. Gracias por la información @cambraca – Varshaan

20

Calling setIntegrityCheck(false) es la forma correcta de hacer una unión; si está utilizando Zend_Db_Table y Zend_Db_Table_Select, no puede unirse a menos que se desactive la comprobación de integridad.

La verificación de integridad simplemente se realiza para asegurarse de que la consulta NO utiliza varias tablas y, cuando está en su lugar, asegura que los objetos Zend_Db_Table_Row se pueden eliminar o modificar y guardar porque los datos de la fila son exclusivos de una sola tabla y no es una mezcla de datos de diferentes tablas.

Para indicar que desea utilizar varias tablas, a continuación, especifique setIntegrityCheck(false) para que Zend Framework saber que es intencional. El resultado es que obtiene una fila bloqueada que no puede llamar al save() o delete().

Aquí es una cita de la guía de referencia sobre Zend_Db_Table - Advanced Usage (pase al ejemplo 27.

El Zend_Db_Table_Select se utiliza principalmente para limitar y validar fin de que pueda cumplir los criterios para una consulta legal SELECT Sin embargo, puede haber ciertos casos donde requiera la flexibilidad del componente Zend_Db_Table_Row y no requiera una fila escribible o borrable. Para este caso de usuario específico, es posible ret Rieve una fila o conjunto de filas pasando un valor FALSE a setIntegrityCheck(). El fila o conjunto de filas resultante se devolverán como una fila 'bloqueado' (es decir, el save(), de eliminación() y cualquier campo de fijación de métodos lanzará una excepción).

Consulte también: One-to-Many Joins with Zend_Db_Table_Select