RPGLE Dynamic SQL с предложением Select не работает

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

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

Вот определение 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         

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

Не уверен, что вы имеете в виду, покажите пример кода, и, возможно, кто-нибудь сможет вам это объяснить.

jmarkmurphy 30.05.2018 13:06
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
1
1 686
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Другие вопросы по теме