복붙노트

MySQL IN 문에 대한 PDO 바인딩 값

PHP

MySQL IN 문에 대한 PDO 바인딩 값

저는 PDO에 관해서 제가 꽤 오랫동안 그것에 시달린 후에 답을 얻고 싶습니다.

이 예제를 보자.

나는 ID 배열을 PDO 문에 바인딩하여 MySQL IN 문에 사용한다.

배열은 다음과 같이됩니다 : $ values ​​= array (1,2,3,4,5,6,7,8);

데이터베이스 안전 변수는 $ products = implode ( ','$ values);

따라서 $ 제품은 '1,2,3,4,5,6,7,8'값을 갖는 STRING이됩니다.

성명은 다음과 같습니다.

SELECT users.id
FROM users
JOIN products
ON products.user_id = users.id
WHERE products IN (:products)

물론, $ products는 products로 선언문에 바인딩됩니다.

그러나 문이 컴파일되고 값이 바인딩되면 실제로 다음과 같이 보입니다.

SELECT users.id
FROM users
JOIN products
ON products.user_id = users.id
WHERE products IN ('1,2,3,4,5,6,7,8')

문제는 명령문에 바인드 할 쉼표로 구분 된 값으로 준비 했으므로 IN 문 내부의 모든 것을 단일 문자열로 실행한다는 것입니다.

내가 실제로 필요한 것은 :

SELECT users.id
FROM users
JOIN products
ON products.user_id = users.id
WHERE products IN (1,2,3,4,5,6,7,8)

이 작업을 실제로 수행 할 수있는 유일한 방법은 값 자체를 바인딩하지 않고 문자열 자체에 배치하는 것입니다. 그러나이를 수행하는 더 쉬운 방법이 있어야합니다.

해결법

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

    1.이것은이 질문에서 질문 한 것과 같습니다 : 배열을 IN () 조건에 바인딩 할 수 있습니까?

    이것은이 질문에서 질문 한 것과 같습니다 : 배열을 IN () 조건에 바인딩 할 수 있습니까?

    그 대답은 in 절의 가변 크기 목록에 대해 직접 쿼리를 구성해야한다는 것입니다.

    그러나 큰 데이터 세트의 경우 쉼표로 구분 된 쉼표로 구분 된 목록을 사용할 수 있지만 테이블의 모든 값을 char 유형으로 변환해야하므로 성능에 상당한 영향을 미칩니다.

    예 :

    select users.id
    from users
    join products
    on products.user_id = users.id
    where find_in_set(cast(products.id as char), :products)
    

    또는 세 번째 옵션으로 쉼표로 구분 된 목록을 나눌 수있는 사용자 정의 함수를 만들 수 있습니다 (cf. http://www.slickdev.com/2008/09/15/mysql-query-real-values- from-delimiter-separated-string-ids /). 아마도이 세 가지 옵션 중 가장 좋은 옵션 일 것입니다. 특히 (...) 절에 의존하는 많은 쿼리가있는 경우에 특히 그렇습니다.

  2. ==============================

    2.이 상황을 처리하는 좋은 방법은 str_pad를 사용하여? SQL 쿼리의 모든 값에 대해 그런 다음 값 배열 (귀하의 경우 $ 값)을 실행할 인수로 전달할 수 있습니다.

    이 상황을 처리하는 좋은 방법은 str_pad를 사용하여? SQL 쿼리의 모든 값에 대해 그런 다음 값 배열 (귀하의 경우 $ 값)을 실행할 인수로 전달할 수 있습니다.

    $sql = '
    SELECT users.id
    FROM users
    JOIN products
    ON products.user_id = users.id
    WHERE products.id IN ('.str_pad('',count($values)*2-1,'?,').')
    ';
    
    $sth = $dbh->prepare($sql);
    $sth->execute($values);
    $user_ids = $sth->fetchAll();
    

    이렇게하면 값을 SQL에 직접 삽입하는 대신 준비된 문을 사용하면 많은 이점을 얻을 수 있습니다.

    PS - 제공된 ID가있는 제품이 사용자 ID를 공유하면 결과는 중복 된 사용자 ID를 반환합니다. 고유 한 사용자 ID 만 원할 경우 쿼리의 첫 번째 행을 SELECT DISTINCT users.id로 변경하는 것이 좋습니다.

  3. ==============================

    3.이와 같은 상황에서 여러분이 가장 잘 준비 할 수있는 진술은 다음과 유사합니다 :

    이와 같은 상황에서 여러분이 가장 잘 준비 할 수있는 진술은 다음과 유사합니다 :

    SELECT users.id
    FROM users
    JOIN products
    ON products.user_id = users.id
    WHERE products IN (?,?,?,?,?,?,?,?)

    그런 다음 값을 반복하고 준비된 명령문에 바인드하여 바인딩중인 값과 같은 수의 물음표가 있는지 확인하십시오.

  4. ==============================

    4.$ values ​​배열에있는 값의 수와 IN의 동일한 수를? 제공해야합니다.

    $ values ​​배열에있는 값의 수와 IN의 동일한 수를? 제공해야합니다.

    이 배열은? s 배열을 다음과 같이 쉽게 만들 수 있습니다.

     $in = join(',', array_fill(0, count($values), '?'));
    

    IN 절에서이 $ in 배열을 사용하십시오

    이것은 동적으로 $ tail 배열에 따라 재단 된 배열을 제공합니다.

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

    5.아주 쉽게 할 수 있습니다. IN () 문의 값 배열이있는 경우 예 :

    아주 쉽게 할 수 있습니다. IN () 문의 값 배열이있는 경우 예 :

    $test = array(1,2,3);
    

    당신은 간단하게 할 수 있습니다.

    $test = array(1,2,3);
    $values = count($test);
    $criteria = sprintf("?%s", str_repeat(",?", ($values ? $values-1 : 0)));
    //Returns ?,?,?
    $sql = sprintf("DELETE FROM table where column NOT IN(%s)", $criteria);
    //Returns DELETE FROM table where column NOT IN(?,?,?)
    $pdo->sth = prepare($sql);
    $pdo->sth->execute($test);
    
  6. ==============================

    6.표현식이 bindValue ()로 값을 바인딩하지 않고 사용자 입력을 기반으로하는 경우, 실험적 SQL이 큰 선택이 아닐 수도 있습니다. 그러나 MySQL의 REGEXP를 사용하여 입력 구문을 검사하여 안전하게 만들 수 있습니다.

    표현식이 bindValue ()로 값을 바인딩하지 않고 사용자 입력을 기반으로하는 경우, 실험적 SQL이 큰 선택이 아닐 수도 있습니다. 그러나 MySQL의 REGEXP를 사용하여 입력 구문을 검사하여 안전하게 만들 수 있습니다.

    예 :

    SELECT *
    FROM table
    WHERE id IN (3,156)
    AND '3,156' REGEXP '^([[:digit:]]+,?)+$'
    
  7. ==============================

    7.다음은 알 수없는 레코드 수를 삽입 값에 바인딩하는 예입니다.

    다음은 알 수없는 레코드 수를 삽입 값에 바인딩하는 예입니다.

    public function insert($table, array $data)
    {
        $sql = "INSERT INTO $table (" . join(',', array_keys($data)) . ') VALUES ('
            . str_repeat('?,', count($data) - 1). '?)';
    
        if($sth = $this->db->prepare($sql))
        {
            $sth->execute(array_values($data));
            return $this->db->lastInsertId();
        }
    }
    
    $id = $db->insert('user', array('name' => 'Bob', 'email' => 'foo@example.com'));
    
  8. ==============================

    8.다음과 같이 시도하십시오.

    다음과 같이 시도하십시오.

    WHERE products IN(REPLACE(:products, '\'', ''))
    

    문안 인사

  9. from https://stackoverflow.com/questions/1586587/pdo-binding-values-for-mysql-in-statement by cc-by-sa and MIT license