2013-02-27 39 views
1

我根據某些條件(例如操作類型或某個值的存在)通過將字段添加到INSERT語句來構建查詢。但後來我有不同的DBI與不同的參數列表分支execute S,這樣的:Perl DBI使用數組而不是標量列表執行

if ($x) {$extraFields .= ' , X'; $extraValues= ',? '} 
if ($y) {$extraFields .= ' , Y, Z'; $extraValues= ',?, ? '} 

my $theBasicQuery = "INSERT INTO sometable (A, B, $extraFields) VALUES (?, ? $extraValues)"; 

$sth = $dbh->prepare($theBasicQuery) or error 

# but I dont want to have to do this if for execute 
if ($x) {$sth->execute(1,2,99);} 
if ($y) {$sth->execute(1,2,88, 77);} 

我寧願做這樣的事情:

{$sth->execute($anArrayWithDifferentParams);} 

這可能嗎?或者有另一種方法可以做類似的事情嗎?

+0

爲什麼不將字段名稱存儲在一個數組中,然後在形成查詢字符串時加入數組? – 2013-02-27 20:58:20

回答

6

爲了更直接地回答這個問題,使用數組而不是標量列表執行查詢的方法只是將它傳遞給一個數組。 $sth->execute(@params)將工作得很好。

if ($x) {$extraFields .= ' , X'; $extraValues = ',? '; @params = (99); } 
if ($y) {$extraFields .= ' , Y, Z'; $extraValues = ',?, ? '; @params = (88, 77); } 

my $theBasicQuery = "INSERT INTO sometable (A, B, $extraFields) VALUES (?, ? $extraValues)"; 

$sth = $dbh->prepare($theBasicQuery) or error 

$sth->execute(1,2, @params); 
4

我強烈建議使用SQL構建工具來幫助您解決這個問題。我最喜歡的是SQL::Interp,與DBIx::Simple結合使用。這樣的工具將爲您管理綁定變量,並且DBIx :: Simple也會自動處理準備和重新使用語句句柄。與DBIx ::簡單/ SQL中的解決方案::口譯應該是這樣的:

$db->iquery("INSERT INTO sometable", { 
    a => 1, 
    b => 2, 
    %extra 
}); 

SQL ::抽象也很受歡迎,並有類似的語法的解決方案。

+1

謝謝!他們看起來很酷。我忘記提及的一件事是我不允許/不可能安裝新的CPAN模塊。將仍然嘗試。 – orlybg 2013-02-27 21:26:08

+0

+1此工作已完成。 – pilcrow 2013-02-27 21:32:37

+2

奇怪。你的意思是,管理員不會允許Perl模塊的新的* global *安裝,或者你不允許在本地添加它們?如果您從CPAN複製文件,將其粘貼到您的樹中,並將其命名爲My :: SQL :: Interp? – 2013-02-28 14:57:31

2

一種方法:

my %insert = (A => 1, B=> 2); 

if ($condition_x) { 
    $insert{X} = 99; 
} 

if ($condition_y) { 
    $insert{Y} = 88; 
    $insert{Z} = 77; 
} 

# 1. sprintf isn't very perlish, but I find it clearer here 
# 2. quote_identifier(): you won't ever need this until you need it very badly 
# 
my $query = sprintf('INSERT INTO tbl (%s) VALUES (%s)', 
         join ', ' => map { $dbh->quote_identifier($_) } keys %insert, 
         join ', ' => ('?') x keys %insert); 

my $sth = $dbh->prepare($query); # Perhaps prepare_cached, instead? 
$sth->execute(values %insert); 

警告:!DIY

如果可能的話,不要做自己!按照其他地方的建議使用模塊。其他人已經解決了這個問題,比上述更有說服力和更可靠。

0

您可能會發現我的DBIx::PreQL庫對這類任務很有幫助。它提供了一種基於可用數據標記用於處理的SQL查詢的方法。

DBIx :: PreQL使用簡單的前綴和命名佔位符來標記查詢的哪些行應該包括在內。

例如,*表示「始終包含」,&表示如果存在線路的所有數據字段,則表示「包含」。

你的查詢將被標記如下:

* INSERT INTO sometable (
*  A 
* ,B 
& ,C !C! 
& ,D !D! 
) 
*VALUES (
* ?A? 
* ,?B? 
& ,?C? 
& ,?D? 
*) 

而且你通過查詢和數據散列像{ A => '123', B => 'foo', D => 'bar' }到查詢處理器,這將返回查詢:

INSERT INTO sometable (
    A 
    ,B 
    ,D 
) 
VALUES (
    ? 
    ,? 
    ,? 
) 

和參數列表(123, 'foo', 'bar')