简体   繁体   English

Perl DBI通过创建VIEW修改Oracle数据库

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM