我正在尝试使用SQL*Plus连接到表,并在Perl脚本中获取数据并将该输出存储在Perl变量中。
在shell脚本中我会这样做:
SQL_RESULT=`sqlplus -s ${CONNECT_STRING} << EOF
${SQLPLUS_SETTINGS}
select foo||'|'||bar ||'|'|| xyz from temp where dfg='some';
exit;
EOF`
但是我怎么能在Perl中做到这一点?
答案 0 :(得分: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
答案 1 :(得分:4)
如果您想要针对数据库编写Perl脚本,那么使用DBI的建议是好的,而且肯定是正确的方式。
但是,要回答您的确切问题,如果您特别想要编写SQL * Plus脚本,使用Perl脚本执行此操作的语法与shell版本非常相似
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
运算符只是一种反引号的politer形式,大括号分隔块中的所有内容都由子shell运行,输出返回到赋值。在Perl中,变量通常不是大写的。
答案 2 :(得分:1)
有几件事:
DBI绝对是最好的选择。但请注意我之前给出的Oracle问题的答案,该问题可能“仍然”相关:How can I use a database server from a Perl CGI script?
如果SQL太长,SQL * Plus会抛出错误。它有一个固定的行长度缓冲区(我不记得它是什么,但我认为它低于2000字符与Oracle 8)。可能有一个解决方法(拆分线路?配置设置?)但我发现切换到DBI是出于这个原因和其他原因的最佳解决方案。
警告:我上面的所有信息都基于Oracle 8。
/ I3az /
答案 3 :(得分:1)
任何此类问题都应以“我不能使用DBI,因为......”为前提,因为如果可能的话,你真的想要使用DBI。您可能有充分的理由不使用它,但也许,我们可以告诉您为什么您的理由不是很好以及如何处理它。话虽这么说,这是一种方法来做你所要求的,使用fork和filehandles,并一次输出一行(警告:如果你打印太多这样的过程,它可能会因缓冲区问题而阻塞):< / p>
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;