sql >> Base de Datos >  >> RDS >> Mysql

¿Cómo se gestionan las consultas SQL?

El mejor curso de acción para usted dependerá de cómo esté abordando su acceso a los datos. Hay tres enfoques que puede tomar:

  • Usar procedimientos almacenados
  • Mantenga las consultas en el código (pero coloque todas sus consultas en funciones y arregle todo para usar PDO para parámetros, como se mencionó anteriormente)
  • Usar una herramienta ORM

Si desea pasar su propio SQL sin procesar al motor de la base de datos, los procedimientos almacenados serían el camino a seguir si todo lo que quiere hacer es obtener el SQL sin procesar de su código PHP pero mantenerlo relativamente sin cambios. El debate entre procedimientos almacenados y SQL sin procesar es un poco una guerra santa, pero K. Scott Allen hace un excelente punto, aunque uno descartable, en un artículo sobre versiones de bases de datos :

Tiendo a inclinarme por no usar procedimientos almacenados. He trabajado en proyectos en los que la base de datos tiene una API expuesta a través de procedimientos almacenados, pero los procedimientos almacenados pueden imponer algunas limitaciones propias, y esos proyectos tienen todas , en diversos grados, utilizó SQL sin procesar generado dinámicamente en el código para acceder a la base de datos.

Tener una capa de API en la base de datos brinda una mejor delimitación de las responsabilidades entre el equipo de base de datos y el equipo de desarrollo a expensas de parte de la flexibilidad que tendría si la consulta se mantuviera en el código; sin embargo, es menos probable que los proyectos de PHP tengan suficientes equipos para beneficiarse de esta delimitación.

Conceptualmente, probablemente debería tener su base de datos versionada. Sin embargo, en términos prácticos, es mucho más probable que solo tenga una versión de su código que una versión de su base de datos. Es probable que cambie sus consultas cuando realice cambios en su código, pero si cambia las consultas en procedimientos almacenados almacenados en la base de datos, entonces probablemente no los registre cuando registre el código y pierda muchos de los beneficios del control de versiones para un área importante de su aplicación.

Sin embargo, independientemente de si elige o no usar procedimientos almacenados, al menos debe asegurarse de que cada operación de la base de datos se almacene en una función independiente en lugar de estar incrustada en cada uno de los scripts de su página, esencialmente una capa API para su base de datos que se mantiene y se versiona con su código. Si está utilizando procedimientos almacenados, esto significará efectivamente que tiene dos capas de API para su base de datos, una con el código y otra con la base de datos, lo que puede sentir que complica las cosas innecesariamente si su proyecto no tiene equipos separados. Ciertamente lo hago.

Si el problema es la pulcritud del código, hay formas de hacer que el código con SQL atascado sea más presentable, y la clase UserManager que se muestra a continuación es una buena manera de comenzar:la clase solo contiene consultas relacionadas con la tabla 'usuario', cada consulta tiene su propio método en la clase y las consultas están sangradas en las sentencias de preparación y formateadas como las formatearías en un procedimiento almacenado.

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

Sin embargo, si sus consultas son bastante similares pero tiene una gran cantidad de permutaciones en sus condiciones de consulta, como paginación complicada, clasificación, filtrado, etc., una herramienta de mapeo de objetos/relaciones es probablemente el camino a seguir, aunque el proceso de revisión de su código existente hacer uso de la herramienta podría ser bastante complicado.

Si decide investigar las herramientas ORM, debe consultar Propel , el componente ActiveRecord de Yii , o el PHP ORM King-Daddy, Doctrine . Cada uno de estos le brinda la capacidad de generar consultas a su base de datos mediante programación con todo tipo de lógica complicada. Doctrine es el más completo, lo que le permite crear plantillas para su base de datos con cosas como el Conjunto anidado patrón de árbol fuera de la caja.

En términos de rendimiento, los procedimientos almacenados son los más rápidos, pero generalmente no mucho más que SQL sin formato. Las herramientas ORM pueden tener un impacto significativo en el rendimiento de varias maneras:consultas ineficientes o redundantes, gran cantidad de E/S de archivos al cargar las bibliotecas ORM en cada solicitud, generación dinámica de SQL en cada consulta... todas estas cosas pueden tener un impacto, pero el uso de una herramienta ORM puede aumentar drásticamente la potencia disponible con una cantidad de código mucho menor que la creación de su propia capa de base de datos con consultas manuales.

Gary Richardson Sin embargo, tiene toda la razón, si va a continuar usando SQL en su código, siempre debe usar las declaraciones preparadas de PDO para manejar los parámetros, independientemente de si está usando una consulta o un procedimiento almacenado. PDO realiza por usted la sanitización de la entrada.

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

Advertencia:asumiendo que la ID es 1, la secuencia de comandos anterior generará string(1) "1" . PDO->lastInsertId() devuelve el ID como una cadena independientemente de si la columna real es un número entero o no. Esto probablemente nunca será un problema para usted, ya que PHP realiza la conversión de cadenas a números enteros automáticamente.

Lo siguiente generará bool(true) :

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

pero si tiene un código que espera que el valor sea un número entero, como is_int o "de PHP es realmente, verdaderamente, 100% igual a" operador:

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

podrías encontrarte con algunos problemas.

Editar: Una buena discusión sobre los procedimientos almacenados>aquí