2010-07-05 9 views
8

¿Hay alguna manera de reutilizar los? 'S utilizados en una instrucción de preparación de DBI. Considere el siguiente código:Reutilizando? S en un DBI prepare


$sth=$dbh->prepare("INSERT INTO mytable(a,b,c) SELECT ?,B(?),C(?)"); 
$sth->execute($a,$a,$a); 

Sería muy agradable de usar en lugar de algo como esto:


#I'm making this up as something I hope exists 
$sth=$dbh->prepare("INSERT INTO mytable(a,b,c) SELECT ?,B(?:1),C(?:1)"); 
$sth->execute($a); 

en cuenta que sólo una $a se pasa a la ejecución en lugar de tres. ¿Hay alguna manera de hacer esto en la vida real?

+3

No use '$ a' (y' $ b') como variables nonce. Son especiales y están especialmente definidos: http://perldoc.perl.org/perlvar.html#%24a – pilcrow

Respuesta

7

Depende de su DBD. Por ejemplo, si usa DBD :: Pg con el estilo de marcadores de posición $1, o DBD :: Oracle con marcadores de posición con nombre y bind_param, puede hacer exactamente lo que quiera. Pero si se usa el estilo general de marcadores de posición ? que funciona en DBI, no es posible.

4

Si usa una biblioteca para generar sus declaraciones SQL por usted, p. SQL::Abstract o un ORM completo como DBIx::Class, no tendrá que preocuparse por cosas como esas.

alternativa, se puede hacer algo similar con sólo unas pocas líneas de código:

my $sql = 'INSERT INTO ...blah blah... VALUES (' . (join(', ', ('?') x scalar(@insert_elements))) . ')'; 
+1

Todas estas soluciones requerirían escribir '$ a' tres veces, lo que creo que es la única tarea que User1 intenta evitar . –

+0

@Bipedal: uno podría pasar los parámetros de enlace como '(($ a) x 3)'. – Ether

+0

Sí, el operador 'x' se puede usar como una solución alternativa, pero esto no cambia eso 1) el OP preguntó si hay una forma de pasar una variable una vez y hacer que se vincule a múltiples marcadores de posición y 2) usar' El operador x' transfiere la variable varias veces, una para cada marcador de posición, que es lo que la pregunta quiere evitar. –

3

@hobbs 'answer es correcto, los marcadores de posición DBI predeterminados no pueden hacerlo. @ Ether's answer tiene razón: una abstracción de SQL puede hacer que esto no sea un problema.

Sin embargo, normalmente solo es necesario vincular cada valor parametrizado una vez. En su ejemplo, usando un escalar derivada tabla tenga el valor suministrado por el usuario disponibles por su nombre al resto de la consulta:

my $sth = $dbh->prepare(<<'__eosql'); 
    INSERT INTO mytable(a,b,c) 
       SELECT x, B(x), C(x) FROM (SELECT ? AS x) subq 
           -- Subquery may vary from DB to DB: 
           -- "FROM (SELECT ? AS x FROM DUAL) subq" 
           -- "FROM (SELECT ? FROM rdb$database) subq(x)" 
           -- "FROM (VALUES (?)) subq(x)" 
           -- etc. 
__eosql 

for $v (@values) { 
    $sth->execute($v); 
} 

lo general, esto es incrementalmente más "de transmisión eficaz" que la alternativa, ya que el usuario el parámetro proporcionado por lo general se transmite solo una vez en lugar de N veces.

0

Puede establecer variables SQL en una instrucción SQL y luego usar esa variable varias veces en la siguiente consulta.

$dbh->do('set @reusable = ?', undef, $perl_var); 
$dbh->select_arrayref('select * from table where cola = @reusable or colb = @reusable'); 

No hay variables de duplicados y sigue recibiendo la seguridad de consultas con parámetros.