¿Cómo preparar correctamente una sentencia SQL con %LIKE%?

8 feb 2011, 04:15:00
Vistas: 63.7K
Votos: 56

Me gustaría usar una sentencia LIKE %texto% mientras sigo utilizando la clase $wpdb de WordPress para sanitizar y preparar la entrada.

SELECT column_1 from `prefix_my_table` WHERE column_2 LIKE '%something%';

He intentado algo como esto sin éxito:

$wpdb->prepare( "SELECT column_1 from `{$wpdb->base_prefix}my_table` WHERE column_2 LIKE %s;", like_escape($number_to_put_in_like));

¿Cómo se prepara correctamente una sentencia SQL %LIKE% usando la clase de base de datos de WordPress?

0
Todas las respuestas a la pregunta 4
4
82

La función $wpdb->esc_like existe en WordPress porque el escape regular de la base de datos no escapa los caracteres % y _. Esto significa que puedes agregarlos en tus argumentos para wpdb::prepare() sin problema. Esto es también lo que veo en el código central de WordPress:

$wpdb->prepare(" AND $wpdb->usermeta.meta_key = '{$wpdb->prefix}capabilities' AND $wpdb->usermeta.meta_value LIKE %s", '%' . $this->role . '%');

Así que tu código se vería así:

$wpdb->prepare(
    "SELECT
        column_1
    FROM
        `{$wpdb->base_prefix}my_table`
    WHERE
        column_2 LIKE %s;",
    '%' . $wpdb->esc_like($number_to_put_in_like) . '%'
);

También puedes agregar %% en tu consulta para obtener un % literal (wpdb::prepare() usa vsprintf() en segundo plano, que tiene esta sintaxis), pero recuerda que tu cadena no será entrecomillada, debes agregar las comillas tú mismo (lo cual no es lo que normalmente tienes que hacer en wpdb::prepare()).

8 feb 2011 11:39:26
Comentarios

¿Para qué sirven los {}?

Francisco Corrales Morales Francisco Corrales Morales
21 ago 2014 01:39:00

@FranciscoCorralesMorales: Para indicar que todo lo que está dentro debe ser considerado una expresión variable, de lo contrario solo vería $wpdb e ignoraría el ->prefix después de este.

Jan Fabry Jan Fabry
21 ago 2014 18:14:14

@JanFabry Casi. Corregiría el comentario para decir: "... de lo contrario vería todo $wpdb->base_prefixmi_tabla e intentaría buscar la propiedad base_prefixmi_tabla en lugar de solo base_prefix.

Flimm Flimm
10 oct 2017 12:24:25

También es importante mencionar que los % están siendo reemplazados por un hash ridículamente largo. Lo cual parece incorrecto cuando haces var_dump de la salida SQL. Después de horas de búsqueda, se menciona aquí que esto es una corrección de seguridad de WordPress 4.8.3 para inyección SQL. https://stackoverflow.com/a/57914094/7977916

NME New Media Entertainment NME New Media Entertainment
4 ene 2022 22:26:17
3
10

Necesitas duplicar los porcentajes para que no sean tratados como marcadores de fragmentos por wpdb->prepare():

$wpdb->prepare( "SELECT column_1 from `{$wpdb->base_prefix}my_table` WHERE column_2 LIKE %%%s%%;", $wpdb->esc_like( $number_to_put_in_like));

PD: No estoy seguro si esta es la mejor/única forma de hacerlo.

8 feb 2011 08:52:19
Comentarios

Recuerda que debes agregar las comillas alrededor de la cadena tú mismo, porque wpdb::prepare solo las agregará para un %s que no esté precedido por un %. La parte final de tu consulta debería ser WHERE column_2 LIKE '%%%s%%'.

Jan Fabry Jan Fabry
8 feb 2011 11:39:08

Esto funcionó muy bien junto con el consejo de @JanFabry

Gavin Gavin
31 oct 2021 12:32:26

Me gustó más esta respuesta debido al uso de esc_like y el comentario de @JanFabry.

Tami Tami
18 jun 2022 16:06:41
1

Esta es una forma de hacerlo que he verificado y funciona:

$search_text = "%" . $_GET['some_text'] . "%";

$user_count = $wpdb->get_var( 
    $wpdb->prepare( 
        "SELECT COUNT(*) FROM mix_library WHERE ml_setting_name LIKE %s", 
        $search_text 
    ) 
);

Reemplaza las variables según tus necesidades.

25 oct 2012 08:02:20
Comentarios

Deberías escapar los caracteres % (usando like_escape()). Consulta: http://codex.wordpress.org/Class_Reference/wpdb#Protect_Queries_Against_SQL_Injection_Attacks

Stephen Harris Stephen Harris
25 oct 2012 12:25:07
2
$safe_sql = $wpdb->prepare("SELECT * FROM $wp_track_table $sql",["*yoursecretkey*".$_POST['search']."*yoursecretkey*"]);

$safe_sql = str_replace("*yoursecretkey*", "%", $safe_sql);

Encontré una solución adecuada con los códigos anteriores. Definitivamente pruébalo.

22 sept 2022 23:06:27
Comentarios

¿Así que tu enfoque es pasar una cadena aleatoria a prepare() y reemplazarla con porcentajes después? Se siente como si estuvieras luchando contra WordPress.

Rup Rup
23 sept 2022 14:46:17

Básicamente plantillas, supongo. No es lo más limpio, pero ciertamente es un enfoque. ¡Gracias!

editor editor
24 sept 2022 00:15:13