将主机结构数组转换为表

时间:2015-04-24 05:20:59

标签: c oracle oracle-pro-c

我正在尝试调整用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,无需遍历每条记录。

2 个答案:

答案 0 :(得分: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可以为null,您还应该考虑使用indicator variables。例如

       error_message = :ps_errors.s_err_msg INDICATOR :indicator_variable

答案 1 :(得分:0)

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

E.g:

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;