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 값 removeimplode
을 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
'programing' 카테고리의 다른 글
투고 요청의 크기 제한은 얼마입니까? (0) | 2022.11.08 |
---|---|
JavaScript를 사용하여 새 페이지를 로드하지 않고 브라우저에서 URL 변경 (0) | 2022.11.08 |
팬더 데이터를 기존 CSV 파일에 추가하려면 어떻게 해야 합니까? (0) | 2022.10.30 |
var 키워드의 목적과 사용(또는 생략)은 무엇입니까? (0) | 2022.10.30 |
Apache Tomcat 응용 프로그램의 기본 세션 시간 초과 (0) | 2022.10.30 |