Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Làm cách nào để bạn quản lý các truy vấn SQL

Quá trình hành động tốt nhất cho bạn sẽ phụ thuộc vào cách bạn tiếp cận quyền truy cập dữ liệu của mình. Có ba cách tiếp cận bạn có thể thực hiện:

  • Sử dụng các thủ tục đã lưu trữ
  • Giữ các truy vấn trong mã (nhưng đặt tất cả các truy vấn của bạn vào các hàm và sửa mọi thứ để sử dụng PDO cho các tham số, như đã đề cập trước đó)
  • Sử dụng công cụ ORM

Nếu bạn muốn chuyển SQL thô của riêng mình vào công cụ cơ sở dữ liệu thì các thủ tục được lưu trữ sẽ là cách để thực hiện nếu tất cả những gì bạn muốn làm là lấy SQL thô ra khỏi mã PHP của bạn nhưng giữ nó tương đối không thay đổi. Cuộc tranh luận về các thủ tục được lưu trữ và SQL thô là một cuộc thánh chiến, nhưng K. Scott Allen đã đưa ra một điểm tuyệt vời - mặc dù là một điều đáng tiếc - trong một bài báo về chuyển đổi cơ sở dữ liệu :

Tôi có xu hướng nghiêng về việc không sử dụng các thủ tục được lưu trữ. Tôi đã làm việc trên các dự án trong đó DB có API được hiển thị thông qua các thủ tục được lưu trữ, nhưng các thủ tục được lưu trữ có thể đặt ra một số hạn chế của riêng chúng và các dự án đó có tất cả , ở các mức độ khác nhau, đã sử dụng SQL thô được tạo động trong mã để truy cập vào DB.

Có một lớp API trên DB giúp phân định rõ hơn trách nhiệm giữa nhóm DB và nhóm Dev với chi phí là một số tính linh hoạt mà bạn có nếu truy vấn được giữ trong mã, tuy nhiên, các dự án PHP ít có khả năng đủ nhóm để hưởng lợi từ sự phân định này.

Về mặt khái niệm, có lẽ bạn nên có phiên bản cơ sở dữ liệu của mình. Tuy nhiên, thực tế mà nói, bạn có nhiều khả năng mã của mình được tạo phiên bản hơn nhiều so với việc bạn đã tạo phiên bản cho cơ sở dữ liệu của mình. Bạn có thể sẽ thay đổi các truy vấn của mình khi bạn thực hiện các thay đổi đối với mã của mình, nhưng nếu bạn đang thay đổi các truy vấn trong các thủ tục được lưu trữ được lưu trong cơ sở dữ liệu thì có thể bạn sẽ không kiểm tra những truy vấn đó khi bạn kiểm tra mã và bạn bị mất nhiều lợi ích của việc tạo phiên bản cho một khu vực quan trọng trong ứng dụng của bạn.

Bất kể bạn có chọn không sử dụng các thủ tục được lưu trữ hay không, ít nhất bạn nên đảm bảo rằng mỗi hoạt động cơ sở dữ liệu được lưu trữ trong một chức năng độc lập thay vì được nhúng vào mỗi tập lệnh của trang của bạn - về cơ bản là một lớp API cho DB của bạn. được duy trì và tạo phiên bản với mã của bạn. Nếu bạn đang sử dụng các thủ tục được lưu trữ, điều này thực sự có nghĩa là bạn có hai lớp API cho DB của mình, một lớp có mã và một lớp với DB, điều này bạn có thể cảm thấy phức tạp một cách không cần thiết nếu dự án của bạn không có các nhóm riêng biệt. Tôi chắc chắn làm vậy.

Nếu vấn đề là do sự gọn gàng của mã, có nhiều cách để làm cho mã có SQL bị kẹt trong nó dễ trình bày hơn và lớp UserManager được hiển thị bên dưới là một cách tốt để bắt đầu - lớp chỉ chứa các truy vấn liên quan đến bảng 'người dùng', mỗi truy vấn có phương thức riêng trong lớp và các truy vấn được thụt vào trong các câu lệnh chuẩn bị và được định dạng như bạn định dạng chúng trong một thủ tục được lưu trữ.

// UserManager.php:

class UserManager
{
    function getUsers()
    {
        $pdo = new PDO(...);
        $stmt = $pdo->prepare('
            SELECT       u.userId as id,
                         u.userName,
                         g.groupId,
                         g.groupName
            FROM         user u
            INNER JOIN   group g
            ON           u.groupId = g.groupId
            ORDER BY     u.userName, g.groupName
        ');
        // iterate over result and prepare return value
    }

    function getUser($id) {
        // db code here
    }
}

// index.php:
require_once("UserManager.php");
$um = new UserManager;
$users = $um->getUsers();
foreach ($users as $user) echo $user['name'];

Tuy nhiên, nếu các truy vấn của bạn khá giống nhau nhưng bạn có số lượng lớn các hoán vị trong các điều kiện truy vấn của mình như phân trang, sắp xếp, lọc phức tạp, v.v., công cụ ánh xạ đối tượng / quan hệ có thể là cách tốt nhất, mặc dù quá trình đại tu mã hiện tại của bạn để sử dụng công cụ có thể khá phức tạp.

Nếu bạn quyết định điều tra các công cụ ORM, bạn nên xem xét Propel , thành phần ActiveRecord của Yii hoặc PHP ORM của vua cha, Doctrine . Mỗi thứ trong số này cung cấp cho bạn khả năng lập trình xây dựng các truy vấn đến cơ sở dữ liệu của bạn với tất cả các cách logic phức tạp. Doctrine là tính năng đầy đủ nhất, cho phép bạn tạo mẫu cơ sở dữ liệu của mình với những thứ như Tập hợp lồng nhau mô hình cây ra khỏi hộp.

Về mặt hiệu suất, các thủ tục được lưu trữ là nhanh nhất, nhưng nhìn chung không bằng sql thô. Các công cụ ORM có thể có tác động đáng kể đến hiệu suất theo một số cách - truy vấn không hiệu quả hoặc dư thừa, IO tệp lớn trong khi tải thư viện ORM trên mỗi yêu cầu, tạo SQL động trên mỗi truy vấn ... tất cả những điều này đều có thể có tác động, nhưng việc sử dụng công cụ ORM có thể tăng đáng kể sức mạnh có sẵn cho bạn với lượng mã nhỏ hơn nhiều so với việc tạo lớp DB của riêng bạn bằng các truy vấn thủ công.

Gary Richardson Tuy nhiên, hoàn toàn đúng, nếu bạn tiếp tục sử dụng SQL trong mã của mình, bạn nên luôn sử dụng các câu lệnh được chuẩn bị sẵn của PDO để xử lý các tham số bất kể bạn đang sử dụng truy vấn hay thủ tục được lưu trữ. Việc loại bỏ thông tin đầu vào do PDO thực hiện cho bạn.

// optional
$attrs = array(PDO::ATTR_PERSISTENT => true);

// create the PDO object
$pdo = new PDO("mysql:host=localhost;dbname=test", "user", "pass", $attrs);

// also optional, but it makes PDO raise exceptions instead of 
// PHP errors which are far more useful for debugging
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$stmt = $pdo->prepare('INSERT INTO venue(venueName, regionId) VALUES(:venueName, :regionId)');
$stmt->bindValue(":venueName", "test");
$stmt->bindValue(":regionId", 1);

$stmt->execute();

$lastInsertId = $pdo->lastInsertId();
var_dump($lastInsertId);

Lưu ý:giả sử rằng ID là 1, tập lệnh trên sẽ xuất ra string(1) "1" . PDO->lastInsertId() trả về ID dưới dạng một chuỗi bất kể cột thực có phải là số nguyên hay không. Điều này có lẽ sẽ không bao giờ là vấn đề đối với bạn vì PHP thực hiện truyền chuỗi thành số nguyên một cách tự động.

Phần sau sẽ xuất ra bool(true) :

// regular equality test
var_dump($lastInsertId == 1); 

nhưng nếu bạn có mã đang mong đợi giá trị là một số nguyên, chẳng hạn như is_int hoặc "của PHP thực sự là 100% bằng" nhà điều hành:

var_dump(is_int($lastInsertId));
var_dump($lastInsertId === 1);

bạn có thể gặp một số vấn đề.

Chỉnh sửa: Một số thảo luận hay về các thủ tục được lưu trữ tại đây



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Làm thế nào để chuyển giá trị hàng hiện tại trong phương thức?

  2. Nhập MySQL 5.7.12 không thể tạo giá trị JSON từ một chuỗi có CHARACTER SET 'nhị phân'

  3. Hàng html đầu tiên không được hiển thị

  4. Hibernate, MySQL và bảng có tên Lặp lại - hành vi lạ

  5. php bộ ký tự mysql:lưu trữ html nội dung quốc tế