2009-11-13 15 views
5

Próbuję połączyć się z tabelą przy użyciu SQL*Plus i pobrać dane ze skryptu Perl i zapisać dane wyjściowe w zmiennej Perl.SQL * Plus wewnątrz skryptu Perla

W skrypcie powłoki chciałbym to zrobić:

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

Ale w jaki sposób można zrobić to w Perl?

Odpowiedz

10

Sprawdź moduł DBI. W rzeczywistości jest cała strona poświęcona temu: dbi.perl.org. Sprawdź także the CPAN module reference for DBI.

Oto przykład kodu, prosto z 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 posiada również, że komentarz styl multilinii EOF; można zrobić długi kwerendy tak:

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

Porady używać DBI jest dobry, a na pewno droga prawo robić rzeczy, jeśli chce programować skrypty Perl przeciwko baz danych.

Jednak, aby odpowiedzieć na dokładne pytanie, jeśli konkretnie chcą skrypt SQL * Plus, składnia to zrobić ze skryptu Perl jest dość podobna do wersji powłoki

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; 

Operator qx używam tam, jest tylko formą backendu dla politer, wszystko wewnątrz bloku ograniczonego klamrami jest uruchamiane przez podpowłokę, a wynik jest zwracany do przypisania. Zmienne nie są zwykle pisane dużymi literami w Perlu.

+0

Zastanawiam się również nad napisaniem skryptu powłoki i zwróceniem wyniku zapytania i chcę wywołać ten skrypt powłoki wewnątrz skryptu perl.is który jest również możliwy? – Vijay

+2

na pewno - wszystko w backtickach lub qx() będzie uruchamiane jako podsieć, a wyjście wychwycone w podobny sposób. Po raz kolejny nie sądzę, że jest to bardzo dobry sposób na zorganizowanie programu perl. – cms

+0

To jest wspaniałe wykorzystanie mechanizmu cytowania qx, a w jednorazowych scenariuszach skryptów może to być przyjemny sposób. –

1

Kilka rzeczy:

  • DBI jest zdecydowanie najlepszym sposobem, aby przejść. Należy jednak zauważyć, że poprzednia odpowiedź podałem na pytanie Oracle, które może "nadal" dotyczyć: How can I use a database server from a Perl CGI script?

  • SQL * Plus zgłasza błąd, jeśli twój SQL był zbyt długi. Ma stały bufor długości linii (nie pamiętam, co to było, ale myślę, że był poniżej 2000 znaków w Oracle 8). Być może obejście (podział linii? Ustawienia konfiguracyjne?), Ale znalazłem przejście do DBI najlepszym rozwiązaniem dla tego i innych powodów.

Zastrzeżenie: Wszystkie moje informacje powyżej jest oparty na Oracle 8.

/I3az/

1

Wszelkie pytania tego typu powinny być poprzedzone „Nie mogę używać DBI ponieważ ... "Ponieważ naprawdę chcesz korzystać z DBI, jeśli w ogóle jest to możliwe. Możesz mieć dobry powód, aby go nie używać, ale być może, możemy powiedzieć, dlaczego twoje powody nie są zbyt dobre i co z tym zrobić. Biorąc to pod uwagę, oto jeden ze sposobów, aby wykonać to, o co prosiłeś, używając uchwytów fork i file, a także uzyskać wydruk po jednej linii naraz (ostrzeżenie: jeśli za dużo wydrukujesz taki proces, może on zostać zablokowany z powodu problemów z buforem):

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; 
Powiązane problemy