2009-11-13 92 views
5

我試圖使用SQL*Plus連接到一個表,並獲取Perl腳本中的數據並將該輸出存儲在Perl變量中。Perl腳本中的SQL * Plus

在一個shell腳本,我這樣做:

SQL_RESULT=`sqlplus -s ${CONNECT_STRING} << EOF 
    ${SQLPLUS_SETTINGS} 
    select foo||'|'||bar ||'|'|| xyz from temp where dfg='some'; 
    exit; 
    EOF` 

但我怎麼能做到這一點在Perl?

回答

10

檢出DBI模塊。實際上,有一個專門的網站:dbi.perl.org。另外,請查看the CPAN module reference for DBI

下面是一個代碼示例,直接從the first DBI tutorial on google

use DBI; 

    my $dbh = DBI->connect('DBI:Oracle:payroll') 
     or die "Couldn't connect to database: " . DBI->errstr; 
    my $sth = $dbh->prepare('SELECT * FROM people WHERE lastname = ?') 
     or die "Couldn't prepare statement: " . $dbh->errstr; 

    $sth->execute($lastname)    # Execute the query 
     or die "Couldn't execute statement: " . $sth->errstr; 

    # Read the matching records and print them out   
    while (@data = $sth->fetchrow_array()) { 
     my $firstname = $data[1]; 
     my $id = $data[2]; 
     print "\t$id: $firstname $lastname\n"; 
    } 
    if ($sth->rows == 0) { 
     print "No names matched `$lastname'.\n\n"; 
    } 
    $sth->finish; 
    print "\n"; 
    print "Enter name> "; 

    $dbh->disconnect; 

的Perl也有EOF風格多行註釋;你可以像這樣的長查詢:

my $query = <<'END_QUERY'; 
${SQLPLUS_SETTINGS} 
select foo||'|'||bar ||'|'|| xyz from temp where dfg='some'; 
exit; 
END_QUERY 
4

建議使用DBI好,絕對是正確的方式做的事情,如果你想對數據庫的Perl腳本編程。

然而,回答您的具體問題,如果你特別希望腳本SQL * Plus中,語法與Perl腳本來做到這一點是非常相似的外殼版本

my $connect_string = 'scott/[email protected]'; 
my $sqlplus_settings = ''; 
my $result = qx { sqlplus $connect_string <<EOF 
$sqlplus_settings 
select 1 from dual; 
exit; 
EOF 
}; 
print $result; 

qx操作我用在那裏,只是一個反引號的politer形式,大括號分隔的塊中的所有內容都由子shell運行,並且輸出返回到賦值。 Perl中的變量通常不是上層的。

+0

我也想寫一個shell腳本並返回quesry輸出結果,我想調用perl script.is中的那個shell腳本也是可能的? – Vijay 2009-11-13 09:38:40

+2

確定 - 反引號或qx()中的任何內容都將作爲子外殼運行,並且輸出的捕獲類似。再一次,我不認爲這是構建perl程序的非常好的方式。 – cms 2009-11-13 10:47:15

+0

這是qx引用機制的神話般的用法,並且在一次性腳本方案中,這可能是一個不錯的方法。 – 2009-11-13 16:55:09

1

幾件事情:

  • DBI絕對是最好的一段路要走。但是,請注意我之前對Oracle問題的回答,這可能與「仍然」有關:How can I use a database server from a Perl CGI script?

  • 如果SQL太長,SQL * Plus會引發錯誤。它有一個固定的行長度緩衝區(我不記得它是什麼,但我認爲它與Oracle 8在2000字節以下)。可能有一種解決方法(分割線路配置設置?),但我發現切換到DBI是這個原因和其他原因的最佳解決方案。

警告:我所有的上述信息基於Oracle 8

/I3az/

1

此類型的任何問題應以「我不能使用DBI因爲被開頭... 「因爲你真的想盡可能使用DBI。你可能有充分的理由不使用它,但也許,我們可以告訴你爲什麼你的理由不是很好,以及如何處理它。也就是說,這裏有一種方法可以使用fork和filehandles來完成你所要求的操作,並且一次獲得一行代碼(警告:如果你對這樣的進程打印太多,可能因爲緩衝區問題而阻塞):

use strict; 
use warnings; 

pipe(my($p_rdr, $c_wtr)) or die "Err: $!"; 
pipe(my($c_rdr, $p_wtr)) or die "Err: $!"; 
my $pid = fork; 
die "Could not fork: $!" unless defined $pid; 
unless ($pid) { 
    close $p_rdr; 
    close $p_wtr; 
    open(STDOUT, ">&=", $c_wtr) or die "dup: $!"; 
    open(STDIN, "<&=", $c_rdr) or die "dup: $!"; 
    print "Exec sqlplus\n"; 
    exec qw(sqlplus user/[email protected]); 
    die "Could not exec: $!"; 
} 
close $c_wtr; 
close $c_rdr; 
print "Print sql\n"; 
print $p_wtr "select * from table_name where col1 = 'something';\n"; 
print "Close fh\n"; 
close $p_wtr; 

print "Read results\n"; 
while (<$p_rdr>) { 
    print "O: $_"; 
} 
close $p_rdr;