복붙노트

[SQL] 가변 크기 변수 목록과 MySQL의 문 준비

SQL

가변 크기 변수 목록과 MySQL의 문 준비

어떻게 인수의 서로 다른 숫자 각 시간이 소요 PHP에서 준비된 MySQL의 명령문을 작성? 예 같은 질의는 다음과 같습니다

SELECT `age`, `name` FROM `people` WHERE id IN (12, 45, 65, 33)

IN 절은 ID의 다른 수에게이 실행될 때마다이있을 것이다.

나는 내 마음 속에 두 가지 솔루션을 가지고 있지만 더 나은 방법이 있는지보고 싶어요.

해결 방법은 1 문 100 개 변수를 적용하고 테이블에 있어야하지 보장 더미 값으로 나머지를 채우기; 100 개 이상의 값을 여러 번 호출합니다.

가능한 해결 방법이 할 일이 준비된 문을 사용하지; 구축 가능한 주입 공격에 대해 엄격하게 검사하는 쿼리를 실행합니다.

해결법

  1. ==============================

    1.나는 몇 가지 솔루션을 생각할 수 있습니다.

    나는 몇 가지 솔루션을 생각할 수 있습니다.

    한 가지 해결책은 임시 테이블을 만들 수 있습니다. 당신이 절에에있는 것이라고 각 매개 변수에 대한 테이블에 삽입 작업을 수행합니다. 그리고 단순한는 임시 테이블에 대해 조인 않습니다.

    또 다른 방법은 이런 식으로 뭔가를 할 수 있습니다.

    $dbh=new PDO($dbConnect, $dbUser, $dbPass);
    $parms=array(12, 45, 65, 33);
    $parmcount=count($parms);   // = 4
    $inclause=implode(',',array_fill(0,$parmcount,'?')); // = ?,?,?,?
    $sql='SELECT age, name FROM people WHERE id IN (%s)';
    $preparesql=sprintf($sql,$inclause);  // = example statement used in the question
    $st=$dbh->prepare($preparesql);
    $st->execute($parms);
    

    나는 생각한다,하지만 첫 번째 솔루션은 더 큰 목록에 대한 더 좋을 수도 있다는 증거가없고, 나중에 작은 목록에 대한 작동합니다.

    여기 @orrd 행복을하려면 간결한 버전입니다.

    $dbh=new PDO($dbConnect, $dbUser, $dbPass);
    $parms=array(12, 45, 65, 33);
    $st=$dbh->prepare(sprintf('SELECT age, name FROM people WHERE id IN (%s)',
                              implode(',',array_fill(0,count($parms),'?'))));
    $st->execute($parms);
    
  2. ==============================

    2.그 두번째 파라미터 콤마 분리 값의 캐릭터 인 FIND_IN_SET 기능이있다 :

    그 두번째 파라미터 콤마 분리 값의 캐릭터 인 FIND_IN_SET 기능이있다 :

    SELECT age, name FROM people WHERE FIND_IN_SET(id, '12,45,65,33')
    
  3. ==============================

    3.흉 SQL 래퍼 배열 값에 바인딩 지원. 즉

    흉 SQL 래퍼 배열 값에 바인딩 지원. 즉

    $sql = "... WHERE id IN (?)";
    $values = array(1, 2, 3, 4);
    $result = $dbw -> prepare ($sql, $values) -> execute ();
    
  4. ==============================

    4.테이블 떨어져 # 2를 확인하시기 바랍니다. 준비된 문은 SQL 주입으로부터 자신을 보호하는 고려해야 할 유일한 방법입니다.

    테이블 떨어져 # 2를 확인하시기 바랍니다. 준비된 문은 SQL 주입으로부터 자신을 보호하는 고려해야 할 유일한 방법입니다.

    당신이 할 수있는 무엇, 그러나, 바인딩 변수의 동적 세트를 생성합니다. 당신은 7 (103)를 필요로하는 경우 즉, (100)를하지 않습니다.

  5. ==============================

    5.내가 내 대답에서 가져온 : http://bugs.php.net/bug.php?id=43568 이건 내 문제에 대한 내 작업 솔루션입니다. 내가 원하는대로 지금은 동적으로 많은 매개 변수로 사용할 수 있습니다. 내가 동적 쿼리에 대한 모든를 얻기 위해 (이메일 = 'johndoe@gmail.com'이 곳의 모든 ID를 발견하는) 배열 또는이 경우 내가 마지막 쿼리에서 ID를 통과하고 같이 가지고 그들은 같은 수있을 것입니다 에 상관없이 이러한 각 ID에 대한 정보를 얼마나 많은 내가 필요로 끝낸다.

    내가 내 대답에서 가져온 : http://bugs.php.net/bug.php?id=43568 이건 내 문제에 대한 내 작업 솔루션입니다. 내가 원하는대로 지금은 동적으로 많은 매개 변수로 사용할 수 있습니다. 내가 동적 쿼리에 대한 모든를 얻기 위해 (이메일 = 'johndoe@gmail.com'이 곳의 모든 ID를 발견하는) 배열 또는이 경우 내가 마지막 쿼리에서 ID를 통과하고 같이 가지고 그들은 같은 수있을 것입니다 에 상관없이 이러한 각 ID에 대한 정보를 얼마나 많은 내가 필요로 끝낸다.

    <?php $NumofIds = 2; //this is the number of ids i got from the last query
        $parameters=implode(',',array_fill(0,$NumofIds,'?')); 
        // = ?,? the same number of ?'s as ids we are looking for<br />
        $paramtype=implode('',array_fill(0,$NumofIds,'i')); // = ii<br/>
        //make the array to build the bind_param function<br/>
        $idAr[] = $paramtype; //'ii' or how ever many ?'s we have<br/>
        while($statement->fetch()){ //this is my last query i am getting the id out of<br/>
            $idAr[] = $id;  
        }
    
        //now this array looks like this array:<br/>
        //$idAr = array('ii', 128, 237);
    
        $query = "SELECT id,studentid,book_title,date FROM contracts WHERE studentid IN ($parameters)";
        $statement = $db->prepare($query);
        //build the bind_param function
        call_user_func_array (array($statement, "bind_param"), $idAr);
        //here is what we used to do before making it dynamic
        //statement->bind_param($paramtype,$v1,$v2);
        $statement->execute();
    ?>
    
  6. ==============================

    6.당신은 당신의 IN 절에서 정수 값을 사용하는 경우, SQL 매개 변수를 사용하지 않고 동적으로 쿼리를 작성에 대한 주장 아무것도 없다.

    당신은 당신의 IN 절에서 정수 값을 사용하는 경우, SQL 매개 변수를 사용하지 않고 동적으로 쿼리를 작성에 대한 주장 아무것도 없다.

    function convertToInt(&$value, $key)
    {
        $value = intval($value);
    }
    
    $ids = array('12', '45', '65', '33');
    array_walk($ids, 'convertToInt');
    $sql = 'SELECT age, name FROM people WHERE id IN (' . implode(', ', $ids) . ')';
    // $sql will contain  SELECT age, name FROM people WHERE id IN (12, 45, 65, 33)
    

    그러나 의심의 여지없이 여기에 솔루션은이 문제에 대한 더 일반적인 방법입니다.

  7. ==============================

    7.오늘 비슷한 문제가 있었다 나는이 주제를 발견했다. 답변을 보면 그리고 내가 꽤 해결책을 발견 구글 주위에 검색.

    오늘 비슷한 문제가 있었다 나는이 주제를 발견했다. 답변을 보면 그리고 내가 꽤 해결책을 발견 구글 주위에 검색.

    내 문제는,하지만 조금 더 복잡합니다. 너무 결합 값 및 동적 고정 했으므로.

    이 솔루션입니다.

    $params = array()
    $all_ids = $this->get_all_ids();
    
    for($i = 0; $i <= sizeof($all_ids) - 1; $i++){
        array_push($params, $all_ids[$i]['id']);
    }
    
    $clause = implode(',', array_fill(0, count($params), '?')); // output ?, ?, ?
    $total_i = implode('', array_fill(0, count($params), 'i')); // output iiii
    
    $types = "ss" . $total_i; // will reproduce : ssiiii ..etc
    
    // %% it's necessary because of sprintf function
    $query = $db->prepare(sprintf("SELECT * 
                                    FROM clients    
                                    WHERE name LIKE CONCAT('%%', ?, '%%') 
                                    AND IFNULL(description, '') LIKE CONCAT('%%', ?, '%%')
                                    AND id IN (%s)", $clause));
    
    $thearray = array($name, $description);
    $merge    = array_merge($thearray, $params); // output: "John", "Cool guy!", 1, 2, 3, 4
    
    // We need  to pass variables instead of values by reference
    // So we need a function to that
    call_user_func_array('mysqli_stmt_bind_param', array_merge (array($query, $types), $this->makeValuesReferenced($merge))); 
    

    그리고 함수는 makeValuesreferenced :

    public function makeValuesReferenced($arr){
        $refs = array();
        foreach($arr as $key => $value)
            $refs[$key] = &$arr[$key];
        return $refs;
    }
    

    (+ array_push 여부) https://bugs.php.net/bug.php?id=49946, PHP가 다른 하나 개의 배열을 추가, [PHP] :이 '노하우'취득하기위한 링크 오류 -> 너무 적음 PHP 5.3.1 참조 문제의 sprintf (); http://no2.php.net/manual/en/mysqli-stmt.bind-param.php#89171 통과에 인수

  8. from https://stackoverflow.com/questions/327274/mysql-prepared-statements-with-a-variable-size-variable-list by cc-by-sa and MIT license