我有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;
我把所有申报单都放在最前面。它们是不可执行的,不需要重复调用,因为它们完全被注释掉了,并且在程序中没有生成任何代码。在游标中使用动态准备语句的顺序是:
- 构建语句
- 准备报表
- 打开光标
- 从循环中的光标获取
- 关闭光标
关于执行的几个注意事项:
- 没有执行,打开光标会执行
- 使用声明游标的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;