Mysql
 sql >> база данни >  >> RDS >> Mysql

Как управлявате SQL заявки

Най-добрият начин на действие за вас ще зависи от това как подхождате към достъпа си до данни. Има три подхода, които можете да предприемете:

  • Използвайте съхранени процедури
  • Запазете заявките в кода (но поставете всичките си заявки във функции и коригирайте всичко, за да използвате PDO за параметри, както беше споменато по-рано)
  • Използвайте ORM инструмент

Ако искате да предадете собствения си необработен SQL на двигателя на базата данни, тогава съхранените процедури биха били правилният начин, ако всичко, което искате да направите, е да извадите суровия SQL от вашия PHP код, но да го запазите относително непроменен. Дебатът между съхранените процедури и необработения SQL е малко свещена война, но К. Скот Алън прави отлична точка - макар и за изхвърляне - в статия за бази данни за версии :

Склонен съм към това да не използвам съхранени процедури. Работил съм върху проекти, при които DB има API, изложен чрез съхранени процедури, но съхранените процедури могат да наложат някои свои собствени ограничения и тези проекти имат всички , в различна степен, използва динамично генериран необработен SQL в код за достъп до DB.

Наличието на API слой в DB дава по-добро разграничаване на отговорностите между екипа на DB и екипа за разработчици за сметка на част от гъвкавостта, която бихте имали, ако заявката беше запазена в кода, но PHP проектите е по-малко вероятно да имат значителни достатъчно екипи, които да се възползват от това разграничаване.

Концептуално вероятно трябва да имате версия на вашата база данни. На практика обаче е много по-вероятно да имате версия само на вашия код, отколкото да имате версия на базата данни. Вероятно е да променяте заявките си, когато правите промени в кода си, но ако променяте заявките в съхранените процедури, съхранени в базата данни, тогава вероятно няма да ги проверявате, когато проверявате кода и губите много от предимствата на версиите за значителна област от вашето приложение.

Независимо дали решите да не използвате съхранени процедури или не, трябва най-малкото да гарантирате, че всяка операция на базата данни се съхранява в независима функция, вместо да бъде вградена във всеки от скриптовете на вашата страница - по същество API слой за вашата DB, който се поддържа и версии с вашия код. Ако използвате съхранени процедури, това на практика ще означава, че имате два API слоя за вашата DB, един с кода и един с DB, което може да почувствате, че ненужно усложнява нещата, ако вашият проект няма отделни екипи. Определено го правя.

Ако проблемът е в чистотата на кода, има начини да направите кода със заседнал SQL по-представителен, а класът UserManager, показан по-долу, е добър начин да започнете – класът съдържа само заявки, които се отнасят до таблицата „user“, всяка заявка има свой собствен метод в класа и заявките са с отстъп в подготвителните оператори и се форматират, както бихте ги форматирали в съхранена процедура.

// 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'];

Въпреки това, ако вашите заявки са доста сходни, но имате огромен брой пермутации в условията на заявката си, като сложно пейджинг, сортиране, филтриране и т.н., инструментът за картографиране на обекти/релации вероятно е начинът, въпреки че процесът на преработка на съществуващия ви код използването на инструмента може да бъде доста сложно.

Ако решите да проучите ORM инструменти, трябва да погледнете Propel , компонентът ActiveRecord на Yii , или king-daddy PHP ORM, Doctrine . Всеки от тях ви дава възможността програмно да изграждате заявки към вашата база данни с всякакъв вид сложна логика. Doctrine е най-пълнофункционалният, който ви позволява да шаблонирате вашата база данни с неща като вложен набор модел на дърво изваден от кутията.

По отношение на производителността, съхранените процедури са най-бързите, но като цяло не са много над raw sql. ORM инструментите могат да имат значително въздействие върху производителността по редица начини - неефективно или излишно запитване, огромен файлов IO при зареждане на ORM библиотеките при всяка заявка, динамично SQL генериране при всяка заявка... всички тези неща могат да имат влияние, но използването на ORM инструмент може драстично да увеличи мощността, с която разполагате с много по-малко количество код, отколкото създаването на свой собствен DB слой с ръчни заявки.

Гари Ричардсън е абсолютно прав обаче, ако ще продължите да използвате SQL в кода си, винаги трябва да използвате подготвените изрази на PDO за обработка на параметрите, независимо дали използвате заявка или съхранена процедура. Санирането на входа се извършва вместо вас от ЗНП.

// 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);

Предупреждение:ако приемем, че ID е 1, горният скрипт ще изведе string(1) "1" . PDO->lastInsertId() връща ID като низ, независимо дали действителната колона е цяло число или не. Това вероятно никога няма да е проблем за вас, тъй като PHP извършва прехвърляне на низове към цели числа автоматично.

Следното ще изведе bool(true) :

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

но ако имате код, който очаква стойността да бъде цяло число, като is_int или "наистина наистина е 100% равно на" оператор:

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

може да срещнете някои проблеми.

Редактиране: Няколко добра дискусия за съхранените процедури тук



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Съкратете всички таблици (повечето от които имат ограничения). Как да ги пусна временно

  2. Mysqli не позволява множество заявки?

  3. как да работя с рекурсивна заявка в MySql?

  4. Как да проверите версията на MySQL

  5. Свързване на MATLAB и MySQL с JDBC драйвера