3

我正在尝试调整一段用 Pro*C 编写的大型代码,特别是瓶颈循环和其中的UPDATE语句。通过“主机结构数组”for loop循环,该数组可能包含数千条有时数百万条记录,并且更新执行次数过多。更新可以在整个程序中更频繁地执行,但这需要对代码进行重大更改,我无权进行重大更改。

所以我有这样的东西

....
#define NULL_REF_NO   10
#define NULL_ERR      256
....
....
struct s_errors
{
  char s_ref_id        [NULL_REF_NO];
  char s_ref_seq_no    [NULL_REF_NO];
  char s_err_msg       [NULL_ERR];
}; 
....
....
struct s_errors *ps_errors = NULL;
....
....
/*The part below happens throughout the program to collect all errors*/
/*ls_ref_id, ls_ref_seq_no, and ls_err_msg are local variables of same data type. and i_curr_index is the array index variable*/

strcpy(ls_ref_id, ps_errors[i_curr_index].s_ref_id);
strcpy(ls_ref_seq_no, ps_errors[i_curr_index].s_ref_seq_no);
strcpy(ls_err_msg, ps_errors[i_curr_index].s_err_msg);

.....
/* At this point ps_error contains thousands or even millions of rows*/
/* The final part is to update all these rows back to the table like below*/
 /* pl_err_count is a Global var which keeps track of the total number of records in the host structure array*/

 int i_curr_index = 0;
 char l_ref_id        [NULL_REF_NO];
 char l_ref_seq_no    [NULL_REF_NO];
 char l_err_msg       [NULL_ERR];

 for(i_curr_index = 0; i_curr_index < pl_err_count; i_curr_index++)
 {
  strcpy(l_ref_id, ps_errors[i_curr_index].s_ref_id);
  strcpy(l_ref_seq_no, ps_errors[i_curr_index].s_ref_seq_no);
  strcpy(l_err_msg, ps_errors[i_curr_index].s_err_msg);

  EXEC SQL
   UPDATE some_table
   SET status       = 'E',
       error_message = :l_err_msg 
   WHERE ref_id = :l_ref_id
   AND ref_seq_no   = :l_ref_seq_no;

  if (SQL_ERROR_FOUND)
  {
      sprintf(err_data, "Updation failed with sql errors ");
      strcpy(table, "some_table");
      WRITE_ERROR(SQLCODE,function,"",err_data);
      return(FATAL);
  }
  }

瓶颈是上面的 for 循环(它是程序的最后一步),它循环太多次导致程序运行时间过长。我想知道是否有一种方法可以CAST将主机结构数组ps_errors转换为 Oracle 表类型,这样我就可以轻松地进行批量UPDATE操作,甚至可以MERGE使用一些并行 DML 进行操作,而无需遍历每条记录。

4

2 回答 2

0

从我在工作中看到的其他一些类似的代码推断,你可以做这样的事情而不是for循环:

EXEC SQL for :pl_err_count
UPDATE some_table
   SET status        = 'E',
       error_message = :ps_errors.s_err_msg 
 WHERE ref_id        = :ps_errors.s_ref_id
   AND ref_seq_no    = :ps_errors.s_ref_seq_no;

这可能依赖于添加到ps_errors空终止的内容。鉴于strcpy()在现有代码中的使用,而不是strncpy()(或类似的),我猜他们已经是。

如果s_err_msg可以为空,您还应该考虑使用指示变量。例如。

       error_message = :ps_errors.s_err_msg INDICATOR :indicator_variable
于 2015-04-25T10:01:43.437 回答
0

您可以使用数组更新http://docs.oracle.com/cd/B28359_01/appdev.111/b28427/pc_08arr.htm#i1879但您需要将结构数组更改ps_errors为数组结构

例如:

EXEC SQL
  UPDATE some_table
     SET status        = 'E',
         error_message = :ps_errors.s_err_msg 
   WHERE ref_id        = :ps_errors.s_ref_id
     AND ref_seq_no    = :ps_errors.s_ref_seq_no;
于 2015-08-25T15:30:28.147 回答