Пусть SQL UPDATE выдает сообщение об ошибке при блокировке записи, как это делает нативный IO
Я несколько новичок в IBM i, и я пришел из Java / C# фона. Поэтому, если я использую неправильный жаргон, поправьте меня. В настоящее время мы работаем на IBM i 7.1 и в следующем году перейдем на 7.3.
Мне было поручено обновить записи в файле. Я написал две программы RPGLE, которые делают то же самое.
Собственный ввод / вывод:
**free
dcl-f table1 usage(*update) keyed;
setll ('001': 'Y') table1;
reade ('001': 'Y') table1;
dow not %eof(table1);
letter = 'X';
update table1;
reade ('001': 'Y') table1;
enddo;
*inlr = *ON;
return;
Встроенный SQL:
**free
exec sql UPDATE table1
SET letter = 'X'
WHERE GroupCode = '001' AND Newbie = 'Y';
*inlr = *ON;
return;
На мой взгляд, это один из случаев, когда SQL обладает мощным преимуществом по сравнению с собственным вводом-выводом и тем, насколько он лаконичен.
Вот моя проблема. Моя компания полагается на сообщения CPF. Мы, как и многие компании, не идеальны и имеем устаревший код. Это довольно много, и иногда мы получаем блокировки записи. Когда это происходит, в систему отправляется сообщение об ошибке, и оно ждет, пока кто-нибудь войдет в систему и ответит на него.
Это приводит к обращению в нашу внутреннюю поддержку и, как правило, к тому времени, когда кто-то добирается до нее, программа, которая заблокировала файл, завершается, и нам просто нужно ответить R, чтобы повторить попытку, и обновление продолжается с того места, где оно было прервано. Этого не происходит достаточно часто, чтобы мы могли потратить время на исправление процесса планирования и всех программ из блокировок записей, но достаточно часто, чтобы отсутствие этой возможности причиняло нам много боли.
При собственном вводе / выводе эти сообщения выбрасываются. При использовании встроенного SQL переменные SQLSTATE и SQLCODE устанавливаются, и программа продолжает работу, не отправляя никаких сообщений в систему. Я мог бы проверить эту переменную, написать собственное сообщение и отправить сообщение в систему, если что-то пойдет не так. Тем не мение; это не идеально. Если я вручную дам возможность повторить попытку, я не смогу возобновить обновление с того места, где оно было прервано. Я должен был бы выполнить весь оператор обновления снова.
Я рассмотрел параметры компилятора, параметры управления, параметры SQL и команды SQL, и ни одна из них, которую я видел, не дала мне той возможности, которую я искал.
Короче говоря, я хотел бы знать, есть ли способ заставить встроенный SQL вести себя как собственный ввод-вывод при неконтролируемом сообщении об ошибке?
5 ответов
Если вы ищете решение, полностью изменяющее подход, может быть много способов. Выбор только одного конкретного пути (использование только нативного или только sql и т. Д.) Сужает варианты.
Я попытался посмотреть на разные ответы выше, вот моя точка зрения
- с подходом danny117, если нет зависимости от "времени", когда файловое поле "буква" может быть обновлено до "x", тогда имеется обновление sql внутри "монитора" и позволяет всей программе запускать несколько расписаний с фильтром на букву ='х' может быть вариант
- для подхода jmarkmurphy, но где ожидание зависит от атрибута файла и может иметь проблемы, если файл будет заблокирован на более длительное время снаружи.
- поскольку даже вариант Чарльза также не помогает при случайной блокировке и отпускании
- Я думал о другом варианте, если обновление может выполняться быстрее, чем время, когда другая программа заблокирует файл. "выделить" файл исключительно для этого обновления и выпустить его после успешного обновления. во время выполнения цикла выполните шаг с задержкой, пока не получите эксклюзивную блокировку файла, затем обновите.
Лучшее решение - поймать ошибку блокировки записи и автоматически повторить операцию обновления базы данных до тех пор, пока не будет снята блокировка, или отключиться через определенный интервал времени ожидания. Это может быть легко реализовано либо с помощью встроенного ввода-вывода, либо с помощью SQL, что должно сократить значительный процент инцидентов поддержки.
Я вижу это в дикой природе все время. Не используя оптимистичный код. Если вы потерпите неудачу, возможно, оптимистическое кодирование обойдется даже при использовании устаревших программ.
Там все еще есть, как мне сделать повтор, когда строка заблокирована. Олдтаймеры, которые вызывали проблему с устаревшими методами кодирования, блокировали бы процесс сообщением, потому что то, что они делают, они пишут код, который зависит от вмешательства человека. Теперь все остальное в очереди заблокировано, и больше вещей не будет работать, ожидая, пока оператор ответит на сообщение.
Современная программа сможет перепланировать себя в будущем, когда она потерпит неудачу. Возможно отправьте электронное письмо, когда процесс перенесется. Похоже, что в будущем будет запущен.
exec sql UPDATE table1
SET letter = 'X'
WHERE GroupCode = '001' AND Newbie = 'Y'
and letter <> 'X'; /* and letter <> 'X' is the optimistic part */
*inlr = *ON;
return;
if calledpgm failed then reschedule to run in the future send an email to support if desired.
Короче... нет.
SQL - это другая парадигма. Обработка ошибок SQL в DB2 for i работает так же, как обработка ошибок в SQL на любом другом языке...
Вы, вероятно, хотите запустить свой UPDATE
под контролем обязательств. Затем проверьте sqlstate. Если не было ошибки, COMMIT
перевод.
Иначе, ROLLBACK
транзакции, и отобразите ваше сообщение. На этом этапе возможность повторить цикл и повторить SQL UPDATE
,
издательским
И после того, как вы добавите все это, ваша версия SQL выглядит не так лаконично, не так ли? Черт возьми, RPG-версия может быть урезана до 5 или 6 строк... если вы хотите пойти в старую школу и использовать исходный первичный файл. Не то, чтобы я рекомендовал это сейчас.
Тесная интеграция RPG с БД многое для вас делает. SQL великолепен, и я все время им пользуюсь, но иногда немного больше контроля. К счастью, в IBM i есть альтернатива SQL.
В этом случае вы можете просто:
**free
dou sqlstate = '00000' or sqlstate = '02000';
exec sql UPDATE table1
SET letter = 'X'
WHERE GroupCode = '001'
AND Newbie = 'Y'
and letter <> 'X';
enddo;
*inlr = *ON;
return;
Блокировка будет все еще вызывать ожидание в SQL в течение 60 секунд или около того, в зависимости от WAITRCD
атрибут файла или переопределение, так что это не вызовет слишком большой проблемы.
Вы также можете создать процедуру для отправки сообщения в случае блокировки и реализовать это как:
**free
dou sqlstate = '00000' or sqlstate = '02000';
exec sql UPDATE table1
SET letter = 'X'
WHERE GroupCode = '001'
AND Newbie = 'Y'
and letter <> 'X';
if sqlstate = '57033';
SendSqlMsg('SQL0913');
endif;
enddo;
*inlr = *ON;
return;
Вы могли бы даже заставить эту процедуру отправить запрос и получить ответ. Затем обработайте ответ по мере необходимости. Я оставлю это как упражнение для вас.