Làm cách nào tôi có thể chạy nhiều truy vấn trong sql cùng một lúc trong php?

Trong PHP 4, khi bạn cần thực hiện nhiều truy vấn liên tiếp, bạn buộc phải gọi mysql_query() một lần cho mỗi truy vấn. Điều này thường xảy ra khi bạn cần các mẩu thông tin riêng biệt từ MySQL hoặc khi bạn muốn tạo một bộ bảng mới

Đây không phải là vấn đề lớn khi bạn biết trước các truy vấn của mình, bởi vì thật dễ dàng để lặp lại và gửi chúng đến MySQL một lần. Tuy nhiên, đối với một số tình huống, đây không phải là trường hợp. Ví dụ: bạn đang viết giao diện người dùng PHP cho MySQL, chẳng hạn như phpMyAdmin (http. //www. phpmyadmin. net) và muốn có khả năng kết xuất cơ sở dữ liệu và tạo lại thông tin

Không có khả năng gửi toàn bộ kết xuất cùng một lúc, bạn bắt buộc phải phân tích dữ liệu thành các câu lệnh riêng lẻ. Điều đó nghe có vẻ không dễ dàng chút nào, bởi vì bạn không thể chỉ chia nhỏ trên dấu chấm phẩy (;). Ví dụ: hoàn toàn hợp lệ khi có một dòng như INSERT INTO users VALUES('rasmus', 'pass;word');. Vì pass;word nằm trong dấu ngoặc đơn, MySQL biết nó không báo hiệu kết thúc câu lệnh, nhưng một sự phân tách đơn giản không đủ thông minh để hiểu điều này. Kết quả là, bạn thực sự buộc phải viết một trình phân tích cú pháp MySQL trong PHP

Việc hạn chế một truy vấn cho mỗi yêu cầu được dỡ bỏ trong MySQLi. Đây thực sự không phải là một hạn chế trong PHP, mà là sự thiếu sót trong giao thức được sử dụng bởi các phiên bản MySQL trước đó. Một lợi ích khác của MySQL 4. Giao thức được cập nhật của 1 là khả năng giới thiệu hàm mysqli_multi_query( ) cho các loại trường hợp này

Mặc dù đây là một tin tốt, nhưng nó cũng tạo ra một tiềm năng lớn hơn cho các cuộc tấn công SQL injection. Một cuộc tấn công SQL injection là khi một kẻ độc hại chuyển dữ liệu làm thay đổi SQL của bạn để cuối cùng bạn đưa ra một truy vấn SQL khác (và có thể nguy hiểm hơn) so với những gì bạn mong đợi

Đây là một ví dụ được cho là trả lại thông tin tài khoản ngân hàng cho chỉ một người dùng

$sql = "SELECT account_number, balance FROM bank_accounts 

        WHERE secret_code LIKE '$_GET[secret_code]'";

Bạn biết rằng điều quan trọng là sử dụng mã bí mật để mọi người không thể truy cập thông tin của người khác bằng cách tăng số ID khóa chính vì những số đó rất dễ đoán. Tuy nhiên, bạn đã quên gọi mysql_real_escape_string( ) trên $_GET['secret_code'], và đây là sự cố. Một kẻ bẻ khóa có thể đặt secret_code thành ' OR '1' LIKE '1 và điều đó biến truy vấn của bạn thành

SELECT account_number, balance FROM bank_accounts 

 WHERE secret_code LIKE '' OR '1' LIKE '1';

Vì bất kỳ chuỗi nào luôn khớp với chính nó, điều này sẽ thay đổi truy vấn một cách hiệu quả để trả về tất cả các hàng. Nếu có bất kỳ điểm tích cực nào đối với cách khai thác này, thì đó là vì MySQL chỉ cho phép bạn thực hiện một truy vấn duy nhất tại một thời điểm, nên bạn không thể thay đổi hoàn toàn truy vấn

Tuy nhiên, bây giờ bạn có thể đưa ra nhiều truy vấn, bạn dễ bị tổn thương bởi điều gì đó thậm chí còn tồi tệ hơn. Mọi người có thể đưa ra bất kỳ truy vấn nào họ muốn

SELECT account_number, balance FROM bank_accounts 

 WHERE secret_code LIKE '';

UPDATE bank_accounts 

   SET balance = 1000000

 WHERE account_number = '12345678';

Bằng cách thay đổi secret_code thành '; . Truy vấn thứ hai không bị giới hạn bởi các ràng buộc của truy vấn đầu tiên, do đó, một truy vấn được cho là CHỌN dữ liệu giờ đây cũng CẬP NHẬT nó (hoặc dữ liệu trong bất kỳ bảng nào khác)

Để ngăn chặn lỗ hổng bảo mật này, mysqli buộc vô hiệu hóa khả năng thực hiện nhiều truy vấn của mysqli_query( ). Thay vào đó, có một bộ chức năng thay thế để bạn sử dụng

3. 8. 1 mysql. Thực hiện nhiều truy vấn

Trong mysql, cách tốt nhất để xử lý nhiều truy vấn là đặt chúng trong các phần tử mảng riêng lẻ. Sau đó, bạn có thể lặp qua mảng và đưa ra các truy vấn

Ví dụ 3-9 tạo một bảng người dùng và điền vào đó các tài khoản rasmus và zeev

Ví dụ 3-9. Thực hiện nhiều truy vấn với mysql_query( )
$queries = array(

    "DROP TABLE IF EXISTS users;",

    "CREATE TABLE users(username VARCHAR(50) UNIQUE,

                        password VARCHAR(50));",

    "INSERT INTO users VALUES('rasmus', 'z.8cMpdFbNAPw'), 

                             ('zeev',   'asd34.23NNDeq');",

    "SELECT * FROM users WHERE username LIKE 'rasmus';");

    

foreach ($queries as $query) {

    if ($result = mysql_query($query, $db) and $result !=  = true) {

        while ($row = mysql_fetch_row($result)) {

            print "$row[0]\n";

         }

    }

}

Điều quan trọng là phải trích dẫn đúng các câu lệnh SQL vì chúng thường có dấu ngoặc kép đơn và kép được nhúng. Trong trường hợp này, cả hai câu lệnh INSERT và SELECT đều có dấu nháy đơn

foreach lặp qua từng phần tử và gọi mysql_query(). Nếu mọi thứ đều ổn, hàm trả về giá trị thực. Khi có các hàng cần xử lý, chẳng hạn như trong truy vấn CHỌN hoặc MÔ TẢ, mysql_query( ) trả về một tài nguyên. Khi yêu cầu thành công nhưng không có thông tin bổ sung, nó chỉ trả về true

Điều này cho phép bạn phân biệt giữa các truy vấn mà bạn có thể gọi mysql_fetch_row( ) bằng cách đặt và $result. = = true bên trong điều kiện. Bạn phải sử dụng cả hai và thay vì && và. = = thay vì. =;

Cuối cùng, vòng lặp while truy xuất từng hàng và in ra cột đầu tiên. Vì chỉ một trong bốn câu lệnh được thực hiện trong ví dụ này trả về kết quả và nó chỉ trả về một hàng duy nhất, nên toàn bộ đầu ra của vòng lặp này là rasmus

Tất nhiên, như đã nói trước đó, không có điều nào trong số này là cần thiết nếu SQL của bạn không được tách thành các câu lệnh riêng lẻ

3. 8. 2 mysqli. Thực hiện nhiều truy vấn

Tiện ích mở rộng mysqli giải quyết nhiều vấn đề phát sinh khi thực hiện nhiều truy vấn. Quan trọng nhất, bạn không cần phải chia nhỏ SQL. Điều này không chỉ loại bỏ nhu cầu về trình phân tích cú pháp MySQL mà còn cho phép bạn dễ dàng đặt SQL bên trong tập lệnh của mình hơn mà không phải lo lắng về dấu ngoặc kép

Tuy nhiên, nhược điểm là mã xử lý yêu cầu phức tạp hơn nhiều. Thay vì một chức năng duy nhất, mysql_query(), bốn chức năng khác nhau là cần thiết để điều hướng qua các kết quả

Sử dụng mysqli_multi_query( ) để tự gửi truy vấn và mysqli_store_result( ) để tải kết quả của từng truy vấn liên tiếp vào vị trí có thể tìm nạp chúng. Khi bạn thực hiện xong một truy vấn, hãy giải phóng nó bằng mysqli_free_result( ) và chuyển sang truy vấn tiếp theo bằng mysqli_next_result( )

Ví dụ 3-10 là phiên bản sửa đổi của Ví dụ 3-9 cho thấy cách các chức năng này hoạt động kết hợp

Ví dụ 3-10. Thực hiện nhiều truy vấn với mysqli_multi_query( )
$query = <<<_SQL_

DROP TABLE IF EXISTS users;

CREATE TABLE users(username VARCHAR(50),

                   password VARCHAR(50));

INSERT INTO users VALUES('rasmus', 'z.8cMpdFbNAPw'), 

                        ('zeev',   'asd34.23NNDeq');

SELECT * FROM users WHERE username LIKE 'rasmus';

_SQL_;



if (mysqli_multi_query($db, $query)) {

    do {

        if ($result = mysqli_store_result($db)) {

            while ($row = mysqli_fetch_row($result)) {

                print "$row[0]\n";

            }

            mysqli_free_result($result);

        }

    } while (mysqli_next_result($db));

}

SQL của bạn không còn được lưu trữ trong một mảng mà dưới dạng một chuỗi. Điều này cho phép bạn sử dụng heredoc để tránh vấn đề về dấu ngoặc đơn và dấu ngoặc kép

Hàm mysqli_multi_query() nhận một liên kết cơ sở dữ liệu và một truy vấn, giống như hàm mysqli_query(). Nếu có bất cứ điều gì sai, chẳng hạn như lỗi phân tích cú pháp, nó sẽ trả về false;

Vì mysqli_multi_query( ) đã xử lý kết quả đầu tiên, hãy sử dụng vòng lặp do/while thay vì vòng lặp while để lặp lại tất cả dữ liệu. Mặt khác, cuộc gọi đầu tiên tới mysqli_next_result( ) sẽ thực sự tải kết quả thứ hai

Trong vòng lặp, gọi mysqli_store_result( ) để chuyển từng tập kết quả sang PHP. Nếu truy vấn không trả về bất kỳ hàng nào, thì mysqli_store_result( ) sẽ trả về false. Điều này thực sự xảy ra đối với ba truy vấn đầu tiên trong ví dụ này? DROP, CREATE và INSERT. Chỉ câu lệnh SELECT gây ra phản hồi không sai

Hành vi này khác với mysql_query( ) và thực sự hữu ích hơn vì nó cho phép bạn loại bỏ và $result. = = kiểm tra đúng từ mã

Giờ đây, bạn có thể sử dụng bộ chức năng truy xuất tiêu chuẩn, chẳng hạn như mysqli_fetch_row(), để xử lý dữ liệu. Ví dụ này chỉ in ra cột đầu tiên từ mỗi hàng được truy xuất

Đảm bảo gọi mysqli_free_result( ) để giải phóng bộ nhớ khi bạn hoàn thành kết quả. Nếu không, nó sẽ chồng chất cho đến khi tập lệnh chạy xong. Vì thật dễ dàng để thực hiện nhiều truy vấn bằng cách sử dụng mysqli_multi_query( ), nên thật dễ dàng để nhanh chóng sử dụng nhiều RAM

Để kiểm tra xem có kết quả bổ sung nào mà không tăng bộ đếm hay không bằng cách gọi mysqli_next_result(), hãy gọi mysqli_more_results()

if (mysqli_multi_query($db, $query)) {

    do {

        if ($result = mysqli_store_result($db)) {

            while ($row = mysqli_fetch_row($result)) {

                print "$row[0]\n";

            }

            mysqli_free_result($result);



            // Add divider after all results except the last

            if (mysqli_more_results($db)) {

                print str_repeat('-', 10) . "\n";

            }

        }



    } while (mysqli_next_result($db));

}

Hàm mysqli_more_results( ) trả về cùng một giá trị như lần gọi tiếp theo tới mysqli_next_result( ). Điều này cho phép bạn thêm các dấu phân cách hoặc thực hiện một số loại xử lý khác sau tất cả các kết quả của câu lệnh ngoại trừ câu lệnh cuối cùng

Nếu bạn cảm thấy khó chịu bởi sự phức tạp của mã này, thì có một giải pháp thay thế kết hợp lợi ích của nhiều truy vấn với sự đơn giản của cú pháp trước đó. Phần 6. 3 chứa một trình lặp đa truy vấn MySQL gói gọn tất cả logic vào một lớp có thể tái sử dụng và cho phép bạn tìm hiểu về các kết quả

Bạn có thể chạy nhiều truy vấn SQL cùng một lúc không?

Bạn có thể đưa nhiều câu lệnh SQL vào bảng truy vấn SQL . Các ngoại lệ là câu lệnh CALL và CREATE PROCEDURE.

Làm cách nào để kết hợp hai truy vấn SQL trong một kết quả trong PHP?

$stmt = $db->prepare("CHỌN col1, col2, col3 từ bảng1");

Làm cách nào để viết hai truy vấn trong PHP?

Hàm multi_query() / mysqli_multi_query() thực hiện một hoặc nhiều truy vấn đối với cơ sở dữ liệu. Các truy vấn được phân tách bằng dấu chấm phẩy.

Làm cách nào để chạy nhiều SQL trong MySQL?

MySQL cũng hỗ trợ thực thi một chuỗi chứa nhiều câu lệnh được phân tách bằng ký tự dấu chấm phẩy ( ; ). Khả năng này được kích hoạt bởi các tùy chọn đặc biệt được chỉ định khi bạn kết nối với máy chủ bằng mysql_real_connect() hoặc sau khi kết nối bằng cách gọi mysql_set_server_option() .