[英]Perl DBI modifying Oracle database by creating a VIEW
I wrote a Perl script to check the data in an Oracle database. 我编写了一个Perl脚本来检查Oracle数据库中的数据。 Because the query process is very complex I chose to create a VIEW in the middle.
因为查询过程非常复杂,所以我选择在中间创建一个VIEW。 Using this view the code could be largely simplified.
使用此视图,可以大大简化代码。
The Perl code run well when I used it to query the database starting from a file, like Perl mycode.pl file_a
. 当我使用Perl代码从文件(例如
Perl mycode.pl file_a
开始查询数据库时,Perl代码运行良好。 The Perl code reads lines from file_a
and creates/updates the view until the end of the input. Perl代码从
file_a
读取行,并创建/更新视图,直到输入结束。 The results I achieved are completely right. 我取得的结果是完全正确的。
The problem came when I simultaneously run 问题是我同时跑步时出现的
perl mycode.pl file_a
and 和
perl mycode.pl file_b
to access the same database. 访问相同的数据库。 According to my observation, the VIEW used by the first process will be modified by the second process.
根据我的观察,第一个进程使用的VIEW将被第二个进程修改。 These two processes were intertwined on the same view.
这两个过程在同一观点上交织在一起。
Is there any suggestion to make these two processes not conflict with one another? 是否有任何建议使这两个过程不相互冲突?
The Perl code for querying database is normally like this, but the details in each real query is more complex. 用于查询数据库的Perl代码通常是这样的,但是每个实际查询中的细节都更加复杂。
my ($gcsta,$gcsto,$cms) = @t; #(details of @t is read from a line in file a or b)
my $VIEWSS = 'CREATE OR REPLACE VIEW VIEWSS AS SELECT ID,GSTA,GSTO,GWTA FROM TABLEA WHERE GSTA='.$gcsta.' AND GSTO='.$gcsto.' AND CMS='.$cms;
my $querying = q{ SELECT COUNT(*) FROM VIEWSS WHERE VIEWSS.ID=1};
my $inner_sth = $dbh->prepare($VIEWSS);
my $inner_rv = $inner_sth->execute();
$inner_sth = $dbh->prepare($querying);
$inner_rv = $inner_sth->execute();
You must 你必须
Create the view only once, and use it everywhere 仅创建一次视图,并在任何地方使用
Use placeholders in your SQL statements, and pass the actual parameters with the call to execute
在SQL语句中使用占位符,并在调用时传递实际参数以
execute
Is this the full extent of your SQL? 这是您的SQL的全部范围吗? Probably not, but if so it really is fairly simple.
可能不是,但如果是这样,那确实很简单。
Take a look at this refactoring for some ideas. 看一下这种重构的一些想法。 Note that is uses a here document to express the SQL.
请注意,使用here文档来表示SQL。 The
END_SQL
marker for the end of the text must have no whitespace before or after it. 文本结尾的
END_SQL
标记之前或之后必须没有空格。
If your requirement is more complex than this then please describe it to us so that we can better help you 如果您的要求比这更复杂,请向我们描述,以便我们更好地为您提供帮助
my $stmt = $dbh->prepare(<<'END_SQL');
SELECT count(*)
FROM tablea
WHERE gsta = ? AND gsto = ? AND cms= ? AND id = 1
END_SQL
my $rv = $stmt->execute($gcsta, $gcsto, $cms);
If you must use a view then you should use placeholders in the CREATE VIEW
as before, and make every set of changes into a transaction so that other processes can't interfere. 如果必须使用视图,则应像以前一样在
CREATE VIEW
使用占位符,并对事务进行每组更改,以免其他进程干扰。 This involves disabling AutoCommit
when you create the database handle $dbh
and adding a call to $dbh->commit
when all the steps are complete 这涉及在创建数据库句柄
$dbh
时禁用AutoCommit
,并在所有步骤完成后添加对$dbh->commit
的调用
use strict;
use warnings;
use DBI;
my $dbh = DBI->connect('dbi:Oracle:mydbase', 'user', 'pass',
{ AutoCommit => 0, RaiseError => 1 } );
my $make_view = $dbh->prepare(<<'END_SQL');
CREATE OR REPLACE VIEW viewss AS
SELECT id, gsta, gsto, gwta
FROM tablea
WHERE gsta = ? AND gsto = ? AND cms= ? AND id = 1
END_SQL
my $get_count = $dbh->prepare(<<'END_SQL');
SELECT count(*)
FROM viewss
WHERE id = 1
END_SQL
while (<>) {
my ($gcsta, $gcsto, $cms) = split;
my $rv = $make_view->execute($gcsta, $gcsto, $cms);
$rv = $get_count->execute;
my ($count) = $get_count->fetchrow_array;
$dbh->commit;
}
Is the view going to be the same or different? 视图是相同还是不同?
If the views are all the same then create it only once, or check if it exists with the all_views table : http://docs.oracle.com/cd/B12037_01/server.101/b10755/statviews_1202.htm#i1593583 如果所有视图都相同,则仅创建一次,或者使用all_views表检查它是否存在: http ://docs.oracle.com/cd/B12037_01/server.101/b10755/statviews_1202.htm#i1593583
You can easily create a view including your pid with the $$ variable to be the pid, but it wont be unique across computers, oracle has also some unique ids, see http://docs.oracle.com/cd/B14117_01/server.101/b10759/functions150.htm , for example, the SESSIONID. 您可以轻松地创建一个视图,其中包含带有$变量作为pid的pid,但是在计算机之间将是唯一的,oracle也具有一些唯一的ID,请参见http://docs.oracle.com/cd/B14117_01/server .101 / b10759 / functions150.htm ,例如SESSIONID。
But do you really need to do this? 但是您真的需要这样做吗? why dont you prepare a statement and then execute it?
您为什么不准备一个语句然后执行呢? http://search.cpan.org/dist/DBI/DBI.pm#prepare
http://search.cpan.org/dist/DBI/DBI.pm#prepare
thanks, mike 谢谢,迈克
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.