MySQLi의 확장은 PDO보다 더 기능적이므로 학습 과정에서 MySQLi의 다양하고 흥미로운 방법과 기능을 계속해서 삽입할 것입니다. 하지만 오늘의 주인공은 MySQLi에서 SQL 문을 실행하는 방법과 여러 개의 SQL 문을 실행하는 방법이다.
우선 작은 콘텐츠 학습 공유, 여전히 데이터베이스에 연결되어 있지만 이번에는 다른 연결 방법을 사용합니다.
$mysqli = new mysqli(); $mysqli->real_connect("localhost", "root", "", "blog_test"); var_dump($mysqli); // ["thread_id"]=> // int(163) $mysqli->real_connect("localhost", "root2", "123", "blog_test"); var_dump($mysqli); // ["thread_id"]=> // int(164)
먼저 mysqli 객체를 인스턴스화합니다. 인스턴스화 과정에서 mysqli 생성자에 어떤 매개변수도 전달하지 않고 real_connect() 메소드를 사용하여 데이터베이스 서버 정보를 전달하고 연결을 설정했습니다.
mysqli 인스턴스에서 다른 데이터베이스 연결을 전환하기 위해 real_connect()를 사용하는 코드를 보면 많은 친구들이 알 수 있을 것 같습니다. mysqli 객체의 내용을 출력해 보면 두 연결의 스레드 ID가 서로 다른, 즉 서로 다른 두 연결이지만 상단에 초기화된 mysqli 객체를 사용하고 있음을 알 수 있다.
연결을 전환할 수 있는데 연결하려는 데이터베이스는 어떻게 되나요? 물론 쉽게 전환도 가능합니다.
$mysqli->select_db('mysql');
코드 실행 중에 연결된 데이터베이스를 동적으로 수정하는 데 도움이 되는 간단한 select_db() 메서드입니다.
PDO의 경우 쿼리 문인 경우 query() 메서드를 사용해야 하며, 추가, 삭제, 수정 등의 다른 문인 경우 exec()를 사용해야 합니다. . 이 두 가지 메소드를 통해 각각 다른 SQL 문을 실행합니다. 하지만 MySQLi에서는 query() 메소드만 사용할 수 있습니다.
$mysqli->query("insert into zyblog_test_user(username, password, salt) values('3a', '3a', '3a')"); var_dump($mysqli->affected_rows); var_dump($mysqli->insert_id); $mysqli->query("update zyblog_test_user set password='3aa' where username='3a'"); var_dump($mysqli->affected_rows); $mysqli->query("delete from zyblog_test_user where id = 60"); var_dump($mysqli->affected_rows); $res = $mysqli->query("select * from zyblog_test_user where username='3a'"); print_r($res); // mysqli_result Object // ( // [current_field] => 0 // [field_count] => 4 // [lengths] => // [num_rows] => 3 // [type] => 0 // ) print_r($res->fetch_assoc()); // Array // ( // [id] => 61 // [username] => 3a // [password] => 3aa // [salt] => 3a // ) while ($row = $res->fetch_assoc()) { print_r($row); } // Array // ( // [id] => 62 // [username] => 3a // [password] => 3aa // [salt] => 3a // ) // Array // ( // [id] => 63 // [username] => 3a // [password] => 3aa // [salt] => 3a // ) // ……
추가, 삭제, 수정과 같은 문의 경우 query() 메서드는 부울 값, 즉 문이 성공적으로 실행되었는지 여부만 반환합니다. 영향을 받은 행 수는 반환하지 않는다는 점을 기억하십시오. 영향을 받은 행의 수를 얻으려면 MySQLi 속성에 영향을 받은_rows를 사용해야 합니다. insert 문의 경우 insert_id 속성은 최근에 삽입된 데이터 ID를 얻는 데 사용됩니다.
SELECT 문이 실행되면 query()는 데이터베이스 쿼리에서 얻은 결과 집합을 나타내는 mysqli_result 객체를 반환합니다. 이 개체의 내용에 대해서는 이후 기사에서 자세히 설명하겠습니다.
PDO에서는 다중 SQL 문을 실행하는 기능이 불가능합니다. 하지만 PDO에서는 이를 지원하고 문은 정상적으로 실행될 수 있다고 하지만 완전한 반환 결과를 얻을 수는 없습니다.
$sql = "insert into zyblog_test_user(username, password, salt) values('3bb', '3bb', '3bb');" . "update zyblog_test_user set password='3aa' where username='3a';" . "select * from zyblog_test_user where username='3b';" . "select now()"; $pdo = new PDO("mysql:dns=locahost;dbname=blog_test", 'root', '', [PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION]); $res = $pdo->exec($sql); var_dump($res); // int(1) $stmt = $pdo->query($sql); foreach ($stmt as $row) { //PHP Fatal error: Uncaught PDOException: SQLSTATE[HY000]: General error in var_dump($row); }
코드에서 알 수 있듯이 exec() 메소드를 사용하면 INSERT 문의 결과가 반환됩니다. query() 메소드를 사용하면 PDOStatement 객체가 반환되지만 탐색할 수 없습니다.
다음으로, MySQLi가 여러 개의 명령문으로 구성된 이 SQL 문을 어떻게 실행하는지 살펴보겠습니다.
$mysqli->multi_query($sql); $i = 1; do{ echo '第' . $i . '条:', PHP_EOL; $i++; $result = $mysqli->use_result(); var_dump($result); var_dump($mysqli->affected_rows); if(is_object($result)){ var_dump($result->fetch_assoc()); } var_dump($mysqli->next_result()); echo '========', PHP_EOL; } while($mysqli->more_results() ); // 第1条: // bool(false) // int(1) // ======== // 第2条: // bool(false) // int(0) // ======== // 第3条: // object(mysqli_result)#2 (5) { // ["current_field"]=> // int(0) // ["field_count"]=> // int(4) // ["lengths"]=> // NULL // ["num_rows"]=> // int(0) // ["type"]=> // int(1) // } // int(-1) // array(4) { // ["id"]=> // string(2) "67" // ["username"]=> // string(2) "3b" // ["password"]=> // string(2) "3b" // ["salt"]=> // string(2) "3b" // } // ======== // 第4条: // bool(false) // int(0) // ========
multi_query()는 여러 SQL 문을 실행하기 위해 MySQLi에서 제공하는 메서드입니다. 실행된 후 반환된 결과는 부울 값입니다. 첫 번째 문에 문제가 있으면 FALSE를 반환합니다. 후속 명령문이 잘못된 경우 next_result()를 호출하여 후속 명령문의 오류 정보를 얻어야 합니다.
사실 이는 next_result() 메소드의 역할로도 이어집니다. 이는 다음 결과를 얻기 위한 연산을 준비하는 것과 동일하며, 커서를 다음 SQL 문으로 이동시키는 것으로도 볼 수 있습니다. more_results() 메소드는 실행되지 않은 문장이 더 있는지 확인하는 것입니다.
위 테스트 코드에서는 각 문의 실행 결과를 얻기 위해 use_result() 메서드를 사용했습니다. 그 기능은 결과 세트 검색을 시작하는 것입니다. 즉, mutli_query()가 호출되면 이 명령문이 즉시 실행되지 않고, use_result()가 호출될 때 현재 명령문이 실행됩니다. INSERT 및 UPDATE 문에서 반환된 결과가 FALSE라는 것을 확인했습니다. 그리고 SELECT 문의 num_rows도 0입니다. 이는 결과 세트 정보를 프로그램 메모리에 직접 저장하지 않는 것이 특징입니다. 따라서 use_result() 메소드의 가장 큰 장점은 메모리를 적게 차지하며 많은 수의 쿼리를 순회하는 데 적합하다는 점입니다. 단점은 매번 쿼리하려면 데이터베이스에 가야 하므로 속도가 느리다는 것입니다.
use_result() 외에도 쿼리 결과 집합을 얻는 데 도움이 되는 store_result() 메서드도 있습니다. use_result() 메소드와 반대입니다. 즉, 직접 실행하고 결과 세트를 메모리에 저장합니다.
$mysqli = new mysqli("localhost", "root", "", "blog_test"); $mysqli->multi_query($sql); $i = 1; do{ echo '第' . $i . '条:', PHP_EOL; $i++; $result = $mysqli->store_result(); var_dump($result); var_dump($mysqli->affected_rows); if(is_object($result)){ var_dump($result->fetch_assoc()); } var_dump($mysqli->next_result()); echo '========', PHP_EOL; } while($mysqli->more_results() ); // 第1条: // bool(false) // int(1) // ======== // 第2条: // bool(false) // int(0) // ======== // 第3条: // object(mysqli_result)#1 (5) { // ["current_field"]=> // int(0) // ["field_count"]=> // int(4) // ["lengths"]=> // NULL // ["num_rows"]=> // int(7) // ["type"]=> // int(0) // } // int(7) // array(4) { // ["id"]=> // string(2) "67" // ["username"]=> // string(2) "3b" // ["password"]=> // string(2) "3b" // ["salt"]=> // string(2) "3b" // } // ======== // 第4条: // object(mysqli_result)#3 (5) { // ["current_field"]=> // int(0) // ["field_count"]=> // int(1) // ["lengths"]=> // NULL // ["num_rows"]=> // int(1) // ["type"]=> // int(0) // } // int(1) // array(1) { // ["now()"]=> // string(19) "2020-09-14 10:31:37" // }
쿼리 결과의 num_rows에 데이터가 있을 뿐만 아니라 마지막 SELECT now() 문도 성공적으로 반환됩니다. 이는 우리가 매일 query()를 사용하는 결과와 유사합니다.
또 한 가지 주목해야 할 점은 결과를 얻는 이 두 가지 방법을 실행하기 위한 루프 조건을 작성하는 방법을 살펴볼 수 있다는 것입니다. more_results() 및 next_result()에는 이 두 가지 결과 세트를 얻는 다른 방법이 있습니다. 직접 테스트할 수 있습니다.
光说不练假把式,虽说多语句执行看似很美好,但即使在这简单的测试代码中,也会出现各种问题,大家一定要自己多尝试一下。在日常的开发过程中,最好还是一条一条的语句来执行,避免出现各种无法查明的问题而影响我们正常的业务执行。至于到底要不要使用这个能力,还是大家仁者见仁智者见智了。
测试代码:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202009/source/6.PHP中的MySQLi扩展学习(三)mysqli的基本操作.php
推荐学习:php视频教程
위 내용은 PHP에서 mysqli의 기본 작업은 무엇입니까의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!