2009-11-23 2 views
113

PHP에서 매개 변수화 된 쿼리로 PDO로 MySQL 데이터베이스에 액세스 할 때 (모든 토큰을 대체 한 후) 최종 쿼리를 어떻게 확인할 수 있습니까?PDO가있는 PHP에서 최종 SQL 매개 변수 쿼리를 확인하는 방법은 무엇입니까?

데이터베이스에서 실제로 무엇이 실행되는지 확인할 수있는 방법이 있습니까?

+2

가. 한동안 나를 괴롭 히고있었습니다. –

+1

PHP> = 5.1 인 경우, http://www.php.net/manual/en/pdostatement.debugdumpparams.php를 보시기 바랍니다. – Mawg

+1

'debugDumpParams()'에 버그가 있습니다 - 출력에는 값이 포함되어 있지 않습니다.mysql에 의해 실행 된 질의를 (쉽게) 검사하는 유일한 방법은 my.cnf (h/t to @JB Hurteaux)의 로그를 잠시 활성화하는 것입니다. –

답변

49

그래서 나는 기록을위한 완전한 해결책을 갖기 위해 마침내 내 질문에 대답 할 것이라고 생각합니다. 그러나 이것에 대한 단서를 제공 한 Ben James와 Kailash Badu에게 감사해야합니다. 벤 제임스에 의해 언급 한 바와 같이

짧은 대답
: NO.
쿼리와 토큰 및 매개 변수가 데이터베이스에 개별적으로 전송되기 때문에 전체 SQL 쿼리가 PHP쪽에 존재하지 않습니다. 데이터베이스 측에서만 전체 쿼리가 존재합니다.

PHP 측에서 토큰을 대체하는 함수를 만들려고해도 SQL 프로세스와 동일한 것으로 보장 할 수 없습니다 (토큰 유형, bindValue와 bindParam과 같은 까다로운 항목 ...)내가 KAILASH 바두의 대답에 정교한 곳)

해결
이다. 모든 SQL 쿼리를 로깅하여 실제로 서버에서 실행되는 것을 볼 수 있습니다. MySQL과 이는 my.cnf 파일을 업데이트하여 수행 할 수 있습니다 (또는 WAMP 서버 내 경우의 my.ini)과 같은 줄을 추가 :

log=[REPLACE_BY_PATH]/[REPLACE_BY_FILE_NAME] 

그냥 생산이 실행되지 않습니다! !

+1

'my.cnf'의 변경 사항에 대해 mysql을 다시 시작하십시오. 효력이 발생합니다. 쿼리를 실행 한 후에는 로그 라인을 주석 처리하고, 다시 mysql을 다시 시작하여 로깅을 중지하십시오. –

0

나는 누군가는 저를 틀리게 증명할 것이라는 점을 희망하지만, 나는 할 수 있다고 믿지 않습니다.

나는 당신이 질의를 인쇄 할 수 있고 그것의 toString 메서드가 당신에게 교체없이 SQL을 보여줄 것이라는 것을 알고있다. 복잡한 쿼리 문자열을 작성하는 경우 유용 할 수 있지만 전체 쿼리에 값을 제공하지는 않습니다.

26

매개 변수화 된 값으로 준비된 문을 사용하는 것은 단순히 SQL 문자열을 동적으로 만드는 또 다른 방법이 아닙니다. 준비된 문을 데이터베이스에서 작성한 다음 매개 변수 값 만 보냅니다.

아마도 데이터베이스에 전송되는 내용은 PREPARE ...이고,이어서 SET ...이며 마지막으로는 EXECUTE ...이됩니다.

같은 쿼리가 실제 데이터베이스에 전송되지 않았기 때문에 SELECT * FROM ...과 같은 일부 SQL 문자열을 얻을 수 없습니다.

+1

지금 받아 들여야합니다. 디버깅에는 그다지 편리하지 않습니다. –

+2

실제로 실행 된 SQL 문 "스트림"을 볼 수있는 방법이 있습니까? 어쩌면 여전히 도움이 될 수 있습니다. –

+0

'$ stmt-> debugDumpParams();'가 가까이 와야합니다. –

1

나는 실제 쿼리가 조금 복잡 있음을 인쇄했지만 내 문에 변수를 할당하는 방법 :

를 작동 내가이 같은 비트 보이는 다른 변수가 있습니다

$this->fullStmt = str_replace($column, '\'' . str_replace('\'', '\\\'', $param) . '\'', $this->fullStmt); 

:
$column이는
$param
$this->fullStmt 내 인쇄 대체 토큰 만 문이다 토큰에 할당되는 실제 값 토큰 내

실제 PDO 할당이 발생하면 단순히 토큰을 값으로 대체하십시오.

나는 당신을 혼란스럽게하지 않았고 적어도 올바른 방향으로 당신을 지적했으면합니다.

+0

네, 고마워요. 벤 제임스 (Ben James)의 답변을 본 후 토큰을 수동으로 교체하는 사용자 지정 함수에 대해서도 설명합니다. 여러 토큰이있을 때 편리하지는 않지만 생성 된 모든 바인딩에 액세스 할 수있는 경우이를 자동화하고 일반 함수를 만드는 방법이있을 수 있습니다. 반면에 내가 원하는 것은 실행 전에 생성 된 쿼리입니다. 내 자신의 함수를 생성한다고해도 같은 결과를 얻을 수 있다고 보장 할 수는 없습니다 (예 : String 매개 변수에 대한 인용 부호를 고려하여 ...) –

9

나는 준비 문으로 실행 된 정확한 쿼리를 보려면 쿼리 로그를 확인하십시오.

17

PDOStatement->debugDumpParams을 사용할 수 있습니다. the PHP documentation을 참조하십시오.

+3

좋은 답변이지만 param 값을 표시하려면 [패치가 필요할 수도 있습니다] (http://stackoverflow.com/a/3656529/819417). –

+0

+1 이것은 대답으로 받아 들여 졌을 것입니다. PHP를 통해 여러 디버그 트레이스와 SQL을 혼합 할 수 있습니다. – Mawg

4

처음에는 번거롭지 만 전혀 힘들지 않다고 생각하여 PDO를 모니터링하기 위해 로깅을 켜는 것을 피했습니다. 당신은 (5.1.9 이후)의 MySQL을 다시 부팅 할 필요가 없습니다 :

당신이 높은 데시벨 권한이있을 수 있습니다 phpMyAdmin을이 SQL 또는 기타 환경 실행 : 터미널에서

SET GLOBAL general_log = 'ON'; 

을, 꼬리 로그를 파일. 광산은 여기에 있었다 :

>sudo tail -f /usr/local/mysql/data/myMacComputerName.log 
당신이 터미널 명령으로 MySQL의 파일을 검색 할 수 있습니다

: 나는 당신이 쓸 수 있도록 PDO는 모든 탈출 발견

>ps auxww|grep [m]ysqld 

$dynamicField = 'userName'; 
$sql = "SELECT * FROM `example` WHERE `:field` = :value"; 
$this->statement = $this->db->prepare($sql); 
$this->statement->bindValue(':field', $dynamicField); 
$this->statement->bindValue(':value', 'mick'); 
$this->statement->execute(); 

그것이 생성하기 때문에 :

SELECT * FROM `example` WHERE `'userName'` = 'mick' ; 

오류를 생성하지 않은 빈 결과.

SET GLOBAL general_log = 'OFF'; 

그렇지 않으면 당신의 로그가 큰 얻을 것이다 대신 당신이 완료되면 실행

SELECT * FROM `example` WHERE `userName` = 'mick' ; 

를 얻을 수

$sql = "SELECT * FROM `example` WHERE `$dynamicField` = :value"; 

를 사용하는 데 필요한.

+2

그래서 SQL 인젝션에 쿼리를 열었습니다. congrats : –

+4

사실, 우선 pdo는이 방식으로 동적 컬럼을 설정할 방법이 없습니다. 이것이 최선의 방법입니다. 둘째, 동적으로 필드를 설정하는 방법은 :'dynamicField = 'userName ''은 주사를위한 여유 공간을 남기지 않습니다. whitelist에 대해 열 이름의 유효성을 검사하는 한이 SQL 작성 방법을 주입 할 수 없습니다. – Louis

-1

나는 pdo를 사용할 때 최종 쿼리 텍스트를 보는 가장 쉬운 방법은 특별한 오류를 만들고 오류 메시지를 보는 것이라고 생각합니다. 어떻게 해야할지 모르겠지만 yii 프레임 워크에서 pdo를 사용하여 sql 오류가 발생하면 쿼리 텍스트를 볼 수 있습니다.