복붙노트

WHERE 절을 사용하여 쿼리에 배열 전달하기

PHP

WHERE 절을 사용하여 쿼리에 배열 전달하기

주어진 배열의 ID $ galleries = array (1,2,5) WHERE 절에서 배열 값을 사용하는 SQL 쿼리를 원합니다.

SELECT *
FROM galleries
WHERE id = /* values of array $galleries... eg. (1 || 2 || 5) */

MySQL과 함께 사용할이 쿼리 문자열을 어떻게 생성 할 수 있습니까?

해결법

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

    1.

    $ids = join("','",$galleries);   
    $sql = "SELECT * FROM galleries WHERE id IN ('$ids')";
    
  2. ==============================

    2.

    PDO 사용 : [1]

    $in = join(',', array_fill(0, count($ids), '?'));
    $select = <<<SQL
        SELECT *
        FROM galleries
        WHERE id IN ($in);
    SQL;
    $statement = $pdo->prepare($select);
    $statement->execute($ids);
    

    MySQLi 사용하기 [2]

    $in = join(',', array_fill(0, count($ids), '?'));
    $select = <<<SQL
        SELECT *
        FROM galleries
        WHERE id IN ($in);
    SQL;
    $statement = $mysqli->prepare($select);
    $statement->bind_param(str_repeat('i', count($ids)), ...$ids);
    $statement->execute();
    $result = $statement->get_result();
    

    설명:

    일반적으로 다음과 같이 보입니다.

    expr IN (value,...)
    

    배열에서 () 안에 배치 할 수식을 만들 수 있습니다. 괄호 안에 적어도 하나의 값이 있어야합니다. 그렇지 않으면 MySQL은 오류를 반환합니다. 이것은 입력 배열에 적어도 하나의 값이 있는지 확인하는 것과 같습니다. SQL 삽입 공격을 방지하려면 먼저? 각 입력 항목에 대해 매개 변수가있는 쿼리를 만듭니다. 여기에 귀하의 ID를 포함하는 배열을 $ ids라고 가정합니다 :

    $in = join(',', array_fill(0, count($ids), '?'));
    
    $select = <<<SQL
        SELECT *
        FROM galleries
        WHERE id IN ($in);
    SQL;
    

    3 개의 항목 $ select의 입력 배열이 다음과 같이 나타납니다.

    SELECT *
    FROM galleries
    WHERE id IN (?, ?, ?)
    

    또 주목할 점은? 입력 배열의 각 항목에 대해 그런 다음 위에서 설명한대로 PDO 또는 MySQLi를 사용하여 쿼리를 준비하고 실행합니다.

    바운드 매개 변수 때문에 문자열과 정수 사이에서 쉽게 변경할 수 있습니다. PDO의 경우 변경이 필요하지 않습니다. MySQLi 변경 str_repeat ( 'i', str_repeat ( 's', 문자열을 검사해야하는 경우.

    [1] : 간결함을 위해 오류 검사를 생략했습니다. 각 데이터베이스 메서드에 대한 일반적인 오류를 확인하거나 예외를 throw하도록 DB 드라이버를 설정해야합니다.

    [2] : PHP 5.6 이상이 필요합니다. 다시 한 번 간략하게 오류 검사를 생략했습니다.

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

    3.

    ints :

    $query = "SELECT * FROM `$table` WHERE `$column` IN(".implode(',',$array).")";
    

    문자열 :

    $query = "SELECT * FROM `$table` WHERE `$column` IN('".implode("','",$array)."')";
    
  4. ==============================

    4.

    미리 입력 내용을 제대로 살균한다고 가정하면 ...

    $matches = implode(',', $galleries);
    

    그런 다음 쿼리를 조정하십시오.

    SELECT *
    FROM galleries
    WHERE id IN ( $matches ) 
    

    데이터 세트에 따라 적절하게 값을 인용하십시오.

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

    5.

    용도:

    select id from galleries where id in (1, 2, 5);
    

    각 루프에 대해 간단하게 작동합니다.

    Flavius ​​/ AvatarKava의 방법이 더 좋지만 배열 값에 쉼표가 없는지 확인하십시오.

  6. ==============================

    6.

    Flavius ​​Stef의 답은 intval ()을 사용하여 모든 ID가 int 값인지 확인할 수 있습니다.

    $ids = join(',', array_map('intval', $galleries));  
    $sql = "SELECT * FROM galleries WHERE id IN ($ids)";
    
  7. ==============================

    7.

    이스케이프 기능이있는 MySQLi의 경우 :

    $ids = array_map(function($a) use($mysqli) { 
        return is_string($a) ? "'".$mysqli->real_escape_string($a)."'" : $a;
      }, $ids);
    $ids = join(',', $ids);  
    $result = $mysqli->query("SELECT * FROM galleries WHERE id IN ($ids)");
    

    준비된 진술서가있는 PDO의 경우 :

    $qmarks = implode(',', array_fill(0, count($ids), '?'));
    $sth = $dbh->prepare("SELECT * FROM galleries WHERE id IN ($qmarks)");
    $sth->execute($ids);
    
  8. ==============================

    8.

    SQL 인젝션 취약점과 빈 상태를 처리해야합니다. 나는 아래 둘을 다룰 것이다.

    순수한 숫자 배열의 경우 적절한 유형 변환 즉 intval 또는 floatval 또는 doubleval을 각 요소 위에 사용하십시오. 원하는 경우 숫자 값에도 적용될 수있는 문자열 유형 mysqli_real_escape_string (). MySQL은 숫자와 날짜 변형을 문자열로 허용합니다.

    쿼리에 전달하기 전에 값을 적절하게 이스케이프하려면 다음과 유사한 함수를 만듭니다.

    function escape($string)
    {
        // Assuming $db is a link identifier returned by mysqli_connect() or mysqli_init()
        return mysqli_real_escape_string($db, $string);
    }
    

    이러한 함수는 이미 응용 프로그램에서 이미 사용 가능할 수도 있고 이미 작성한 기능 일 수도 있습니다.

    다음과 같이 문자열 배열을 살균하십시오.

    $values = array_map('escape', $gallaries);
    

    숫자 형 배열은 intval 또는 floatval 또는 doubleval을 대신 사용하여 위생 처리 될 수 있습니다 :

    $values = array_map('intval', $gallaries);
    

    마지막으로 쿼리 조건 작성

    $where  = count($values) ? "`id` = '" . implode("' OR `id` = '", $values) . "'" : 0;
    

    또는

    $where  = count($values) ? "`id` IN ('" . implode("', '", $values) . "')" : 0;
    

    $ gareries = array ();와 같이 배열도 때때로 비어있을 수 있기 때문에; 우리는 IN ()이 빈리스트를 허용하지 않는다는 것을 알아야한다. 대신 OR을 사용할 수도 있지만 문제는 여전히 남아 있습니다. 그래서 위의 검사 인 count ($ values)는 같은 것을 보장합니다.

    마지막 쿼리에 추가하십시오.

    $query  = 'SELECT * FROM `galleries` WHERE ' . $where;
    
  9. ==============================

    9.

    안전한.

    $galleries = array(1,2,5);
    array_walk($galleries , 'intval');
    $ids = implode(',', $galleries);
    $sql = "SELECT * FROM galleries WHERE id IN ($ids)";
    
  10. ==============================

    10.

    입력 배열을 적절히 필터링하면이 "WHERE id IN"절을 사용할 수 있습니다. 이 같은:

    $galleries = array();
    
    foreach ($_REQUEST['gallery_id'] as $key => $val) {
        $galleries[$key] = filter_var($val, FILTER_SANITIZE_NUMBER_INT);
    }
    

    아래 예와 같이 :

    $galleryIds = implode(',', $galleries);
    

    나는. 이제 안전하게 $ query = "SELECT * 갤러리에서 WHERE id IN ({$ galleryIds})";를 사용해야합니다.

  11. ==============================

    11.

    Col. Shrapnel의 PHP 용 SafeMySQL 라이브러리는 매개 변수가있는 쿼리에 유형 힌팅 된 자리 표시자를 제공하며 배열 작업을위한 편리한 자리 표시 자 두 개를 포함합니다. ? 자리 표시자는 배열을 쉼표로 구분 된 이스케이프 된 문자열 목록 *으로 확장합니다.

    예 :

    $someArray = [1, 2, 5];
    $galleries = $db->getAll("SELECT * FROM galleries WHERE id IN (?a)", $someArray);
    

    * MySQL이 자동 타입 강제 변환을 수행하기 때문에, SafeMySQL이 위의 id를 문자열로 변환하는 것은 중요하지 않습니다. 여전히 정확한 결과를 얻을 수 있습니다.

  12. ==============================

    12.

    테이블 텍스트 (T_ID (int), T_TEXT (텍스트)) 및 테이블 테스트 (id (int), var (varchar (255)))가있을 수 있습니다.

    테스트 값 (1, '1,2,3')에 삽입; 다음은 테이블 텍스트에서 행을 출력합니다. T_ID IN (1,2,3) :

    SELECT * FROM `texts` WHERE (SELECT FIND_IN_SET( T_ID, ( SELECT var FROM test WHERE id =1 ) ) AS tm) >0
    

    이 방법을 사용하면 여분의 테이블없이 간단한 n2m 데이터베이스 관계를 관리하고 PHP 나 다른 프로그래밍 언어를 사용할 필요없이 SQL 만 사용할 수 있습니다.

  13. ==============================

    13.

    원래 질문은 숫자 배열과 관련이 있고 주어진 예제를 작동시킬 수없는 문자열 배열을 사용하고 있기 때문입니다.

    각 문자열을 작은 따옴표로 묶어서 IN () 함수로 작업해야한다는 것을 알았습니다.

    여기 내 해결책이있다.

    foreach($status as $status_a) {
            $status_sql[] = '\''.$status_a.'\'';
        }
        $status = implode(',',$status_sql);
    
    $sql = mysql_query("SELECT * FROM table WHERE id IN ($status)");
    

    보시다시피 첫 번째 함수는 각 배열 변수를 작은 따옴표 (\ ')로 묶은 다음 배열을 내삽합니다.

    참고 : $ status에는 SQL 문에 작은 따옴표가 없습니다.

    따옴표를 추가하는 것이 더 좋은 방법 일 수 있지만이 방법이 효과적입니다.

  14. ==============================

    14.

    IN 쿼리를 사용하는 것 외에도 IN 쿼리에 SQL 인젝션 취약점의 위험이 있으므로 두 가지 옵션이 있습니다. 루핑을 사용하여 원하는 정확한 데이터를 얻거나 OR 케이스와 함께 쿼리를 사용할 수 있습니다.

    1. SELECT *
          FROM galleries WHERE id=1 or id=2 or id=5;
    
    
    2. $ids = array(1, 2, 5);
       foreach ($ids as $id) {
          $data[] = SELECT *
                        FROM galleries WHERE id= $id;
       }
    
  15. ==============================

    15.

    추가 예제 :

    $galleryIds = [1, '2', 'Vitruvian Man'];
    $ids = array_filter($galleryIds, function($n){return (is_numeric($n));});
    $ids = implode(', ', $ids);
    
    $sql = "SELECT * FROM galleries WHERE id IN ({$ids})";
    // output: 'SELECT * FROM galleries WHERE id IN (1, 2)'
    
    $statement = $pdo->prepare($sql);
    $statement->execute();
    
  16. ==============================

    16.

    아래는 다른 데이터를 위해 명명 된 자리 표시자를 사용하여 PDO를 사용한 필자가 사용한 방법입니다. SQL 삽입을 극복하기 위해 배열을 필터링하여 정수 값만 허용하고 다른 모든 값은 거부합니다.

    $owner_id = 123;
    $galleries = array(1,2,5,'abc');
    
    $good_galleries = array_filter($chapter_arr, 'is_numeric');
    
    $sql = "SELECT * FROM galleries WHERE owner=:OWNER_ID AND id IN ($good_galleries)";
    $stmt = $dbh->prepare($sql);
    $stmt->execute(array(
        "OWNER_ID" => $owner_id,
    ));
    
    $data = $stmt->fetchAll(PDO::FETCH_ASSOC);
    
  17. ==============================

    17.

    PDO가없는 안전한 방법 :

    $ids = array_filter(array_unique(array_map('intval', (array)$ids)));
    
    if ($ids) {
        $query = 'SELECT * FROM `galleries` WHERE `id` IN ('.implode(',', $ids).');';
    }
    
  18. ==============================

    18.

    SQL 삽입을 방지하는 기본 방법은 다음과 같습니다.

    준비된 문과 매개 변수화 된 쿼리를 사용하는 것이 더 나은 방법이지만, 이스케이프 문자를 선택하면 아래 예를 시도 할 수 있습니다.

    array_map을 사용하여 $ galleries의 각 요소에 작은 따옴표를 추가하여 쿼리를 생성 할 수 있습니다.

    $galleries = array(1,2,5);
    
    $galleries_str = implode(', ',
                         array_map(function(&$item){
                                       return "'" .mysql_real_escape_string($item) . "'";
                                   }, $galleries));
    
    $sql = "SELECT * FROM gallery WHERE id IN (" . $galleries_str . ");";
    

    생성 된 $ sql var은 다음과 같습니다.

    SELECT * FROM gallery WHERE id IN ('1', '2', '5');
    
  19. from https://stackoverflow.com/questions/907806/passing-an-array-to-a-query-using-a-where-clause by cc-by-sa and MIT lisence