sql >> Databasteknik >  >> RDS >> Mysql

Hur hanterar du SQL-frågor

Det bästa tillvägagångssättet för dig beror på hur du närmar dig din dataåtkomst. Det finns tre tillvägagångssätt du kan använda:

  • Använd lagrade procedurer
  • Behåll frågorna i koden (men lägg alla dina frågor i funktioner och fixa allt för att använda PDO för parametrar, som nämnts tidigare)
  • Använd ett ORM-verktyg

Om du vill skicka din egen rå SQL till databasmotorn så skulle lagrade procedurer vara rätt väg att gå om allt du vill göra är att få ut rå SQL från din PHP-kod men behålla den relativt oförändrad. Debatten om lagrade procedurer kontra rå SQL-debatt är lite av ett heligt krig, men K. Scott Allen gör en utmärkt poäng - om än en engångsföremål - i en artikel om versionsdatabaser :

Jag tenderar att luta mig mot att inte använda lagrade procedurer. Jag har arbetat med projekt där DB har ett API exponerat genom lagrade procedurer, men lagrade procedurer kan införa några egna begränsningar, och dessa projekt har alla , i varierande grad, använde dynamiskt genererad rå SQL i kod för att komma åt DB.

Att ha ett API-lager på DB ger bättre avgränsning av ansvarsområden mellan DB-teamet och Dev-teamet på bekostnad av en del av den flexibilitet du skulle ha om frågan hölls i koden, men det är mindre sannolikt att PHP-projekt har betydande tillräckligt många lag för att dra nytta av denna avgränsning.

Konceptuellt bör du förmodligen ha din databas versionsversion. I praktiken är det dock mycket mer sannolikt att du bara har din kodversion än att du har din databas versionsversion. Du kommer sannolikt att ändra dina frågor när du gör ändringar i din kod, men om du ändrar frågorna i lagrade procedurer lagrade mot databasen kommer du förmodligen inte att checka in dem när du checkar in koden och du förlorar många av fördelarna med versionshantering för en betydande del av din applikation.

Oavsett om du väljer att inte använda lagrade procedurer eller inte, bör du åtminstone se till att varje databasoperation lagras i en oberoende funktion istället för att vara inbäddad i vart och ett av din sidas skript - i huvudsak ett API-lager för din DB som underhålls och versioneras med din kod. Om du använder lagrade procedurer innebär detta i praktiken att du har två API-lager för din DB, ett med koden och ett med DB, vilket du kan känna att det komplicerar saker i onödan om ditt projekt inte har separata team. Det gör jag verkligen.

Om problemet handlar om kodsnyhet, finns det sätt att göra kod med SQL fast i den mer presentabel, och klassen UserManager som visas nedan är ett bra sätt att börja - klassen innehåller bara frågor som relaterar till "användartabellen", varje fråga har sin egen metod i klassen och frågorna dras in i prepare-satserna och formateras som du skulle formatera dem i en lagrad procedur.

// 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 om dina frågor är ganska lika men du har ett stort antal permutationer i dina frågeförhållanden som komplicerad personsökning, sortering, filtrering, etc, är förmodligen ett objekt-/relationsmappningsverktyg rätt väg att gå, även om processen att se över din befintliga kod att använda verktyget kan vara ganska komplicerat.

Om du bestämmer dig för att undersöka ORM-verktyg bör du titta på Propel , ActiveRecord-komponenten i Yii , eller king-daddy PHP ORM, doktrin . Var och en av dessa ger dig möjligheten att programmässigt bygga frågor till din databas med all slags komplicerad logik. Doctrine är den mest kompletta, vilket gör att du kan malla din databas med saker som Inkapslade set trädmönster ur kartongen.

När det gäller prestanda är lagrade procedurer de snabbaste, men i allmänhet inte mycket över raw sql. ORM-verktyg kan ha en betydande inverkan på prestanda på ett antal sätt - ineffektiv eller redundant sökning, enorma fil-IO medan ORM-biblioteken laddas vid varje begäran, dynamisk SQL-generering på varje fråga... alla dessa saker kan ha en inverkan, men användningen av ett ORM-verktyg kan drastiskt öka kraften som är tillgänglig för dig med en mycket mindre mängd kod än att skapa ditt eget DB-lager med manuella frågor.

Gary Richardson har helt rätt men om du ska fortsätta använda SQL i din kod bör du alltid använda PDO:s förberedda satser för att hantera parametrarna oavsett om du använder en fråga eller en lagrad procedur. Saneringen av input utförs åt dig av 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);

Varning:förutsatt att ID är 1, kommer ovanstående skript att mata ut string(1) "1" . PDO->lastInsertId() returnerar ID:t som en sträng oavsett om den faktiska kolumnen är ett heltal eller inte. Detta kommer förmodligen aldrig att vara ett problem för dig eftersom PHP utför casting av strängar till heltal automatiskt.

Följande kommer att mata ut bool(true) :

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

men om du har kod som förväntar sig att värdet ska vara ett heltal, som is_int eller PHP:s "är verkligen, verkligen, 100 % lika med" operatör:

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

du kan stöta på några problem.

Redigera: Några bra diskussioner om lagrade procedurer här



  1. Hur man kontrollerar MySQL-anslutningsstatus i C#

  2. Hur NCHAR()-funktionen fungerar i SQL Server (T-SQL)

  3. Var kan jag hitta filen my.ini för Windows mysql-server?

  4. Fråga för att välja strängar som slutar med ett visst tecken