2010-07-05 13 views
8

Existe-t-il un moyen de réutiliser les? Utilisés sur une instruction DBI prepare. Considérez le code suivant:Réutilisation des?? S sur un DBI prepare


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

Il serait très agréable d'utiliser plutôt quelque chose comme ceci:


#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); 

Notez que seul $a est passé à l'exécuter au lieu de trois. Y a-t-il un moyen de le faire dans la vraie vie?

+3

Veuillez ne pas utiliser '$ a' (et' $ b') comme variables nonce. Ils sont spéciaux et spécialement définis: http://perldoc.perl.org/perlvar.html#%24a – pilcrow

Répondre

7

Cela dépend de votre DBD. Par exemple, en utilisant DBD :: Pg avec le style $1 des espaces réservés, ou DBD :: Oracle avec des espaces réservés nommés et bind_param, vous pouvez faire exactement ce que vous aimez. Mais en utilisant le style général des espaces réservés qui fonctionne DBI à l'échelle, ce n'est pas possible.

4

Si vous utilisez une bibliothèque pour générer vos instructions SQL pour vous, par ex. SQL::Abstract ou un ORM complet comme DBIx::Class, vous ne devrez pas vous inquiéter de choses comme ça.

Sinon, vous pouvez faire quelque chose de similaire avec seulement quelques lignes de code:

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

Toutes ces solutions nécessiteraient de taper '$ a' trois fois, ce qui, je crois, est la seule tâche que User1 tente d'éviter . –

+0

@Bipedal: on pourrait passer les paramètres de liaison comme '(($ a) x 3)'. – Ether

+0

Oui, l'opérateur 'x' peut être utilisé comme une solution de contournement, mais cela ne change pas cela 1) l'OP a demandé s'il y a un moyen de passer une variable une fois et l'avoir lié à plusieurs espaces réservés et 2) L'opérateur x' passe plusieurs fois dans la variable, une fois pour chaque espace réservé, ce que la question veut éviter. –

3

@hobbs 'answer est correct - les espaces réservés DBI par défaut ne peuvent pas le faire. @answer @ Ether a raison - une abstraction SQL peut en faire un non-problème.

Cependant, typiquement, il suffit de lier chaque valeur paramétrée distincte une fois. Dans votre exemple, en utilisant une table dérivée scalaire rend la valeur fournie par l'utilisateur disponible par nom au reste de la requête:

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); 
} 

Habituellement, cela est progressivement plus « fil efficace » que l'alternative, car l'utilisateur Le paramètre fourni est généralement transmis une seule fois au lieu de N fois.

0

Vous pouvez définir des variables SQL dans une instruction SQL, puis utiliser cette variable plusieurs fois dans la requête suivante.

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

Aucune variable dupliquée et vous obtenez toujours la sécurité des requêtes paramétrées.

Questions connexes