programing

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

copyandpastes 2022. 11. 8. 21:32
반응형

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

" " " 을 합니다.$galleries = array(1,2,5)다음과 같은 WHERE 절의 배열 값을 사용하는 SQL 쿼리를 만들고 싶습니다.

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

MySQL에서 사용할 이 쿼리 문자열을 생성하려면 어떻게 해야 합니까?

주의! 이 답변에는 심각한 SQL 주입 취약성이 포함되어 있습니다.여기에 제시된 코드샘플은 외부 입력이 삭제되었는지 확인하지 않고 사용하지 마십시오.

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

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

설명:

을 합니다.IN()연산자를 사용하여 지정된 목록에 값이 있는지 확인합니다.

일반적으로 다음과 같습니다.

expr IN (value,...)

해서 '내부' 수 있어요.()어레이에서 제외됩니다.괄호 안에 적어도1개의 값이 있어야 합니다.MySQL을 사용하다이것은 입력 배열에 적어도1개의 값이 포함되어 있는 것을 확인하는 것과 같습니다.공격을 SQL을 합니다.?각 입력 항목에 대해 매개 변수화된 쿼리를 만듭니다.에서는, 를 을 「ID」라고 .$ids:

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

$select = <<<SQL
    SELECT *
    FROM galleries
    WHERE id IN ($in);
SQL;

항목의 되면 3개 항목에서 입력 배열은 3개 항목입니다.$select음음음같 뭇매하다

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

한 번 주의해 .?을 사용법그런 다음 PDO 또는 MySQLi를 사용하여 위에서 설명한 대로 쿼리를 준비하고 실행합니다.

「 」의 IN()이 있는

파라미터가 바운드되어 있기 때문에 문자열과 정수를 쉽게 변경할 수 있습니다.의 경우 PDO의 경우 MySQLi 변경의 경우 MySQLi로 변경할 수 있습니다.str_repeat('i',로로 합니다.str_repeat('s',스트링 체크가 필요한 경우.

[1]: 간결성 확인을 위해 몇 가지 오류를 누락했습니다.각 데이터베이스 방법에 대해 일반적인 오류를 확인해야 합니다(또는 예외를 발생시키도록 DB 드라이버를 설정해야 합니다).

[2]: PHP 5.6 이상이 필요합니다.또, 간결성 체크의 에러도 몇개 빠뜨렸습니다.

입력:

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

문자열:

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

사전에 입력을 적절히 삭제한다고 가정하면...

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

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

SELECT *
FROM galleries
WHERE id IN ( $matches ) 

데이터 세트에 따라 값을 적절히 견적합니다.

용도:

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

한 a a.for each루프가 동작합니다.

Flavius/AvatarKava의 방법이 더 좋지만, 어느 배열 값에도 쉼표가 포함되어 있지 않은지 확인하십시오.

Flavius Stef의 답변으로, 당신은 그것을 사용할 수 있습니다.intval()을 기하다id값은 과 같습니다.int int 값 음 、 음 음 、 습 are are are are are 。

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

이스케이프 기능이 있는 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);

SQL 주입의 취약성과 빈 상태대처해야 합니다.둘 다 아래와 같이 처리하겠습니다.

배열의 적절한 합니다.intval ★★★★★★★★★★★★★★★★★」floatval ★★★★★★★★★★★★★★★★★」doubleval각 요소에 걸쳐 있습니다.원하는 경우 숫자 값에도 적용할 수 있는 문자열 유형.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);

은 자음음음음음음음음음음음음음음음음 a a a a a 를 사용하여 삭제할 수 .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;

에 예를 ' 수도 있습니다.$galleries = array(); 때문에 는 주의할 가 있습니다.IN ()을 사용하다, 이 경우에도 사용할 수 있습니다.OR대신, 문제는 남습니다. 위의 체크는 '이러다'입니다.count($values)아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 맞다.

마지막 쿼리에 추가합니다.

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

힌트: 모든 행을 숨기는 대신 빈 배열의 경우 모든 레코드(필터링 없음)를 표시하는 경우, 3진수의 잘못된 부분에서 0을 1바꿉니다.

PDO를 사용하지 않는 안전한 방법:

$ids = array_filter(array_unique(array_map('intval', (array)$ids)));

if ($ids) {
    $query = 'SELECT * FROM `galleries` WHERE `id` IN ('.implode(',', $ids).');';
}
  • (array)$ids ★★★★★★★$ids to 열
  • array_map 로 변환합니다.
  • array_unique된 값 삭제( repeated values)
  • array_filter 값 삭제 0 값 remove
  • implode 을 IN 합니다.

더 안전해

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

Col. Shrapnel의 SafeMySQL 라이브러리 for PHP는 파라미터화된 쿼리에 타입 힌트 플레이스 홀더를 제공하며 어레이를 사용하기 위한 몇 가지 편리한 플레이스 홀더를 포함하고 있습니다.?a플레이스 홀더는 이스케이프된 문자열*의 쉼표로 구분된 목록으로 배열을 확장합니다.

예를 들어 다음과 같습니다.

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

* MySQL은 자동 타입 강제를 실행하므로 SafeMySQL이 위의 ID를 문자열로 변환하는 것은 중요하지 않습니다. 그래도 올바른 결과를 얻을 수 있습니다.

입력 배열을 올바르게 필터링하면 이 "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 * FROM galleries WHERE id IN ({$galleryIds})";

수 .texts (T_ID (int), T_TEXT (text)) 테이블 " " "test (id (int), var (varchar(255)))

»insert into test values (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만 사용할 수 있습니다.

더 많은 예:

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

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

원래 질문은 숫자의 배열에 관한 것이고, 저는 문자열의 배열을 사용하고 있기 때문에, 주어진 예제를 사용할 수 없었습니다.

따옴표로 가 있었습니다.IN()★★★★★★ 。

이것이 나의 해결책이다.

foreach($status as $status_a) {
        $status_sql[] = '\''.$status_a.'\'';
    }
    $status = implode(',',$status_sql);

$sql = mysql_query("SELECT * FROM table WHERE id IN ($status)");

처럼 첫 번째 는 각 배열 .single quotes (\')어레이를 파괴합니다.

의:$status에 sql SQL 。

견적을 추가하는 더 좋은 방법이 있을 수 있지만, 이것은 효과가 있습니다.

다음은 다른 데이터에 대해 지정된 자리 표시자와 함께 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);

언급URL : https://stackoverflow.com/questions/907806/passing-an-array-to-a-query-using-a-where-clause

반응형