Типы данных. Что нужно помнить
Эта глава может показаться абсолютно тривиальной. В ней не описываются никакие «хитрые» или супер эффективные методы кодирования. Это – просто напоминание о некоторых базовых основах программирования на ABL. К сожалению, порой даже опытные разработчики испытывают определенные трудности с основами…
Строки
Размер данных типа CHARACTER ограничен 32 K (размер записи во временной таблице или БД также ограничен 32K). Это может вызывать проблемы при хранении и обработке больших объемов информации.
Для хранения больших объемов данных в базе данных или временной таблице имеются типы данных CLOB (Character Large OBject) и BLOB (Binary Large OBject), при этом в записи хранится только указатель на область хранения данных. Для работы с CLOB и BLOB полями в программе ABL используются переменные типа LONGCHAR и MEMPTR соответственно. Эти типы могут быть использованы, например, при работе с большими XML-файлами или изображениями.
Рассмотрим небольшой пример. Неопределенное значение (?) в строковых операциях может быть корректно обработано с помощью функции SUBSTITUTE, например, при формировании сообщения об ошибке (Программа 1).
Программа 1. Неопределенное значение в строках
DEFINE VARIABLE a AS CHARACTER NO-UNDO. DEFINE VARIABLE b AS CHARACTER NO-UNDO. DEFINE VARIABLE c AS CHARACTER NO-UNDO. b = ?. a = "contract " + b + "does not exist". c = SUBSTITUTE("contract &1 does not exist",b). MESSAGE a VIEW-AS ALERT-BOX INFO BUTTONS OK. MESSAGE c VIEW-AS ALERT-BOX INFO BUTTONS OK.
Особенности функции SUBSTITUTE:
- Исходная строка должна содержать аргументы вида &n, где n – целое число от 1 до 9.
- Если аргумент имеет неопределенное значение, функция подставляет символ “?”.
- Аргумент можно использовать несколько раз: “When I say &1, I mean &1!”.
- Что бы включить символ ‘&’ в исходную строку, нужно поставить 2 амперсанда.
- Если Вы указали параметр замены в исходной строке, но не предоставили соответствующий аргумент, то параметр заменяется пустой строкой.
- Если после амперсанда стоит не цифра, произойдет ошибка времени выполнения.
Для включения специальных символов ( “ ‘ ~ \ { ) в строку, всегда используйте escape-символ ~. Не используйте \, это делает код платформо-зависимым (в Windows \ является не escape-символом, а разделителем в файловых путях).
При сравнении строк концевые пробелы не учитываются, выражение “A” = “A “ имеет значение TRUE.
Функция ENTRY может вызвать ошибку, если требуемый элемент выходит за границы списка. Безопаснее писать c = ENTRY(3, cList + “,,”).
Конечно, можно проверить количество элементов в списке с помощью функции NUM-ENTRIES и обработать возможную проблему, но добавление пустых элементов в конец списка эффективнее.
Следует помнить, что ENTRY и SUBSTRING это не только функции, но и операторы. Сравните:
c = ENTRY(3, cList + “,,”) и ENTRY(3, cList) = “My text”.
Вторая конструкция опасна, если список не содержит третьего элемента (хотя бы пустого) – произойдет ошибка. Здесь простого и эффективного решения не существует – если проблема возможна, следует проверять длину списка и обрабатывать ошибку.
Не используйте case-sensitive поля и переменные – за исключением тех случаев, когда это абсолютно необходимо. Это может привести к неожиданным результатам при сравнении, а также, если такое поле является индексным, приведет к увеличению пространства, занимаемого индексом.
В операции BEGINS концевые пробелы учитываются (в отличие от сравнения). Если во втором выражении указать пустую строку, операция возвращает TRUE: ‘a’ BEGINS ”.
При использовании BEGINS для выборки по индексному полю в условии WHERE индекс будет использован, в отличие от операции MATCHES.
Для использования в операции MATCHES шаблонов как символов, используйте специальный символ ‘~’: DISPLAY ‘*s.p’ MATCHES ‘~*s~.p’.
Для проверки принадлежности значения переменной некоторому списку следует использовать функции INDEX, LOOKUP или CAN-DO вместо серии проверок связанных условием OR. Это улучшает производительность и уменьшает объем r-кода. К сожалению, использование этих функций в условии WHERE не позволяет использовать индексы.
Даты
В OpenEdge дата хранится в виде целого числа, и представляет собой количество дней от некоторой начальной даты. В качестве начальной даты (DATE(0)) выбрано 31 декабря 4714 года до н.э. Диапазон допустимых дат составляет от 1 января 32768 года до н.э. и до 31 декабря 32767 года. Как можно увидеть, диапазон симметричен относительно начала эры, а не относительно нулевой даты. Таким образом, диапазон целых чисел, представляющих дату, составляет от -10247087 до 13689326.
- Если дата задана константой типа DATE, то формат даты всегда фиксирован mm/dd/yy. (Отметим, что при этом нельзя задать недействительные значения для месяца и дня. Нельзя также указать 0 для года).
- Если дата задана строкой, то она всегда зависит от формата сессии (SESSION:DATE-FORMAT). Формат даты для сессии задается стартовым параметром –d и может быть изменен в сессии программно.
- Если есть необходимость хранить дату в текстовом поле, лучше перевести ее в INTEGER.
Пример сохранения даты и извлечения даты – Программа 2.
Программа 2. Хранение даты в строке
DEFINE VARIABLE cDate AS CHARACTER NO-UNDO. cDate = STRING(INTEGER(DATE(01, 01, 1998))). MESSAGE TODAY - INTEGER (TODAY) + INTEGER (cDate) VIEW-AS ALERT-BOX INFO BUTTONS OK.