Cómo incluir una variable PHP dentro de una declaración MySQL

Resuelto Pinkie asked hace 54 años • 5 respuestas

Estoy intentando insertar valores en la tabla de contenido. Funciona bien si no tengo una variable PHP dentro de VALORES. Cuando pongo la variable $typedentro VALUES, esto no funciona. ¿Qué estoy haciendo mal?

$type = 'testing';
mysql_query("INSERT INTO contents (type, reporter, description) 
     VALUES($type, 'john', 'whatever')");
Pinkie avatar Jan 01 '70 08:01 Pinkie
Aceptado

Las reglas para agregar una variable PHP dentro de cualquier declaración MySQL son claras y simples:

1. Utilice declaraciones preparadas

Esta regla cubre el 99% de las consultas y su consulta en particular. Cualquier variable que represente un literal de datos SQL (o, para decirlo simplemente, una cadena SQL o un número) DEBE agregarse mediante una declaración preparada. Sin excepciones . Un valor constante se puede poner tal cual.

Este enfoque implica cuatro pasos básicos

  • en su declaración SQL, reemplace todas las variables con marcadores de posición
  • preparar la consulta resultante
  • vincular variables a marcadores de posición
  • ejecutar la consulta

Y aquí se explica cómo hacerlo con todos los controladores de bases de datos PHP populares:

Agregar literales de datos usandomysqli

A partir de PHP 8.2, puede realizar toda la secuencia de preparación/vinculación/ejecución en una sola llamada:

$type = 'testing';
$reporter = "John O'Hara";
$sql = "INSERT INTO contents (type,reporter,description) VALUES ('whatever',?,?)";
$mysqli->execute_query($sql, [$reporter, $description]);

Si su versión de PHP es antigua, entonces preparar/vincular/ejecutar debe hacerse explícitamente:

$type = 'testing';
$reporter = "John O'Hara";
$sql = "INSERT INTO contents (type,reporter,description) VALUES ('whatever',?,?)";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param("ss", $reporter, $description);
$stmt->execute();

El código es un poco complicado, pero la explicación detallada de todos estos operadores se puede encontrar en mi artículo Cómo ejecutar una consulta INSERT usando Mysqli , así como una solución que facilita enormemente el proceso.

Para una consulta SELECT puede utilizar el mismo método que el anterior:

$reporter = "John O'Hara";
$result = $mysqli->execute_query("SELECT * FROM users WHERE name=?", [$reporter]);
$row = $result->fetch_assoc(); // or while (...)

pero nuevamente, si su versión de PHP es antigua, necesitará pasar por la rutina preparar/vincular/ejecutar y también agregar una llamada al get_result()método, para familiarizarse mysqli_resultcon el cual pueda recuperar los datos de la forma habitual:

$reporter = "John O'Hara";
$stmt = $mysqli->prepare("SELECT * FROM users WHERE name=?");
$stmt->bind_param("s", $reporter);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc(); // or while (...)
Agregar literales de datos usando PDO
$type = 'testing';
$reporter = "John O'Hara";
$sql = "INSERT INTO contents (type,reporter,description) VALUES ('whatever',?,?)";
$stmt = $pdo->prepare($sql);
$stmt->execute([$reporter, $description]);

En PDO, podemos combinar las partes de vinculación y ejecución, lo cual es muy conveniente. PDO también admite marcadores de posición con nombre que algunos encuentran extremadamente convenientes.

2. Utilice filtrado de lista blanca

Cualquier otra parte de la consulta, como una palabra clave SQL, una tabla o un nombre de campo u operador, debe filtrarse a través de una lista blanca .

A veces tenemos que agregar una variable que represente otra parte de una consulta, como una palabra clave o un identificador (una base de datos, una tabla o un nombre de campo). Es un caso raro pero es mejor estar preparado.

En este caso, su variable debe compararse con una lista de valores escritos explícitamente en su secuencia de comandos. Esto se explica en mi otro artículo, Agregar un nombre de campo en la cláusula ORDER BY según la elección del usuario :

Desafortunadamente, PDO no tiene un marcador de posición para los identificadores (nombres de tablas y campos), por lo que el desarrollador debe filtrarlos manualmente. Un filtro de este tipo a menudo se denomina "lista blanca" (donde solo enumeramos los valores permitidos) en lugar de "lista negra" donde enumeramos los valores no permitidos.

Por lo tanto, tenemos que enumerar explícitamente todas las variantes posibles en el código PHP y luego elegir entre ellas.

Aquí hay un ejemplo:

$orderby = $_GET['orderby'] ?: "name"; // set the default value
$allowed = ["name","price","qty"]; // the white list of allowed field names
$key = array_search($orderby, $allowed, true); // see if we have such a name
if ($key === false) { 
    throw new InvalidArgumentException("Invalid field name"); 
}

Se debe utilizar exactamente el mismo enfoque para la dirección,

$direction = $_GET['direction'] ?: "ASC";
$allowed = ["ASC","DESC"];
$key = array_search($direction, $allowed, true);
if ($key === false) { 
    throw new InvalidArgumentException("Invalid ORDER BY direction"); 
}

Después de dicho código, ambas variables $directiony $orderbyse pueden colocar de forma segura en la consulta SQL, ya que o son iguales a una de las variantes permitidas o se generará un error.

Lo último que hay que mencionar sobre los identificadores es que también deben formatearse según la sintaxis particular de la base de datos. Para MySQL deberían ser backtickcaracteres alrededor del identificador. Entonces, la cadena de consulta final para nuestro pedido por ejemplo sería

$query = "SELECT * FROM `table` ORDER BY `$orderby` $direction";
Your Common Sense avatar Sep 24 '2011 06:09 Your Common Sense

Para evitar la inyección SQL, la instrucción insert con be

$type = 'testing';
$name = 'john';
$description = 'whatever';

$con = new mysqli($user, $pass, $db);
$stmt = $con->prepare("INSERT INTO contents (type, reporter, description) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $type , $name, $description);
$stmt->execute();
Stefan avatar Dec 12 '2016 21:12 Stefan

La mejor opción son las declaraciones preparadas. Para empezar, jugar con citas y escapes es un trabajo más difícil y difícil de mantener. Tarde o temprano terminarás olvidándote accidentalmente de citar algo o terminarás escapando de la misma cadena dos veces, o estropearás algo así. Pueden pasar años antes de que encuentre ese tipo de errores.

http://php.net/manual/en/pdo.prepared-statements.php

Tel avatar Feb 12 '2017 22:02 Tel

El texto dentro de $type se sustituye directamente en la cadena de inserción, por lo tanto MySQL obtiene esto:

... VALUES(testing, 'john', 'whatever')

Tenga en cuenta que no hay comillas sobre las pruebas, debe colocarlas así:

$type = 'testing';
mysql_query("INSERT INTO contents (type, reporter, description) VALUES('$type', 'john', 'whatever')");

También le recomiendo que lea sobre la inyección SQL , ya que este tipo de paso de parámetros es propenso a intentos de piratería si no desinfecta los datos que se utilizan:

  • MySQL - Prevención de inyección SQL
Spencer Rose avatar Sep 24 '2011 06:09 Spencer Rose

Esa es la respuesta fácil:

$query="SELECT * FROM CountryInfo WHERE Name = '".$name."'";

y tú defines $namelo que quieras.
Y otra forma, la compleja, es así:

$query = " SELECT '" . $GLOBALS['Name'] . "' .* " .
         " FROM CountryInfo " .
         " INNER JOIN District " .
         " ON District.CountryInfoId = CountryInfo.CountryInfoId " .
         " INNER JOIN City " .
         " ON City.DistrictId = District.DistrictId " .
         " INNER JOIN '" . $GLOBALS['Name'] . "' " .
         " ON '" . $GLOBALS['Name'] . "'.CityId = City.CityId " .
         " WHERE CountryInfo.Name = '" . $GLOBALS['CountryName'] .
         "'";
Baloomba avatar Aug 31 '2016 15:08 Baloomba