sql >> Database teknologi >  >> RDS >> Mysql

Hvordan administrerer du SQL-forespørgsler

Den bedste fremgangsmåde for dig vil afhænge af, hvordan du griber din dataadgang an. Der er tre tilgange, du kan tage:

  • Brug lagrede procedurer
  • Behold forespørgslerne i koden (men sæt alle dine forespørgsler i funktioner og ret alt for at bruge PDO til parametre, som tidligere nævnt)
  • Brug et ORM-værktøj

Hvis du vil videregive din egen rå SQL til databasemotoren, vil lagrede procedurer være vejen at gå, hvis alt du vil gøre er at få den rå SQL ud af din PHP-kode, men holde den relativt uændret. De lagrede procedurer vs rå SQL-debat er lidt af en hellig krig, men K. Scott Allen gør en glimrende pointe - omend en smid - i en artikel om versionsdatabaser :

Jeg har en tendens til at hælde til ikke at bruge lagrede procedurer. Jeg har arbejdet på projekter, hvor DB'en har en API, der er eksponeret gennem lagrede procedurer, men lagrede procedurer kan pålægge deres egne begrænsninger, og disse projekter har alle , i varierende grad, brugte dynamisk genereret rå SQL i kode for at få adgang til DB.

At have et API-lag på DB'en giver en bedre afgrænsning af ansvar mellem DB-teamet og Dev-teamet på bekostning af noget af den fleksibilitet, du ville have, hvis forespørgslen blev holdt i koden, men PHP-projekter er mindre tilbøjelige til at have betydelige nok hold til at drage fordel af denne afgrænsning.

Begrebsmæssigt burde du sandsynligvis have din database versioneret. I praksis er det dog langt mere sandsynligt, at du kun har din kode versioneret, end at du har din database versioneret. Det er sandsynligt, at du ændrer dine forespørgsler, når du foretager ændringer i din kode, men hvis du ændrer forespørgslerne i lagrede procedurer, der er gemt mod databasen, vil du sandsynligvis ikke tjekke dem ind, når du tjekker koden ind, og du mister mange af fordelene ved versionering for et væsentligt område af din applikation.

Uanset om du vælger ikke at bruge lagrede procedurer eller ej, bør du i det mindste sikre, at hver databaseoperation er gemt i en uafhængig funktion i stedet for at blive indlejret i hver af din sides scripts - i det væsentlige et API-lag til din DB, som er vedligeholdt og versioneret med din kode. Hvis du bruger lagrede procedurer, vil det reelt betyde, at du har to API-lag til din DB, et med koden og et med DB'en, hvilket du måske føler unødigt komplicerer tingene, hvis dit projekt ikke har separate teams. Det gør jeg bestemt.

Hvis problemet drejer sig om kodning, er der måder at gøre kode med SQL fast i den mere præsentabel, og UserManager-klassen vist nedenfor er en god måde at starte på - klassen indeholder kun forespørgsler, der vedrører 'bruger'-tabellen, hver forespørgsel har sin egen metode i klassen, og forespørgslerne indrykkes i prepare-sætningerne og formateres, som du ville formatere dem i en lagret procedure.

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

Men hvis dine forespørgsler er ret ens, men du har et stort antal permutationer i dine forespørgselsbetingelser som kompliceret personsøgning, sortering, filtrering osv., er et objekt/relationelt kortlægningsværktøj sandsynligvis vejen at gå, selvom processen med at eftersyne din eksisterende kode at gøre brug af værktøjet kunne være ret kompliceret.

Hvis du beslutter dig for at undersøge ORM-værktøjer, bør du se på Propel , ActiveRecord-komponenten af ​​Yii , eller king-daddy PHP ORM, doktrin . Hver af disse giver dig mulighed for programmæssigt at bygge forespørgsler til din database med al mulig kompliceret logik. Doktrin er den mest fuldt udbyggede, så du kan skabeloner til din database med ting som det Indlejrede sæt træmønster ud af kassen.

Med hensyn til ydeevne er lagrede procedurer de hurtigste, men generelt ikke meget over raw sql. ORM-værktøjer kan have en betydelig indvirkning på ydeevnen på en række måder - ineffektiv eller redundant forespørgsel, enorm fil-IO, mens ORM-bibliotekerne indlæses på hver anmodning, dynamisk SQL-generering på hver forespørgsel... alle disse ting kan have en indflydelse, men brugen af ​​et ORM-værktøj kan drastisk øge den tilgængelige kraft med en meget mindre mængde kode end at oprette dit eget DB-lag med manuelle forespørgsler.

Gary Richardson er dog helt rigtigt, hvis du vil fortsætte med at bruge SQL i din kode, bør du altid bruge PDO's forberedte sætninger til at håndtere parametrene, uanset om du bruger en forespørgsel eller en lagret procedure. Saneringen af ​​input udføres for dig af 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);

Advarsel:forudsat at ID'et er 1, vil ovenstående script udsende string(1) "1" . PDO->lastInsertId() returnerer ID'et som en streng, uanset om den faktiske kolonne er et heltal eller ej. Dette vil sandsynligvis aldrig være et problem for dig, da PHP udfører casting af strenge til heltal automatisk.

Følgende vil udsende bool(true) :

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

men hvis du har kode, der forventer, at værdien er et heltal, f.eks. is_int eller PHP's "er virkelig, virkelig, 100 % lig med" operatør:

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

du kan løbe ind i nogle problemer.

Rediger: Nogle gode diskussioner om lagrede procedurer her



  1. Tjek sproget for streng baseret på glyffer i PHP

  2. Hvordan nulstiller jeg en sekvens i Oracle?

  3. Wordnet SQL-forklaring

  4. Django JSONField-filtrering