RPGLE Динамический SQL с предложением Select не работает - PullRequest
0 голосов
/ 30 мая 2018

После прочтения нескольких статей о SQLRPGLE, извлечения данных и их сохранения в массивах структур данных я пришел к динамическим операторам sql.

Это прекрасно работает, если я использую эти динамические поля для замены длямое состояние где.Но как я использую это?параметр в выбранной части или вообще в качестве замены полей базы данных, результат будет пустым.

Вот определение DDS и программа:

TESTPF

A**************************************************************************
A*
A*-------------------------------------------------------------------------
A*
A          R TESTPFR
A
A            FLD01          2S 0
A            FLD02         20A
A
A**************************************************************************

Я уже заполнил этот файл некоторыми фиктивными данными.Вот что внутри:

runqry () qtemp / 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 

А это программа:

TST001I

 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********************************************************************************************** 

Это вывод:

DSPLY  Text 01
DSPLY  Text 02
DSPLY         
DSPLY         
DSPLY         

Может кто-нибудь мне помочь и объяснить, почему это так?

1 Ответ

0 голосов
/ 30 мая 2018

При использовании подготовленного оператора вы можете использовать ? в качестве маркера параметра везде, где вы можете использовать переменную хоста в статическом операторе.Из ваших четырех подготовленных утверждений первые 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 в источнике.

Как правило, я хотел бы поместить свои объявления SQL в заголовок программы сразу после оператора SET OPTION, который должен быть первым SQL, встроенным в программу.Это где я помещаю объявления, когда я использую подготовленные заявления.Я также объявляю имя заявления, хотя это не является строго необходимым.Однако для этого есть небольшая хитрость, которая существует при использовании статического SQL с локальными переменными хоста.Чтобы справиться с этим, я объявляю статические курсоры немного по-другому при использовании подпроцедур.Прекомпилятор SQL распознает, что в подпроцедурах используются переменные локальной области видимости, поэтому, если вы объявляете статический курсор с переменными хоста локальной области действия, переменные хоста и объявление курсора должны находиться в одной области видимости.Это означает, что я должен объявить свои статические курсоры в той же подпроцедуре, что и open.Я по-прежнему объявляю курсор вверх около операторов RPGLE dcl-, чтобы сохранить объявления вместе.

...