2009-11-13 7 views
5

J'essaie de me connecter à une table en utilisant SQL*Plus et d'extraire les données dans un script Perl et de stocker cette sortie dans une variable Perl.SQL * Plus dans le script Perl

Dans un script shell que je ferais ceci:

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

Mais comment puis-je faire en Perl?

Répondre

10

Extrayez le module DBI. En fait, il y a tout un site Web qui s'y consacre: dbi.perl.org. En outre, consultez the CPAN module reference for DBI.

Voici un exemple de code, directement à partir 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 a aussi ce style EOF multiligne commentaire; vous pouvez faire une requête longue comme ceci:

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

Les conseils à utiliser DBI est bon, et sans aucun doute le droit façon de faire les choses, si vous êtes désireux de programmer des scripts Perl des bases de données.

Cependant, pour répondre à votre question précise, si vous voulez spécifiquement vers un script SQL * Plus, la syntaxe de le faire avec un script Perl est assez similaire à la version shell

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; 

L'opérateur qx J'utilise là, est juste une forme de polarité de backtick, tout dans le bloc délimité par accolade est exécuté par un sous-shell, et la sortie retournée à l'affectation. Les variables ne sont généralement pas en majuscules en Perl.

+0

Je pense aussi à écrire un script shell et retourner le résultat de sortie de quesry et je veux appeler ce script shell dans le script perl.est-ce aussi possible? – Vijay

+2

sûr - tout ce qui est à l'intérieur des guillemets ou qx() sera exécuté comme un sous-shell et la sortie sera capturée de la même manière. Encore une fois, je ne pense pas que ce soit un très bon moyen de structurer un programme Perl. – cms

+0

Ceci est une utilisation fabuleuse du mécanisme de quotation qx, et dans des scénarios de script uniques, cela pourrait être une bonne façon de procéder. –

1

Quelques choses:

  • DBI est sans aucun doute la meilleure façon d'aller. Cependant, veuillez noter une réponse précédente que j'ai donnée à une question d'Oracle qui est peut-être "encore" pertinente: How can I use a database server from a Perl CGI script?

  • SQL * Plus génère une erreur si votre SQL était trop long. Il a un tampon de longueur de ligne fixe (je ne me souviens pas de ce que c'était mais je pense qu'il était inférieur à 2000 caractères avec Oracle 8). Il y a peut-être une solution de contournement (le fractionnement des lignes, des paramètres de configuration?), Mais j'ai trouvé que passer à DBI était la meilleure solution pour cette raison et d'autres.

caveat: Toutes mes informations ci-dessus sont basées sur Oracle 8.

/I3az/

1

Toute question de ce type doit être précédé de « Je ne peux pas utiliser DBI parce que ... "Parce que vous voulez vraiment utiliser DBI si possible. Vous pourriez avoir de bonnes raisons de ne pas l'utiliser, mais peut-être, nous pouvons vous dire pourquoi vos raisons ne sont pas très bonnes et que faire à ce sujet. Cela dit, voici une façon de faire ce que vous avez demandé, en utilisant fork et filehandles, et en obtenant une sortie ligne par ligne (avertissement: si vous imprimez trop à un processus comme celui-ci, il peut bloquer en raison des problèmes de buffer):

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; 
Questions connexes