2010-07-05 13 views
8

Esiste un modo per riutilizzare i? Utilizzati in un'istruzione di preparazione DBI. Si consideri il seguente codice:Riutilizzare? Su un DBI prepara


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

Sarebbe molto bello utilizzare invece qualcosa di simile:


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

Si noti che un solo $a è passato alla esecuzione invece di tre. C'è un modo per farlo nella vita reale?

+3

Si prega di non utilizzare '$ a' (e' $ b') come variabili nonce. Sono speciali e appositamente definiti: http://perldoc.perl.org/perlvar.html#%24a – pilcrow

risposta

7

Dipende dal vostro DBD. Ad esempio, utilizzando DBD :: Pg con lo stile $1 di segnaposto o DBD :: Oracle con segnaposto con nome e bind_param, è possibile eseguire esattamente ciò che si desidera. Ma usando lo stile generale di segnaposto ? che funziona con DBI-wide, non è possibile.

4

Se si utilizza una libreria per generare le proprie istruzioni SQL, ad es. SQL::Abstract o un ORM completo come DBIx::Class, non dovrai preoccuparti di cose del genere.

In alternativa è possibile fare qualcosa di simile con poche righe di codice:

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

Tutte queste soluzioni richiedono la digitazione di '$ a' tre volte, che ritengo sia l'unica attività che Utente1 sta tentando di evitare . –

+0

@Bipedal: uno potrebbe passare i parametri di collegamento come '(($ a) x 3)'. – Ether

+0

Sì, l'operatore 'x' può essere usato come soluzione alternativa, ma ciò non cambia che 1) l'OP ha chiesto se c'è un modo per passare una variabile una volta e averla associata a più segnaposti e 2) usando il' L'operatore x' passa più volte nella variabile, una volta per ogni segnaposto, che è ciò che la domanda vuole evitare. –

3

@hobbs 'answer è corretto: i segnaposto DBI predefiniti non possono farlo. @ Ether's answer ha ragione: un'astrazione SQL può rendere questo un non-problema.

Tuttavia, in genere è sufficiente unire ciascun valore parametrico distinto una sola volta. Nel tuo esempio, utilizzando uno scalare derivato tavolo rende il valore fornito dall'utente disponibili nome al resto della query:

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

solito questo è incrementalmente più "wire efficiente" rispetto all'alternativa, poiché l'utente -il parametro fornito viene trasmesso in genere una sola volta invece di N volte.

0

È possibile impostare le variabili SQL in un'istruzione SQL e quindi utilizzare tale variabile più volte nella query successiva.

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

Nessuna variabile duplicati ed è ancora ottenere la sicurezza di query con parametri.