Files
guias_informatica/Guia_prepare_statements_cruds.md
T
2026-08-04 19:24:21 +02:00

19 KiB

CRUD con MySQL usando Prepared Statements (recomendado)

<?php $host = "localhost"; $user = "tu\_usuario"; $pass = "tu\_contraseña"; $db = "nombre\_bd"; // Crear conexión $conn = new mysqli($host, $user, $pass, $db); // Verificar conexión if ($conn->connect\_error) { die("Error de conexión: " . $conn->connect\_error); } // ========== CREATE (INSERT) ========== function createUser($nombre, $email) { global $conn; $stmt = $conn->prepare("INSERT INTO usuarios (nombre, email) VALUES (?, ?)"); $stmt->bind\_param("ss", $nombre, $email); if ($stmt->execute()) { echo "Usuario creado con ID: " . $stmt->insert\_id . "\n"; } else { echo "Error al crear usuario: " . $stmt->error . "\n"; } $stmt->close(); } // ========== READ (SELECT) ========== function getUsers() { global $conn; $stmt = $conn->prepare("SELECT id, nombre, email FROM usuarios"); $stmt->execute(); $result = $stmt->get\_result(); $users = []; while ($row = $result->fetch\_assoc()) { $users[] = $row; } $stmt->close(); return $users; } // ========== UPDATE ========== function updateUser($id, $nombre, $email) { global $conn; $stmt = $conn->prepare("UPDATE usuarios SET nombre = ?, email = ? WHERE id = ?"); $stmt->bind\_param("ssi", $nombre, $email, $id); if ($stmt->execute()) { echo "Usuario actualizado. Filas afectadas: " . $stmt->affected\_rows . "\n"; } else { echo "Error al actualizar: " . $stmt->error . "\n"; } $stmt->close(); } // ========== DELETE ========== function deleteUser($id) { global $conn; $stmt = $conn->prepare("DELETE FROM usuarios WHERE id = ?"); $stmt->bind\_param("i", $id); if ($stmt->execute()) { echo "Usuario eliminado. Filas afectadas: " . $stmt->affected\_rows . "\n"; } else { echo "Error al eliminar: " . $stmt->error . "\n"; } $stmt->close(); } // ========== EJEMPLOS DE USO ========== // Crear usuario createUser("Juan Pérez", "[email protected]"); // Obtener todos los usuarios $usuarios = getUsers(); print\_r($usuarios); // Actualizar usuario (asumiendo que existe el ID 1) updateUser(1, "Juan García", "[email protected]"); // Eliminar usuario (asumiendo que existe el ID 2) deleteUser(2); // Cerrar conexión $conn->close(); ?>

Ejemplo de SELECT con Prepared Statements en MySQLi

Aquí tienes un ejemplo completo de cómo realizar consultas SELECT usando prepared statements con MySQLi:

  1. Ejemplo básico (obtener múltiples registros)
<?php // Configuración de la base de datos $host = "localhost"; $user = "tu\_usuario"; $pass = "tu\_contraseña"; $db = "nombre\_bd"; // Crear conexión $conn = new mysqli($host, $user, $pass, $db); // Verificar conexión if ($conn->connect\_error) { die("Error de conexión: " . $conn->connect\_error); } // Preparar la consulta SELECT $stmt = $conn->prepare("SELECT id, nombre, email FROM usuarios WHERE activo = ?"); $activo = 1; // Valor para el parámetro $stmt->bind\_param("i", $activo); // "i" indica que es un entero // Ejecutar la consulta $stmt->execute(); // Obtener resultados $result = $stmt->get\_result(); // Procesar resultados echo "Usuarios activos:\n"; while ($row = $result->fetch\_assoc()) { echo "ID: " . $row['id'] . ", Nombre: " . $row['nombre'] . ", Email: " . $row['email'] . "\n"; } // Cerrar statement y conexión $stmt->close(); $conn->close(); ?>
  1. Ejemplo con parámetros dinámicos
<?php // ... (configuración de conexión igual que arriba) // Función para buscar usuarios por nombre function buscarUsuariosPorNombre($nombre) { global $conn; $stmt = $conn->prepare("SELECT id, nombre, email FROM usuarios WHERE nombre LIKE ?"); $param = "%" . $nombre . "%"; // Búsqueda parcial $stmt->bind\_param("s", $param); // "s" indica string $stmt->execute(); $result = $stmt->get\_result(); $usuarios = []; while ($row = $result->fetch\_assoc()) { $usuarios[] = $row; } $stmt->close(); return $usuarios; } // Ejemplo de uso $resultados = buscarUsuariosPorNombre("Juan"); print\_r($resultados); $conn->close(); ?>
  1. Ejemplo con múltiples parámetros
<?php // ... (configuración de conexión igual que arriba) // Consulta con múltiples condiciones $stmt = $conn->prepare("SELECT \* FROM usuarios WHERE edad > ? AND pais = ?"); $edad\_minima = 18; $pais = "España"; $stmt->bind\_param("is", $edad\_minima, $pais); // "is" = integer + string $stmt->execute(); $result = $stmt->get\_result(); while ($row = $result->fetch\_assoc()) { echo "Usuario: " . $row['nombre'] . " (" . $row['edad'] . " años)\n"; } $stmt->close(); $conn->close(); ?>
  1. Ejemplo con ORDER BY y LIMIT
<?php // ... (configuración de conexión igual que arriba) // Consulta con ordenación y límite $stmt = $conn->prepare("SELECT nombre, email FROM usuarios ORDER BY fecha\_registro DESC LIMIT ?"); $limite = 10; $stmt->bind\_param("i", $limite); $stmt->execute(); $result = $stmt->get\_result(); echo "Últimos 10 usuarios registrados:\n"; while ($row = $result->fetch\_assoc()) { echo "- " . $row['nombre'] . ": " . $row['email'] . "\n"; } $stmt->close(); $conn->close(); ?>

Ventajas de usar prepared statements para SELECT:

Seguridad: Previene inyección SQL al separar claramente los datos de la consulta

Rendimiento: Mejor performance en consultas repetidas (el motor prepara la consulta una vez)

Claridad: Código más organizado y mantenible

Tipado seguro: Los parámetros se vinculan con su tipo correcto (entero, string, etc.)

Tipos de parámetros en bind_param():

"i" - integer (entero)

"d" - double (decimal)

"s" - string (cadena)

"b" - blob (datos binarios)

Puedes combinar tipos cuando tienes múltiples parámetros: $stmt->bind_param("iss", $id, $nombre, $email);

Recomendación:

Usa new mysqli() porque:

Es más moderno y consistente con PHP actual

Mejor para mantenimiento de código

Permite encadenamiento de métodos

Más intuitivo en frameworks modernos

CRUD con MySQL sin Prepared Statements (no recomendado)

Aquí tienes el mismo CRUD pero sin utilizar prepared statements. Importante: Este método es menos seguro y no se recomienda para producción, ya que es vulnerable a inyección SQL.

<?php // Configuración de la base de datos $host = "localhost"; $user = "tu\_usuario"; $pass = "tu\_contraseña"; $db = "nombre\_bd"; // Crear conexión $conn = new mysqli($host, $user, $pass, $db); // Verificar conexión if ($conn->connect\_error) { die("Error de conexión: " . $conn->connect\_error); } // ========== CREATE (INSERT) ========== function createUser($nombre, $email) { global $conn; // Escapar valores para prevenir inyección SQL (no es tan seguro como prepared statements) $nombre = $conn->real\_escape\_string($nombre); $email = $conn->real\_escape\_string($email); $sql = "INSERT INTO usuarios (nombre, email) VALUES ('$nombre', '$email')"; if ($conn->query($sql)) { echo "Usuario creado con ID: " . $conn->insert\_id . "\n"; } else { echo "Error al crear usuario: " . $conn->error . "\n"; } } // ========== READ (SELECT) ========== function getUsers() { global $conn; $sql = "SELECT id, nombre, email FROM usuarios"; $result = $conn->query($sql); $users = []; if ($result->num\_rows > 0) { while ($row = $result->fetch\_assoc()) { $users[] = $row; } } return $users; } // ========== UPDATE ========== function updateUser($id, $nombre, $email) { global $conn; // Escapar valores $id = (int)$id; // Forzar tipo entero $nombre = $conn->real\_escape\_string($nombre); $email = $conn->real\_escape\_string($email); $sql = "UPDATE usuarios SET nombre = '$nombre', email = '$email' WHERE id = $id"; if ($conn->query($sql)) { echo "Usuario actualizado. Filas afectadas: " . $conn->affected\_rows . "\n"; } else { echo "Error al actualizar: " . $conn->error . "\n"; } } // ========== DELETE ========== function deleteUser($id) { global $conn; $id = (int)$id; // Forzar tipo entero $sql = "DELETE FROM usuarios WHERE id = $id"; if ($conn->query($sql)) { echo "Usuario eliminado. Filas afectadas: " . $conn->affected\_rows . "\n"; } else { echo "Error al eliminar: " . $conn->error . "\n"; } } // ========== EJEMPLOS DE USO ========== // Crear usuario createUser("Juan Pérez", "[email protected]"); // Obtener todos los usuarios $usuarios = getUsers(); print\_r($usuarios); // Actualizar usuario (asumiendo que existe el ID 1) updateUser(1, "Juan García", "[email protected]"); // Eliminar usuario (asumiendo que existe el ID 2) deleteUser(2); // Cerrar conexión $conn->close(); ?>

Diferencias clave con la versión con prepared statements:

Seguridad:

Se usa real_escape_string() en lugar de parámetros enlazados

Se fuerza el tipo de datos con (int) para IDs

Aún así es menos seguro que los prepared statements

Sintaxis:

Consultas directas con concatenación de strings

No hay bind_param() ni execute()

Se usa $conn->query() directamente

Manejo de resultados:

Se accede a conn->insert_id en lugar de stmt->insert_id

Se usa conn->affected_rows en lugar de stmt->affected_rows

Advertencia importante:

Este método no es recomendable para aplicaciones reales porque:

real_escape_string() no protege completamente contra inyección SQL

La conversión de tipos manual es propensa a errores

Es más difícil mantener el código

No aprovecha las optimizaciones del servidor SQL

Los prepared statements son el método recomendado para interactuar con bases de datos en PHP por su seguridad y eficiencia.

------------------------------------------------------------------------------------------------------------------------------

CRUD con SQLite usando Prepared Statements (recomendado)

<?php // Configuración de la base de datos SQLite $dbFile = 'mi\_base\_datos.db'; try { // Crear/conectar a la base de datos $db = new PDO("sqlite:$dbFile"); $db->setAttribute(PDO::ATTR\_ERRMODE, PDO::ERRMODE\_EXCEPTION); // Crear tabla si no existe $db->exec("CREATE TABLE IF NOT EXISTS productos ( id INTEGER PRIMARY KEY AUTOINCREMENT, nombre TEXT NOT NULL, precio REAL NOT NULL, stock INTEGER NOT NULL )"); // ========== CREATE (INSERT) ========== function crearProducto($nombre, $precio, $stock) { global $db; $stmt = $db->prepare("INSERT INTO productos (nombre, precio, stock) VALUES (?, ?, ?)"); $stmt->execute([$nombre, $precio, $stock]); return $db->lastInsertId(); } // ========== READ (SELECT) ========== function obtenerProductos() { global $db; $stmt = $db->prepare("SELECT \* FROM productos"); $stmt->execute(); return $stmt->fetchAll(PDO::FETCH\_ASSOC); } function obtenerProductoPorId($id) { global $db; $stmt = $db->prepare("SELECT \* FROM productos WHERE id = ?"); $stmt->execute([$id]); return $stmt->fetch(PDO::FETCH\_ASSOC); } // ========== UPDATE ========== function actualizarProducto($id, $nombre, $precio, $stock) { global $db; $stmt = $db->prepare("UPDATE productos SET nombre = ?, precio = ?, stock = ? WHERE id = ?"); $stmt->execute([$nombre, $precio, $stock, $id]); return $stmt->rowCount(); } // ========== DELETE ========== function eliminarProducto($id) { global $db; $stmt = $db->prepare("DELETE FROM productos WHERE id = ?"); $stmt->execute([$id]); return $stmt->rowCount(); } // ===== Ejemplos de uso ===== // Crear $idNuevo = crearProducto("Laptop", 1200.50, 10); echo "Producto creado con ID: $idNuevo\n"; // Leer todos $productos = obtenerProductos(); print\_r($productos); // Leer uno $producto = obtenerProductoPorId(1); print\_r($producto); // Actualizar $filasActualizadas = actualizarProducto(1, "Laptop Pro", 1350.75, 8); echo "Filas actualizadas: $filasActualizadas\n"; // Eliminar $filasEliminadas = eliminarProducto(2); echo "Filas eliminadas: $filasEliminadas\n"; } catch (PDOException $e) { die("Error con SQLite: " . $e->getMessage()); } ?>

CRUD con SQLite usando Prepared Statements (sin PDO)

<?php // Configuración de la base de datos SQLite $dbFile = 'mi\_base\_datos.db'; try { // Crear/conectar a la base de datos $db = new SQLite3($dbFile); // Habilitar excepciones para manejo de errores $db->enableExceptions(true); // Crear tabla si no existe $db->exec("CREATE TABLE IF NOT EXISTS productos ( id INTEGER PRIMARY KEY AUTOINCREMENT, nombre TEXT NOT NULL, precio REAL NOT NULL, stock INTEGER NOT NULL )"); // ========== CREATE (INSERT) con prepared statement ========== function crearProducto($nombre, $precio, $stock) { global $db; $stmt = $db->prepare("INSERT INTO productos (nombre, precio, stock) VALUES (:nombre, :precio, :stock)"); $stmt->bindValue(':nombre', $nombre, SQLITE3\_TEXT); $stmt->bindValue(':precio', $precio, SQLITE3\_FLOAT); $stmt->bindValue(':stock', $stock, SQLITE3\_INTEGER); $result = $stmt->execute(); return $db->lastInsertRowID(); } // ========== READ (SELECT) con prepared statement ========== function obtenerProductos() { global $db; $stmt = $db->prepare("SELECT \* FROM productos"); $result = $stmt->execute(); $productos = []; while ($row = $result->fetchArray(SQLITE3\_ASSOC)) { $productos[] = $row; } return $productos; } function obtenerProductoPorId($id) { global $db; $stmt = $db->prepare("SELECT \* FROM productos WHERE id = :id"); $stmt->bindValue(':id', $id, SQLITE3\_INTEGER); $result = $stmt->execute(); return $result->fetchArray(SQLITE3\_ASSOC); } // ========== UPDATE con prepared statement ========== function actualizarProducto($id, $nombre, $precio, $stock) { global $db; $stmt = $db->prepare("UPDATE productos SET nombre = :nombre, precio = :precio, stock = :stock WHERE id = :id"); $stmt->bindValue(':nombre', $nombre, SQLITE3\_TEXT); $stmt->bindValue(':precio', $precio, SQLITE3\_FLOAT); $stmt->bindValue(':stock', $stock, SQLITE3\_INTEGER); $stmt->bindValue(':id', $id, SQLITE3\_INTEGER); $stmt->execute(); return $db->changes(); } // ========== DELETE con prepared statement ========== function eliminarProducto($id) { global $db; $stmt = $db->prepare("DELETE FROM productos WHERE id = :id"); $stmt->bindValue(':id', $id, SQLITE3\_INTEGER); $stmt->execute(); return $db->changes(); } // ===== Ejemplos de uso ===== // Crear producto $idNuevo = crearProducto("Monitor", 199.99, 15); echo "Producto creado con ID: $idNuevo\n"; // Leer todos los productos $productos = obtenerProductos(); print\_r($productos); // Leer un producto específico $producto = obtenerProductoPorId(1); print\_r($producto); // Actualizar producto $filasActualizadas = actualizarProducto(1, "Monitor HD", 179.99, 10); echo "Filas actualizadas: $filasActualizadas\n"; // Eliminar producto $filasEliminadas = eliminarProducto(2); echo "Filas eliminadas: $filasEliminadas\n"; } catch (Exception $e) { die("Error con SQLite: " . $e->getMessage()); } finally { if (isset($db)) { $db->close(); } } ?>

Características clave:

Prepared Statements nativos de SQLite3:

Uso de prepare() para crear statements

bindValue() para vincular parámetros

Tipos de datos definidos (SQLITE3_TEXT, SQLITE3_INTEGER, etc.)

Métodos importantes:

execute() para ejecutar el statement preparado

fetchArray(SQLITE3_ASSOC) para obtener resultados

lastInsertRowID() para obtener el último ID insertado

changes() para obtener filas afectadas

Tipos de datos para bindValue():

SQLITE3_INTEGER

SQLITE3_FLOAT

SQLITE3_TEXT

SQLITE3_BLOB

SQLITE3_NULL

Ventajas:

Seguridad contra inyección SQL

Manejo adecuado de tipos de datos

No requiere PDO

Sintaxis específica para SQLite

Diferencia con la versión PDO:

Sintaxis:

PDO usa ? o :nombre para placeholders

SQLite3 nativo usa :nombre principalmente

Métodos:

PDO tiene bindParam() y bindValue()

SQLite3 nativo solo tiene bindValue()

Tipos de resultados:

PDO ofrece fetchAll() y varios estilos de fetch

SQLite3 nativo usa fetchArray() con constantes para el estilo

En SQLite3 usando la extensión nativa de PHP (no PDO), no se usa el sistema de tipos combinados como en MySQLi ("iss").

En su lugar, debes especificar el tipo para cada parámetro individualmente usando bindValue().

CRUD con SQLite sin Prepared Statements (no recomendado)

<?php // Configuración de la base de datos SQLite $dbFile = 'mi\_base\_datos.db'; try { // Crear/conectar a la base de datos $db = new SQLite3($dbFile); // Crear tabla si no existe $db->exec("CREATE TABLE IF NOT EXISTS productos ( id INTEGER PRIMARY KEY AUTOINCREMENT, nombre TEXT NOT NULL, precio REAL NOT NULL, stock INTEGER NOT NULL )"); // ========== CREATE (INSERT) ========== function crearProducto($nombre, $precio, $stock) { global $db; $nombre = SQLite3::escapeString($nombre); $precio = floatval($precio); $stock = intval($stock); $sql = "INSERT INTO productos (nombre, precio, stock) VALUES ('$nombre', $precio, $stock)"; if ($db->exec($sql)) { return $db->lastInsertRowID(); } return false; } // ========== READ (SELECT) ========== function obtenerProductos() { global $db; $result = $db->query("SELECT \* FROM productos"); $productos = []; while ($row = $result->fetchArray(SQLITE3\_ASSOC)) { $productos[] = $row; } return $productos; } function obtenerProductoPorId($id) { global $db; $id = intval($id); $result = $db->querySingle("SELECT \* FROM productos WHERE id = $id", true); return $result; } // ========== UPDATE ========== function actualizarProducto($id, $nombre, $precio, $stock) { global $db; $id = intval($id); $nombre = SQLite3::escapeString($nombre); $precio = floatval($precio); $stock = intval($stock); $sql = "UPDATE productos SET nombre = '$nombre', precio = $precio, stock = $stock WHERE id = $id"; return $db->exec($sql); } // ========== DELETE ========== function eliminarProducto($id) { global $db; $id = intval($id); $sql = "DELETE FROM productos WHERE id = $id"; return $db->exec($sql); } // ===== Ejemplos de uso ===== // Crear $idNuevo = crearProducto("Teclado", 45.99, 25); echo "Producto creado con ID: $idNuevo\n"; // Leer todos $productos = obtenerProductos(); print\_r($productos); // Leer uno $producto = obtenerProductoPorId(1); print\_r($producto); // Actualizar $actualizado = actualizarProducto(1, "Teclado Mecánico", 59.99, 15); echo "Actualizado: " . ($actualizado ? "Sí" : "No") . "\n"; // Eliminar $eliminado = eliminarProducto(3); echo "Eliminado: " . ($eliminado ? "Sí" : "No") . "\n"; } catch (Exception $e) { die("Error con SQLite: " . $e->getMessage()); } ?>