MySQLi 멀티 명령문

MySQL은 선택적으로 하나의 명령문 문자열에 다중 명령문을 포함할 수 있지만 특별한 처리가 필요합니다.

다중 명령문 또는 다중 쿼리는 mysqli::multi_query()로 실행해야 합니다. 명령문 문자열의 개별 명령문은 세미콜론으로 구분됩니다. 그런 다음 실행된 문에서 반환된 모든 결과 집합을 가져와야 합니다.

MySQL 서버는 하나의 다중 명령문에서 결과 세트를 리턴하는 명령문과 결과 세트를 리턴하지 않는 명령문을 갖는 것을 허용합니다.

예제 #1 다중 명령문

                  
<?php

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("example.com", "user", "password", "database");

$mysqli->query("DROP TABLE IF EXISTS test");
$mysqli->query("CREATE TABLE test(id INT)");

$sql = "SELECT COUNT(*) AS _num FROM test;
        INSERT INTO test(id) VALUES (1);
        SELECT COUNT(*) AS _num FROM test; ";

$mysqli->multi_query($sql);

do {
    if ($result = $mysqli->store_result()) {
        var_dump($result->fetch_all(MYSQLI_ASSOC));
        $result->free();
    }
} while ($mysqli->next_result());
                  
                

위의 예는 다음을 출력합니다.

array(1) {
  [0]=>
  array(1) {
    ["_num"]=>
    string(1) "0"
  }
}
array(1) {
  [0]=>
  array(1) {
    ["_num"]=>
    string(1) "1"
  }
}
                

Security considerations

API 함수 mysqli::query()mysqli::real_query()는 서버에서 다중 쿼리를 활성화하는 데 필요한 연결 플래그를 설정하지 않습니다. 실수로 인한 SQL 주입 공격의 피해를 줄이기 위해 여러 명령문에 추가 API 호출이 사용됩니다. 공격자는 다음과 같은 명령문을 추가하려고 할 수 있습니다. ; DROP DATABASE mysql 또는 ; SELECT SLEEP(999). 공격자가 명령문 문자열에 SQL을 추가하는 데 성공했지만 mysqli::multi_query를 사용하지 않으면 서버는 주입된 악성 SQL 명령문을 실행하지 않습니다.

예제 #2 SQL Injection

                  
<?php
$mysqli = new mysqli("example.com", "user", "password", "database");
$result = $mysqli->query("SELECT 1; DROP TABLE mysql.user");
if (!$result) {
    echo "Error executing query: (" . $mysqli->errno . ") " . $mysqli->error;
}
?>
                  
                

위의 예는 다음을 출력합니다.

Error executing query: (1064) You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version for the right syntax
to use near 'DROP TABLE mysql.user' at line 1
                

Prepared statements

다중 명령문을 준비된 명령문과 함께 사용하는 것은 지원되지 않습니다.

기타