[SQL] 여러 번 매개 변수 바인딩 사용하십시오
SQL여러 번 매개 변수 바인딩 사용하십시오
나는 사용자가 다른 종류의 정보를 포함 할 수 내 데이터베이스에 대한 아주 기본적인 검색 엔진을 구현하기 위해 노력하고있어. 검색 자체는 결과가 항상 3 열로 병합 노조 선택의 몇 가지로 구성되어 있습니다.
복귀 된 데이터는 그러나 다른 테이블에서 인출되고있다.
각 쿼리는 중매에 대한 $ 용어를 사용하고, 나는 그것을 구속했습니다 준비된 매개 변수로 "용어".
이제 설명서는 말한다 :
용어의 매개 변수와 함께 : termX (X 임기 = N ++)는 더 나은 솔루션이 있어야 내가 대신 각 교체의 생각?
termX : 아니면 단지의 바인드 X 번호로해야합니까?
이 내 솔루션을 게시 편집 :
$query = "SELECT ... FROM table WHERE name LIKE :term OR number LIKE :term";
$term = "hello world";
$termX = 0;
$query = preg_replace_callback("/\:term/", function ($matches) use (&$termX) { $termX++; return $matches[0] . ($termX - 1); }, $query);
$pdo->prepare($query);
for ($i = 0; $i < $termX; $i++)
$pdo->bindValue(":term$i", "%$term%", PDO::PARAM_STR);
좋아, 여기에 샘플입니다. 나는 sqlfiddle 시간이 없어하지만 필요한 경우 나중에 하나를 추가합니다.
(
SELECT
t1.`name` AS resultText
FROM table1 AS t1
WHERE
t1.parent = :userID
AND
(
t1.`name` LIKE :term
OR
t1.`number` LIKE :term
AND
t1.`status` = :flagStatus
)
)
UNION
(
SELECT
t2.`name` AS resultText
FROM table2 AS t2
WHERE
t2.parent = :userParentID
AND
(
t2.`name` LIKE :term
OR
t2.`ticket` LIKE :term
AND
t1.`state` = :flagTicket
)
)
해결법
-
==============================
1.나는 몇 번 지금 같은 문제가 달려 있고 난 내가 꽤 간단하고 좋은 해결책을 발견했다 생각합니다. 경우 내가 매개 변수를 여러 번 사용하려면, 난 그냥 MySQL의 사용자 정의 변수에 저장합니다. 이 코드가 훨씬 더 쉽게 읽을 당신은 PHP의 추가 기능이 필요하지 않습니다 :
나는 몇 번 지금 같은 문제가 달려 있고 난 내가 꽤 간단하고 좋은 해결책을 발견했다 생각합니다. 경우 내가 매개 변수를 여러 번 사용하려면, 난 그냥 MySQL의 사용자 정의 변수에 저장합니다. 이 코드가 훨씬 더 쉽게 읽을 당신은 PHP의 추가 기능이 필요하지 않습니다 :
$sql = "SET @term = :term"; try { $stmt = $dbh->prepare($sql); $stmt->bindValue(":term", "%$term%", PDO::PARAM_STR); $stmt->execute(); } catch(PDOException $e) { // error handling } $sql = "SELECT ... FROM table WHERE name LIKE @term OR number LIKE @term"; try { $stmt = $dbh->prepare($sql); $stmt->execute(); $stmt->fetchAll(); } catch(PDOException $e) { //error handling }
유일한 단점은 추가로 MySQL의 쿼리를 할 필요가있을 수 있습니다 -하지만 그것은 완전히 가치가 이럴. 사용자 정의 변수는 세션 바인딩의 MySQL에 있기 때문에 다중 사용자 환경에서 부작용을 일으키는 원인이되는 변수 @term 걱정할 필요도 없다.
-
==============================
2.나는 두 번 사용하는 용어의 이름을 변경하여 문제를 해결하기 위해 두 가지 기능을 만들었습니다. 바인딩의 이름을 변경하기위한 SQL 하나의 이름을 변경 한 가지.
나는 두 번 사용하는 용어의 이름을 변경하여 문제를 해결하기 위해 두 가지 기능을 만들었습니다. 바인딩의 이름을 변경하기위한 SQL 하나의 이름을 변경 한 가지.
/** * Changes double bindings to seperate ones appended with numbers in bindings array * example: :term will become :term_1, :term_2, .. when used multiple times. * * @param string $pstrSql * @param array $paBindings * @return array */ private function prepareParamtersForMultipleBindings($pstrSql, array $paBindings = array()) { foreach($paBindings as $lstrBinding => $lmValue) { // $lnTermCount= substr_count($pstrSql, ':'.$lstrBinding); preg_match_all("/:".$lstrBinding."\b/", $pstrSql, $laMatches); $lnTermCount= (isset($laMatches[0])) ? count($laMatches[0]) : 0; if($lnTermCount > 1) { for($lnIndex = 1; $lnIndex <= $lnTermCount; $lnIndex++) { $paBindings[$lstrBinding.'_'.$lnIndex] = $lmValue; } unset($paBindings[$lstrBinding]); } } return $paBindings; } /** * Changes double bindings to seperate ones appended with numbers in SQL string * example: :term will become :term_1, :term_2, .. when used multiple times. * * @param string $pstrSql * @param array $paBindings * @return string */ private function prepareSqlForMultipleBindings($pstrSql, array $paBindings = array()) { foreach($paBindings as $lstrBinding => $lmValue) { // $lnTermCount= substr_count($pstrSql, ':'.$lstrBinding); preg_match_all("/:".$lstrBinding."\b/", $pstrSql, $laMatches); $lnTermCount= (isset($laMatches[0])) ? count($laMatches[0]) : 0; if($lnTermCount > 1) { $lnCount= 0; $pstrSql= preg_replace_callback('(:'.$lstrBinding.'\b)', function($paMatches) use (&$lnCount) { $lnCount++; return sprintf("%s_%d", $paMatches[0], $lnCount); } , $pstrSql, $lnLimit = -1, $lnCount); } } return $pstrSql; }
사용 예 :
$lstrSqlQuery= $this->prepareSqlForMultipleBindings($pstrSqlQuery, $paParameters); $laParameters= $this->prepareParamtersForMultipleBindings($pstrSqlQuery, $paParameters); $this->prepare($lstrSqlQuery)->execute($laParameters);
변수 이름에 대한 설명 : P : 파라미터, L : 기능 현지 STR : 문자열 이하, N : 숫자, A : 배열 m : 혼합
-
==============================
3.나는 그것이 변경된 경우 문제가 게시 된 이후 알지만, 지금은 설명서를 확인하지 않습니다, 그것은 말합니다 :
나는 그것이 변경된 경우 문제가 게시 된 이후 알지만, 지금은 설명서를 확인하지 않습니다, 그것은 말합니다 :
http://php.net/manual/en/pdo.prepare.php - (강조 광산.)
그래서, 기술적으로, 에뮬레이션 허용 $ PDO_obj->의 setAttribute (사실 PDO :: ATTR_EMULATE_PREPARES)를 사용하여 준비; 너무 작동합니다; 에뮬레이트 준비된 문 끄기이 답변에서 설명한대로 (좋은 생각되지 않을 수 있지만 특정 주입 공격으로부터 보호하기위한 한 가지 방법은, 일부는 반대로 쓴 비록 에뮬레이트되지 않았거나 준비합니다 여부를 보안에 아무런 차이가 없다 . (나도 몰라,하지만 난 후자를 염두에 전 언급 한 공격을 한 것으로 생각하지 않습니다.)
나는 완전성을 위해서이 답변을 추가 해요; 나는이 사이트에 내가 일하고 있어요 오프 emulate_prepares을 설정하고, 비슷한 쿼리 (SELECT를 사용했다대로 TBL FROM ..., 휴식을 검색 원인으로 WHERE (필드 1 LIKE : 용어 또는 필드 2 LIKE : 용어) ... ), 내가 명시 적으로 false로 PDO :: ATTR_EMULATE_PREPARES을 설정할 때까지하고, 잘 작동했다, 그것은 실패 시작했다.
(PHP 5.4.38, MySQL은 5.1.73 FWIW)
이 질문은 당신이 (오 잘 나에게 반 직관적 보인다,하지만) 동일한 쿼리에 두 번 명명 된 매개 변수를 사용할 수 없습니다 저를 밀고 것입니다. (I 해당 페이지 여러 번 보았다하지만 어떻게 든 나는 매뉴얼도에 그것을 놓쳤다.)
-
==============================
4.실제로 동작하는 솔루션 :
실제로 동작하는 솔루션 :
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, TRUE); $query = "SELECT * FROM table WHERE name LIKE :term OR number LIKE :term"; $term = "hello world"; $stmt = $pdo->prepare($query); $stmt->execute(array('term' => "%$term%")); $data = $stmt->fetchAll();
-
==============================
5.사용자 정의 변수를 이동하고 쿼리에 값을 바인딩에 동일한 변수를 여러 번 사용하고 그래 그게 잘 작동하는 그것의 한 방법입니다.
사용자 정의 변수를 이동하고 쿼리에 값을 바인딩에 동일한 변수를 여러 번 사용하고 그래 그게 잘 작동하는 그것의 한 방법입니다.
//Setting this doesn't work at all, I tested it myself $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, TRUE);
나는 솔루션 중 하나가 여기에 게시처럼 모두에서 사용자 정의 변수를 사용하고 싶어하지 않았다. 나는 다른 솔루션은 여기에 게시처럼 PARAM 이름 변경을 할 수도 싶어하지 않았다. 그래서 여기 내 솔루션은 사용자 정의 변수를 사용하지 않고 적은 코드를 사용하여 쿼리에 어떤 이름을 변경하지 않고 작품과는 PARAM이 쿼리에 사용되는 횟수에 대해 걱정하지 않습니다이다. 내 모든 프로젝트에이를 사용하고있어 잘 작동합니다.
//Example values var $query = "select * from test_table where param_name_1 = :parameter and param_name_2 = :parameter"; var param_name = ":parameter"; var param_value = "value"; //Wrap these lines of codes in a function as needed sending 3 params $query, $param_name and $param_value. //You can also use an array as I do! //Lets check if the param is defined in the query if (strpos($query, $param_name) !== false) { //Get the number of times the param appears in the query $ocurrences = substr_count($query, $param_name); //Loop the number of times the param is defined and bind the param value as many times needed for ($i = 0; $i < $ocurrences; $i++) { //Let's bind the value to the param $statement->bindValue($param_name, $param_value); } }
그리고 여기에 간단한 작업 솔루션입니다!
이 가까운 미래에 누군가가 도움이되기를 바랍니다.
from https://stackoverflow.com/questions/18511645/use-bound-parameter-multiple-times by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] 오류 만들 테이블 : 당신은 근처의 SQL 구문에 오류가있다 '(순서를 ORDER_ID INT UNSIGNED NOT NULL AUTO_INCREMENT, USER_ID'라인 1에 [중복] (0) | 2020.03.26 |
---|---|
[SQL] DBMS의 자성 무엇입니까 (0) | 2020.03.26 |
[SQL] IS NULL = NULL과의 차이가 있습니까 (0) | 2020.03.26 |
[SQL] GROUP BY / SQL의 집계 함수 혼란 (0) | 2020.03.26 |
[SQL] MySQL의 : 절 제한의 FROM에서 하위 쿼리와보기 (0) | 2020.03.26 |