6

SQL * Plusを使用してテーブルに接続し、 Perlスクリプトでデータをフェッチし、その出力をPerl変数に格納しようとしています。

シェルスクリプトでは、次のようにします。

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

しかし、Perlでこれを行うにはどうすればよいですか?

4

4 に答える 4

10

DBIモジュールをチェックしてください。実際、それに専用のWebサイト全体があります:dbi.perl.org。また、DBIのCPANモジュールリファレンスも確認してください。

これは、グーグルの最初のDBIチュートリアルからのコード例です。

    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
于 2009-11-13T07:17:08.583 に答える
5

データベースに対してPerlスクリプトをプログラムしたい場合は、DBIを使用することをお勧めします。これは、間違いなく正しい方法です。

ただし、正確な質問に答えるために、SQL * Plusのスクリプトを具体的に作成する場合、Perlスクリプトでこれを行うための構文はシェルバージョンとかなり似ています。

my $connect_string = 'scott/tiger@test';
my $sqlplus_settings = '';
my $result = qx { sqlplus $connect_string <<EOF
$sqlplus_settings
select 1 from dual;
exit;
EOF
};
print $result;

私がそこで使用しているqx演算子は、単なるアクサングラーブ形式であり、中括弧で区切られたブロック内のすべてがサブシェルによって実行され、出力が割り当てに返されます。Perlでは、変数は通常大文字ではありません。

于 2009-11-13T08:51:14.493 に答える
1

いくつかのこと:

  • DBIは間違いなく最善の方法です。ただし、「まだ」関連している可能性のあるOr​​acleの質問に対する以前の回答に注意してください。PerlCGIスクリプトからデータベースサーバーを使用するにはどうすればよいですか。

  • SQLが長すぎる場合、SQL*Plusはエラーをスローします。固定行長のバッファがあります(それが何であったかは思い出せませんが、Oracle 8では2000文字未満だったと思います)。回避策(ラインアップの分割?構成設定?)があるかもしれませんが、これと他の理由でDBIへの切り替えが最善の解決策であることがわかりました。

警告:上記の私の情報はすべてOracle8に基づいています。

/ I3az /

于 2009-11-13T10:00:17.577 に答える
1

このタイプの質問には、「DBIを使用できないため...」という前に付ける必要があります。可能な限りDBIを使用したいからです。あなたはそれを使わない正当な理由があるかもしれません、しかし多分、あなたの理由があまり良くない理由とそれについて何をすべきかをあなたに話すことができます。そうは言っても、フォークとファイルハンドルを使用して、一度に1行ずつ出力を取得することで、要求したことを実行する1つの方法があります(警告:このようなプロセスに印刷しすぎると、バッファーの問題が原因でブロックされる可能性があります):

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/passwd@dbname);
  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;
于 2009-11-13T23:43:03.573 に答える