as/4000中的sqlrpgle动态查询



我有employee1表,字段为student_id、name、marks和字段为name的表,假设name字段中存在NEHA,我有一个名称为NEHA的表。在name表标记中,id和subject字段就在那里。我想从标记>10的名称表(neha)中提取主题。我需要编写sqlrpgle程序,通过动态查询从employee1中获取名称,因为名称每次都在变化。我已经共享了代码。在这段代码中,每次从emoploye1中提取不同的名称,但这段代码的问题是无法从NEHA表中提取SUBJECT列。在调试中,它的主题="。但同样的查询在strsql.有人能提出任何解决方案吗?

D stmt1           s            500A   inz                                   
D subject         s             10A                                         
D @subject        s             10A                                         
D name            s             20A                                         
D @Name           s             20A                                         
D STUdent_ID      s             10P 0                                       
d marks           s             10P 2                                       
/Free                                                                      
EXEC Sql                                                                  
declare c1 scroll cursor  for                                            
select name,student_id,marks from employee1;                             
EXEC Sql                                                                  
open c1; 
EXEC Sql                                                              
 fetch first from c1 into :@name,:student_id,:marks;                  
dow  sqlcod=0;                                                       
stmt1='select subject from ' + %Trim(@name)+ ' where marks>10';    
EXEC Sql                                                     
declare c2 scroll cursor for                                
select subject from @name where marks>10;   
EXEC Sql                                                   
open c2;                                                  
EXEC sql                                                   
fetch first from c2 into :@SUBJECT;    
 If SQLCOD = 0;                                            
  dsply subject;           
 EndIf; 
EXEC Sql                    
 Prepare s2 from :stmt1;    
EXEC Sql                                                                       
execute s2;                                                                   
EXEC SQL                                                                       
 Fetch next from c1 into :name,:student_id,:marks;                             
EXEC SQL                                                                       
 Fetch next from c2 into :subject;                                                  
enddo;  
EXEC Sql                                                                       
 close c1;                                                                     
EXEC Sql                                                                       
 close c2;     
 *inlr = *on;                                                                  
/END-FREE                                                                    

因此,如果您有一个引用其他表名称的名称表,那么您的动态sql语句的顺序以及它们的调用方式就会出现问题。

exec sql
  declare C1 cursor for
    select name, student_id, marks from employee1;
exec sql
  declare S2 statement;
exec sql
  declare C2 cursor for S2;
exec sql
  open C1;
exec sql
  fetch first from C1 into :@name, :student_id, :marks;
dow sqlcode >= 0;
  stmt1 = 'select subject from ' + %Trim(@name)+ ' where marks>10';      
  exec sql
    prepare S2 from :stmt1;
  exec sql
    open C2;
  exec sql                                                   
    fetch first from c2 into :@SUBJECT;    
  if sqlcod = 0;                                            
    dsply subject;           
  endif;
  exec sql
    close C2;
  exec sql
    fetch next from C1 into :@name, :student_id, :marks;
enddo;
exec sql
  close C1;

我把所有申报单都放在最前面。它们是不可执行的,不需要重复调用,因为它们完全被注释掉了,并且在程序中没有生成任何代码。在游标中使用动态准备语句的顺序是:

  1. 构建语句
  2. 准备报表
  3. 打开光标
  4. 从循环中的光标获取
  5. 关闭光标

关于执行的几个注意事项:

  • 没有执行,打开光标会执行
  • 使用声明游标的for子句中的语句名称声明游标
  • 游标的声明永远不会改变

但是

与其将每个学生的主题(课程)数据分离到自己的表中,不如将它们放在一起,并在单个courses表中添加一个name列,以确定课程数据与哪个学生关联。而且,由于名称可以更改,因此最好使用student_id作为表之间的公共元素。

这里有一个更好的方法。我还没有规范化数据库,这是一个不适合SO的完整主题。但是,我已经将NEHA表重命名为courses,并将courses表中的name替换为student_id,这样你就可以遵循:

// Table formats
// EMPLOYEE1
//   student_id      Integer
//   name            Varchar(255)
//   marks           Integer
//
// COURSES
//   id              Integer
//   student_id      Integer
//   marks           Integer
//   subject         Varchar(255)
//   
dcl-ds employee_t    ExtName('EMPLOYEE1') Template;
end-ds;
dcl_ds courses       ExtName('COURSES') Template;
end-ds;
dcl-ds rec       Qualified;
  name           Like(employee_t.name);
  student_id     Like(employee_t.student_id);
  marks          Like(employee_t.marks);
  subject        Like(courses_t.subject);
endds;
C1_OpenCursor();
dow C1_FetchCursor(rec);
  dsply rec.subject;
enddo;
C1_CloseCursor();
// --------------------------------
// Open the cursor
// This includes the cursor declaration just in case
// I need to use a local variable such as a parameter
// in the SQL.
// --------------------------------
dcl-proc C1_OpenCursor;
  exec sql
    declare C1 cursor for
      select a.name, a.student_id, a.marks, b.subject
      from employee1 a
      join courses b on a.student_id = b.student_id
      where b.marks > 10;
  exec sql open C1;
  // Check SQLSTATE here
end-proc;
// --------------------------------
// Fetch a record from the cursor
// returns *On when a record is found
//   or *Off when no record is found.
// --------------------------------    
dcl-proc C1_FetchCursor;
  dcl-pi *n Ind;
    recout    LikeDs(rec);
  end-pi;
  exec sql
    fetch C1 into :recout;
  // Check SQLSTATE here for errors
  if sqlstate = '02000';  // record not found
    clear recout;
    return *Off;
  endif;
  return *On;
end-proc;
// --------------------------------
// Close the cursor
// --------------------------------
dcl-proc C1_CloseCursor;
  exec sql close C1;
end-proc;

相关内容

  • 没有找到相关文章

最新更新