2014-03-06 4 views
0

이 쿼리가 나를 위해 많은 문제를했다 : 정말이 왜 첫번째 때문에 괄호에 문제SQLSTATE는 [HY093] : 잘못된 매개 변수 번호

/* Looking for a machine already attributed to a site: 
     *  - Date_started is in the given period 
     * OR - Date_ended is in the giver period 
     * OR - Date_started is before the period's end AND date_ended is null 
     * AND - Que l'on parle de la même machine 
     */      
$dsql = $tmp->_dsql(); 
$machine = $tmp->selectQuery(array('site')) 
      ->where($dsql->andExpr() 
      ->where($dsql->orExpr() 
       ->where('date_started BETWEEN "' 
         .$dsql->escape($this['date_started']). 
         '" AND "' 
         .$dsql->escape($this['date_ended']). 
         '"') 
       ->where('date_ended BETWEEN "' 
         .$dsql->escape($this['date_started']). 
         '" AND "' 
         .$dsql->escape($this['date_ended']). 
         '"') 
       ->where($tmp->_dsql()->andExpr() 
       ->where('date_started < "'.$dsql->escape($this['date_ended']).'"') 
       ->where('date_ended IS null') 
       ) 
      ) 
      ->where('machine_id = '.$dsql->escape($this['machine_id'])) 
      ->where('id != '.$dsql->escape($this['id'])) 
      ) 
      ->getOne(); 

부지 orExprandExpr. 그런 다음 BETWEEN 때문에 값을 이스케이프하는 where ($ field, $ cond, $ value)를 사용하지 못하게합니다.

값을 이스케이프 처리하지 않으면 작동하지만 정상적으로 데이터를 신뢰해서는 안됩니다. $ dsql-> expr() 및 setCustom에서 전체 쿼리를 적어도되지만 위대한 프레임 워크를 사용하는 것은 아닙니다.

편집 : 당신은 약간의 조건을 단순화 할 수

Additional information: 

pdo_error: SQLSTATE[HY093]: Invalid parameter number: no parameters were bound 
mode: select 
params: 
query: select (select concat(`site`.`emplacement`, " (", (select `nom` from `region` where `site`.`region_id` = `region`.`id`), ")") `designation` from `site` where `site_machine`.`site_id` = `site`.`id`) `site`,`id`,`machine_id`,`site_id` from `site_machine` where ((date_started BETWEEN ":a" AND ":a_2" or date_ended BETWEEN ":a_3" AND ":a_4" or (date_started < ":a_5" and date_ended IS null)) and machine_id = :a_6 and id != :a_7) 

답변

0

. 이것은 당신이 당신의 질문에 쓴 변함 없을 것이다 : 당신은 많은 양의 데이터가없는 경우 더 이상 너무 문제 BETWEEN :

,

date_started < period_end 
AND (date_ended is null OR date_ended >= period_start) 

그래, 당신도 할 수있다 이렇게하고 OR을 완전히 제거하십시오. 그러나 명심, 그 IFNULL (date_ended)는 인덱스를 사용하지 않습니다 아마 느리게 작동합니다 (SELECT의 실행 계획을 확인) :

date_started < period_end 
AND IFNULL(date_ended, period_start) >= period_start 
+0

들으을 감상의 나의 부족을 강조하지 않는) 그것은 작동하지만 우려했다 오류에 대해. 나는 (arg, arg, arg) where와 dsql-> escape를 직접 섞을 수 없다는 것을 이해했다. 하지만 여기에 나는 모든 것을 dsql-> escape로 바꿨고 여전히 PDO 오류가 발생했습니다. – Sluggogle

+0

어쩌면 $ dsql-> debug()를 추가하고 ATK가 생성하는 SELECT 쿼리를 게시 할 수 있습니까? – DarkSide

관련 문제