О пользе метаданных в простых задачах

Понадобилось увеличить размер текстового поля FIELD_NAM таблицы TABLE_NAM в базе данных (БД) Firebird с m до n байт. Это элементарно выполняется с помощью SQL-команды ALTER TABLE TABLE_NAM ALTER FIELD_NAM TYPE Char(n). На содержимое записей это не влияет. Проверка менеджером IBExpert показывает, что длина поля становится равной m. Почему же при чтении размера этого поля запросом SELECT CHARACTER_LENGTH (FIELD_NAM) AS LN FROM TABLE_NAM по-прежнему получается, что LN=m?

Дело в том, что ваша СУБД уже изначально увеличила все записи в этом поле до m, добавив пустые символы (пробелы). После увеличения максимального размера поля записи остались прежними, и длина их не изменилась, т.е. так и осталась равной m. Причём для всех непустых записей в этом поле. Применение встроенной функции CHARACTER_LENGTH к символьному полю возвращает не длину поля, а длину записи в том поле, на которой стоит курсор таблицы. Это плохо и чревато появлением исключительных ситуаций в средах быстрого программирования, если некоторые свойства компонент, работающих с вашим полем, до их использования не перестроить на новую длину поля. Чтобы предотвратить появление исключений, нужно узнать истинную длину поля. Сделать это можно только обратившись к метаданным БД – данным о данных. В описанном случае нужно использовать следующий запрос:

SELECT RDB$CHARACTER_LENGTH AS LN FROM RDB$FIELDS

WHERE RDB$FIELD_NAME=(SELECT RDB$FIELD_SOURCE FROM

RDB$RELATION_FIELDS WHERE RDB$FIELD_NAME='FIELD_NAM'

AND RDB$RELATION_NAME='TABLE_NAM')

После открытия запроса читают истинную длину поля TABLE_NAM, как возвращаемое значение LN.

Есть и другой способ, но очень некрасивый, да и медленный: сразу после изменения длины поля с помощью обычных SQL-запросов прочитать, удалить и восстановить записи увеличенного поля. В этом случае СУБД автоматически дополнит размеры записей до n, и функция CHARACTER_LENGTH вернёт n. Короче, не факт, что не умея работать с метаданными, обойдётесь без «быдлокода».

Версия для печатиВерсия для печати

Рубрики: 

  • 1
  • 2
  • 3
  • 4
  • 5
Всего голосов: 0
Заметили ошибку? Выделите ее мышкой и нажмите Ctrl+Enter!

Комментарии

Аватар пользователя Al

Не въехал, зачем это надо, но разве вот это не даёт длину нужного поля?

SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'MYTABLE1' AND COLUMN_NAME = 'MYCOLUMN1'

Аватар пользователя mike

Разве вот это не даёт длину нужного поля?

Гхм. INFORMATION_SCHEMA? PostgreSQL,SQLServer and now MySQL have it. Firebird, о которой шла речь,  doesn't have it... :(
Аватар пользователя Al

А, ну ясно. Я имел в виду MS SQL.