MySQL IN 문에 대한 PDO 바인딩 값
PHPMySQL 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.이것은이 질문에서 질문 한 것과 같습니다 : 배열을 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.이 상황을 처리하는 좋은 방법은 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.이와 같은 상황에서 여러분이 가장 잘 준비 할 수있는 진술은 다음과 유사합니다 :
이와 같은 상황에서 여러분이 가장 잘 준비 할 수있는 진술은 다음과 유사합니다 :
SELECT users.id FROM users JOIN products ON products.user_id = users.id WHERE products IN (?,?,?,?,?,?,?,?)
그런 다음 값을 반복하고 준비된 명령문에 바인드하여 바인딩중인 값과 같은 수의 물음표가 있는지 확인하십시오.
-
==============================
4.$ values 배열에있는 값의 수와 IN의 동일한 수를? 제공해야합니다.
$ values 배열에있는 값의 수와 IN의 동일한 수를? 제공해야합니다.
이 배열은? s 배열을 다음과 같이 쉽게 만들 수 있습니다.
$in = join(',', array_fill(0, count($values), '?'));
IN 절에서이 $ in 배열을 사용하십시오
이것은 동적으로 $ tail 배열에 따라 재단 된 배열을 제공합니다.
-
==============================
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.표현식이 bindValue ()로 값을 바인딩하지 않고 사용자 입력을 기반으로하는 경우, 실험적 SQL이 큰 선택이 아닐 수도 있습니다. 그러나 MySQL의 REGEXP를 사용하여 입력 구문을 검사하여 안전하게 만들 수 있습니다.
표현식이 bindValue ()로 값을 바인딩하지 않고 사용자 입력을 기반으로하는 경우, 실험적 SQL이 큰 선택이 아닐 수도 있습니다. 그러나 MySQL의 REGEXP를 사용하여 입력 구문을 검사하여 안전하게 만들 수 있습니다.
예 :
SELECT * FROM table WHERE id IN (3,156) AND '3,156' REGEXP '^([[:digit:]]+,?)+$'
-
==============================
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.다음과 같이 시도하십시오.
다음과 같이 시도하십시오.
WHERE products IN(REPLACE(:products, '\'', ''))
문안 인사
from https://stackoverflow.com/questions/1586587/pdo-binding-values-for-mysql-in-statement by cc-by-sa and MIT license
'PHP' 카테고리의 다른 글
PHP에서 csrf 방지 (0) | 2018.09.15 |
---|---|
PHP를 사용하여 오디오 스트림에서 트랙 정보 가져 오기 (0) | 2018.09.15 |
그들이 적용되기 전에 정규식 패턴을 벗어날 수있는 PHP 함수가 있습니까? (0) | 2018.09.15 |
각각의`echo` 호출 후에 어떻게 출력을 플러시합니까? (0) | 2018.09.15 |
앰퍼샌드가있는 PHP 함수를 시작한다는 것은 무엇을 의미합니까? (0) | 2018.09.15 |