TL; DR:如何修改下面的queryOfQuery()
函数以使用OCI8 / Oracle后端?
在寻找与CFML's query of queries等效的PHP时,我遇到了this question,它指向a function Tom Muck had written:
function queryOfQuery($rs, // The recordset to query
$fields = "*", // optional comma-separated list of fields to return, or * for all fields
$distinct = false, // optional true for distinct records
$fieldToMatch = null, // optional database field name to match
$valueToMatch = null) { // optional value to match in the field, as a comma-separated list
$newRs = Array();
$row = Array();
$valueToMatch = explode(",",$valueToMatch);
$matched = true;
mysql_data_seek($rs, 0);
if($rs) {
while ($row_rs = mysql_fetch_assoc($rs)){
if($fields == "*") {
if($fieldToMatch != null) {
$matched = false;
if(is_integer(array_search($row_rs[$fieldToMatch],$valueToMatch))){
$matched = true;
}
}
if($matched) $row = $row_rs;
}else{
$fieldsArray=explode(",",$fields);
foreach($fields as $field) {
if($fieldToMatch != null) {
$matched = false;
if(is_integer(array_search($row_rs[$fieldToMatch],$valueToMatch))){
$matched = true;
}
}
if($matched) $row[$field] = $row_rs[$field];
}
}
if($matched)array_push($newRs, $row);
};
if($distinct) {
sort($newRs);
for($i = count($newRs)-1; $i > 0; $i--) {
if($newRs[$i] == $newRs[$i-1]) unset($newRs[$i]);
}
}
}
mysql_data_seek($rs, 0);
return $newRs;
}
我想调整此代码以适应我们的数据库环境(我们使用Oracle和OCI8 - 而不是MySQL,为其编写函数)。不幸的是,我新生的PHP技能让我不能胜任这项任务。具体来说,我可以看到mysql_data_seek()
和mysql_fetch_assoc()
可能是其OCI8对手替代的候选者。什么是插件的等价物?还有什么我需要调整的吗?
答案 0 :(得分:1)
修改函数以使用OCI是微不足道的,但遗憾的是,您无法重复从结果集中获取。
我已经发布了下面的完整功能,但只需要更改三行。我已经注释掉现有的行以显示更改的位置。
只需删除对mysql_data_seek()
的来电。第一次调用将结果集指针重置为第一条记录,以防任何已经执行过任何提取。这可确保“子查询”获取所有适用的记录。第二次调用再次重置指针,以确保函数执行后的进一步处理将从结果集的开头开始。
我查看了OCI8 function list,但看不到重置指针的等效内容。我认为你可以使用游标,但我不知道PL / SQL所以不能在那里给你任何帮助。
总而言之,您可以“查询查询”,但有两点需要注意:
function queryOfQuery($rs, // The recordset to query
$fields = "*", // optional comma-separated list of fields to return, or * for all fields
$distinct = false, // optional true for distinct records
$fieldToMatch = null, // optional database field name to match
$valueToMatch = null) { // optional value to match in the field, as a comma-separated list
$newRs = Array();
$row = Array();
$valueToMatch = explode(",",$valueToMatch);
$matched = true;
//mysql_data_seek($rs, 0);
if($rs) {
//while ($row_rs = mysql_fetch_assoc($rs)){
while ($row_rs = oci_fetch_assoc($rs)){
if($fields == "*") {
if($fieldToMatch != null) {
$matched = false;
if(is_integer(array_search($row_rs[$fieldToMatch],$valueToMatch))){
$matched = true;
}
}
if($matched) $row = $row_rs;
}else{
$fieldsArray=explode(",",$fields);
foreach($fields as $field) {
if($fieldToMatch != null) {
$matched = false;
if(is_integer(array_search($row_rs[$fieldToMatch],$valueToMatch))){
$matched = true;
}
}
if($matched) $row[$field] = $row_rs[$field];
}
}
if($matched)array_push($newRs, $row);
};
if($distinct) {
sort($newRs);
for($i = count($newRs)-1; $i > 0; $i--) {
if($newRs[$i] == $newRs[$i-1]) unset($newRs[$i]);
}
}
}
//mysql_data_seek($rs, 0);
return $newRs;
}
编辑: 我已经深入研究了这一点,我认为由于术语和方法之间的差异,这对CFML开发人员来说是误导性的PHP和CFML。 Tom Muck似乎误解了这些差异,因此无意中歪曲了他的功能如何运作。
阅读CFML help doc you linked后,我认为CFML 中的查询隐式将所有行提取到Web服务器内存中。这样就可以在不与数据库服务器通信的情况下再次“查询”结果集。
在PHP中,开发人员选择函数控制此行为(因此他/她做出了显式选择)。标准行为(简化为简洁):
通常,迭代地执行步骤3;一次从数据库中提取和处理一行(与Tom的函数完全相同)。但是也可以将整个结果集提取到Web服务器内存中,然后进行处理。对于OCI,这将是oci_fetch_all()
,它返回一个2D数组。这正是Tom误解PHP行为的地方。
这意味着原始函数不提供与CFML开发人员描述或预期相同的功能。要做到这一点,您需要将所有数据提取到一个数组中然后迭代它。最后,这取决于开发人员的偏好以及潜在的性能优化。你:
最后,除非您以非常大的规模运行Web应用程序,否则我会说性能差异可以忽略不计。
编辑2:
这个调整过的queryOfQuery函数没有绑定到任何特定的数据库;它遍历给定的数组(rs
),无论它是如何生成的:
function queryOfQuery(
$rs, // The recordset to query
$fields = "*", // optional comma-separated list of fields to return, or * for all fields
$distinct = false, // optional true for distinct records
$fieldToMatch = null, // optional database field name to match
$valueToMatch = null // optional unless $fieldToMatch is specified; value to match in the field, as a comma-separated list
) {
$newRs = Array();
$row = Array();
$valueToMatch = explode(",",$valueToMatch);
$matched = true;
if($rs) {
// $issue$ this loop over the results should be moved to lines 20 and 31
foreach($rs AS $row_rs){
if($fields == "*") {
if($fieldToMatch != null) {
$matched = false;
if(is_integer(array_search($row_rs[$fieldToMatch],$valueToMatch))){
$matched = true;
};
};
if($matched) $row = $row_rs;
}
else {
$fieldsArray=explode(",",$fields);
foreach($fieldsArray as $field) {
if($fieldToMatch != null) {
$matched = false;
if(is_integer(array_search($row_rs[$fieldToMatch],$valueToMatch))){
$matched = true;
};
};
if($matched) $row[$field] = $row_rs[$field];
};
};
if($matched)array_push($newRs, $row);
};
if($distinct) {
sort($newRs);
for($i = count($newRs)-1; $i > 0; $i--) {
if($newRs[$i] == $newRs[$i-1]) unset($newRs[$i]);
};
};
};
return $newRs;
};