在阅读了几篇关于SQLRPGLE的文章并检索数据并将它们存储在数据结构数组中之后,我想出了动态的sql语句。
只要我在where where条件下使用这些动态替换字段,这样就可以正常工作。但是,正如我使用这些?选择部分中的参数,或者通常作为数据库字段的替换,结果为空。
这是DDS定义和程序:
TESTPF
FLD01 FLD02
000001 1 Text 01
000002 2 Text 02
000003 3 Text 03
000004 4 Text 04
000005 5 Text 05
000006 6 Text 06
000007 7 Text 07
000008 8 Text 08
000009 9 Text 09
000010 10 Text 10
我已经用一些虚拟数据填充了这个文件。这里面是什么:
runqry()qtemp / testpf
D**********************************************************************************************
D* Standalone Fields
D*---------------------------------------------------------------------------------------------
D stm s 500a inz(*blanks)
D fieldName01 s 10a inz(*blanks)
D fieldName02 s 10a inz(*blanks)
D fieldName03 s 2a inz(*blanks)
D text s 20a inz(*blanks)
D
C**********************************************************************************************
C* M A I N P R O G R A M M
C**********************************************************************************************
stm = 'SELECT fld02 FROM testpf WHERE fld01 = 1';
exec sql prepare s1 from :stm;
exec sql declare c1 cursor for s1;
exec sql open c1;
exec sql fetch c1 into :text;
exec sql close c1;
dsply text; // Prints 'Text 01'
text = *blanks;
stm = 'SELECT fld02 FROM testpf WHERE fld01 = ?';
exec sql prepare s2 from :stm;
exec sql declare c2 cursor for s2;
fieldName03 = '2';
exec sql open c2 using :fieldName03;
exec sql fetch c2 into :text;
exec sql close c2;
dsply text; // Prints 'Text 02'
text = *blanks;
stm = 'SELECT ? FROM testpf WHERE fld01 = 3';
exec sql prepare s3 from :stm;
exec sql declare c3 cursor for s3;
fieldName01 = 'FLD02';
exec sql open c3 using :fieldName01;
exec sql fetch c3 into :text;
exec sql close c3;
dsply text; // Prints ' '
text = *blanks;
stm = 'SELECT ? FROM testpf WHERE ? = ?';
exec sql prepare s4 from :stm;
exec sql declare c4 cursor for s4;
fieldName01 = 'FLD02';
fieldName02 = 'FLD01';
fieldName03 = '4';
exec sql open c4 using :fieldName01, :fieldName02, :fieldName03;
exec sql fetch c4 into :text;
exec sql close c4;
dsply text; // Prints ' '
text = *blanks;
*inlr = *on;
C**********************************************************************************************
这是该计划:
TST001I
DSPLY Text 01
DSPLY Text 02
DSPLY
DSPLY
DSPLY
这是输出:
Сompletion with Tab
有人可以帮我解释为什么会这样吗?
答案 0 :(得分:3)
使用预准备语句时,只要在静态语句中使用主变量,就可以使用?
作为参数标记。在你的四个样本预备语句中,前三个应该有效,但第三个不会返回你所期望的,因为它相当于:
SELECT 'FLD02' FROM testpf WHERE fld01 = 3
我希望收到值'FLD02'
作为结果,而不是FLD02列中的值。这是因为?
不是字符串替换标记,而是参数字段标记。您无法使用它来选择列,但您可以使用它来提供比较值或输出常量。
第四个示例是有效的SQL,但它等同于:
SELECT 'FLD02' FROM testpf WHERE 'FLD01' = '4'
由于'FLD01'
不等于'4'
,因此不返回任何内容。
这样做的另一个结果是?
可用于为预准备语句提供数值。所以你可以这样做:
dcl-s seqno Packed(5:0);
exec sql declare c2 cursor for s2;
stm = 'SELECT fld02 FROM testpf WHERE fld01 = ?';
exec sql prepare s2 from :stm;
seqno = 2;
exec sql open c2 using :seqno;
另请注意,我将游标的声明删除到逻辑流之外的某处,因为声明不是可执行语句。我看到声明在子程序中的程序,该子程序在包含光标打开的单独子程序之前调用。这在语义上是不正确的。 DECLARE CURSOR
语句更准确地等同于RPGLE dcl-
语句。但是因为SQL预编译器线性处理源,很大程度上不考虑子例程或子过程,所以要求DECLARE CURSOR
在物理上位于源OPEN
之前。
一般来说,我喜欢在SET OPTION
语句之后立即将我的SQL声明放在程序的头部,该语句必须是程序中嵌入的第一个SQL。这是我在使用预准备语句时放置声明的地方。我也声明了声明名称,尽管这不是必须的。尽管如此,还是有一点问题,当使用静态SQL和本地范围的主机变量时就存在这种问题。为了解决这个问题,我在使用子程序时声明静态游标有点不同。 SQL预编译器识别出子过程使用本地范围的变量,因此如果要声明具有本地范围的主变量的静态游标,则主机变量和游标声明必须在同一范围内。这意味着我必须在与open相同的子过程中声明我的静态游标。我仍然将光标声明在RPGLE dcl-
语句附近,以便将声明保持在一起。