我正在编写一个脚本,它在几个不同的数据库中执行相同的合并语句。表名和列在我连接的每个模式中是相同的,但模式名称本身是不同的。我不想定义两个单独的查询,而是将一个合并语句定义为模式名称设置为“?”的字符串,然后在执行期间传入所需的模式名称:
my $hostgroup_merge = "MERGE INTO ?.HOSTGROUPS .... ";
然后是:
my $dev_schema = 'DEV';
my $prod_schema = 'PROD';
#do the merge in the dev schema
my $dbh = DBI->connect($dev_server,$user,$pass);
my $sth = $dbh->prepare($hostgroup_merge);
$sth->execute($dev_schema);
$sth->finish();
$dbh->disconnect;
#now do the same merge for the prod schema
$dbh = DBI->connect($prod_server,$user,$pass);
$sth = $dbh->prepare($hostgroup_merge);
$sth->execute($prod_schema);
$sth->finish();
$dbh->disconnect;
此操作因表名错误无效而失败:
DBD::Oracle::st execute failed: ORA-00903: invalid table name (DBD ERROR: error possibly near <*> indicator at char 19 in '
MERGE INTO :p1<*>.HOSTGROUPS ...
然而,它似乎正好接受绑定变量,因为它在查询之后将其吐出:
" with ParamValues: :p1='DEV']
我知道导致问题的绑定变量,因为当我定义单独的合并语句并对模式名称进行硬编码时,它们的工作正常。
由于唯一正在改变的是一开始的变量,我可能通过在字符串中定义语句的不变部分,然后连接其余部分来破解查询:
my $dev_merge = 'MERGE INTO ' . $dev_schema . $merge_statement;
然后只需运行prepare
,但有没有合法的方式通过查询传递名称?如果是这样,有人能指出这里出了什么问题吗?
答案 0 :(得分:2)
SELECT * FROM Table WHERE X = ?
相当于
SELECT * FROM Table WHERE X = 'DEV'
所以
MERGE INTO ?.HOSTGROUPS ....
相当于
MERGE INTO 'DEV'.HOSTGROUPS ...
,而你想要
MERGE INTO DEV.HOSTGROUPS ...
使用
"MERGE INTO ".$dbh->quote_identifier($schema).".HOSTGROUPS ..."