2009-02-04 9 views
18

¿Existe una forma estándar de vincular matrices (de escalares) en una consulta SQL? Quiero unir en una cláusula de IN, así:¿Hay un enlace de parámetros SQL para matrices?

SELECT * FROM junk WHERE junk.id IN (?); 

que se esté utilizando Perl::DBI que coacciona a los parámetros a escalares, por lo que terminan con las consultas inútiles como:

SELECT * FROM junk WHERE junk.id IN ('ARRAY(0xdeadbeef)'); 

Aclaración: Puse la consulta en su propio archivo .sql, por lo que la cadena ya está formada. Cuando las respuestas mencionen la creación dinámica de la cadena de consulta probablemente realice una búsqueda y la reemplace.

Editar: La pregunta es un duplicado de Parameterizing a SQL IN clause?. Originalmente pensé que debería cerrarse como tal, pero parece que está acumulando una buena información específica de Perl.

+0

Esta es una víctima de una pregunta bien conocido. Déjame encontrarlo ... – Ray

+0

También es específico de la base de datos ... –

+0

Cool - buscado, pero no pude encontrarlo yo mismo. – cdleary

Respuesta

12

Usted especifique "este es el SQL para una consulta con un parámetro" - eso no funcionará cuando desee muchos parámetros. Es un dolor tratar, por supuesto. Otras dos variaciones a lo que ya se sugirió:

1) Use DBI-> quote en lugar de place holders.

my $sql = "select foo from bar where baz in (" 
      . join(",", map { $dbh->quote($_) } @bazs) 
      . ")"; 
my $data = $dbh->selectall_arrayref($sql); 

2) Use un ORM para hacer este tipo de cosas de bajo nivel para usted. DBIx :: Class o Rose :: DB :: Object, por ejemplo.

+1

sin embargo, en mi caso, usar DBI-> quote no funciona; utilicé $ dbh-> quote; aquí $ dbh es de $ dbh = DBI-> connect ("DBI: mysql: $ db: $ host", $ usuario, $ pase); – hetaoblog

+0

@hetablog De hecho, tienes razón. He actualizado la respuesta. –

2

en Python, siempre he acabado haciendo algo como: '?'

query = 'select * from junk where junk.id in (' 
for id in junkids: 
    query = query + '?,' 
query = query + ')' 

cursor.execute(query, junkids) 

... que se basa esencialmente en una consulta con uno para cada elemento de la lista.

(y si hay otros parámetros de allí también, es necesario asegurarse de que la línea de las cosas correctamente cuando se ejecuta la consulta)

[editar para hacer que el código sea más fácil de entender para los no pitón. Hay un error, donde la consulta tendrá una coma adicional después de la última, que dejaré en debido a su fijación simplemente sería nublar la idea general]

+0

Claro, si no te preocupa la inyección de SQL, entonces no necesitas ningún parámetro. – Ray

+1

@Ray: No entiendo tu comentario - él * está * haciendo el enlace de parámetros, simplemente agregando una cantidad apropiada de parámetros para vincular dinámicamente. – cdleary

+0

hm .. así es él. Perdón mi error. – Ray

9

que hago algo así como:?

my $dbh = DBI->connect(...); 
my @vals= (1,2,3,4,5); 
my $sql = 'SELECT * FROM table WHERE id IN (' . join(',', map { '?' } @vals) . ')'; 
my $sth = $dbh->prepare($sql); 
$sth->execute(@vals); 
+0

Pero recuerde protegerse de los ataques de Inyección de SQL ... – MatBailie

+3

@Dems, el ejemplo de JDrago ya está utilizando variables de vinculación, por lo que no necesita hacer algo más para evitar la inyección de SQL. – mpeters

+1

'map {'?' } @ vals' es más simple '('?') x @ vals' – ysth

4

Con simple DBI tendrías que construir el SQL por tu cuenta, como se sugirió anteriormente. DBIx::Simple (un contenedor para DBI) hace esto automáticamente con el '??' notación:

$db->query("select * from foo where bar in (??)", @values); 
+0

Pero, ¿puede enlazar parámetros en otro lugar del SQL? No veo cómo podrías enlazar parámetros después de ?? a menos que opcionalmente tome una referencia de matriz en su lugar. – cdleary

+0

Buena pregunta. Si entiendo los documentos correctamente, puede tener múltiples marcadores de posición individuales o un solo '??', pero no ambos. – 8jean

13

Si no te gusta el mapa de ahí, puede utilizar el operador 'x': '?'

my $params = join ', ' => ('?') x @foo; 
my $sql = "SELECT * FROM table WHERE id IN ($params)"; 
my $sth = $dbh->prepare($sql); 
$sth->execute(@foo); 

Los paréntesis son necesarios alrededor de la porque eso fuerza a 'x' a estar en el contexto de la lista.

Lea "perldoc perlop" y busque "Binary" x "'para obtener más información (está en la sección" Operadores multiplicadores ").

+0

esta debería ser la respuesta correcta (al menos en mi opinión). – maletin

+0

¿De dónde viene @vals? ¿Quieres decir @foo? – teambob

+0

teambob: sí, quise decir @foo. Lo he cambiado. ¡Gracias! – Ovid

0

Yo uso DBIx::DWIW. Contiene una función llamada InList(). Esto creará la parte del SQL que se necesita para la lista.Sin embargo, esto solo funciona si tiene todo su SQL en el programa en lugar de afuera en un archivo separado.

6

Y sin embargo, otra manera de construir SQL es utilizar algo así como SQL::Abstract ....

+0

Estaba a punto de publicar esto, y definitivamente creo que es la "respuesta correcta". Si no puede usar un ORM, al menos use algo como SQL :: Abstract (o quizás Fey). – jrockway

0

Uso

SELECT * FROM junk WHERE junk.id = ANY (?); 

lugar

Cuestiones relacionadas