Понадобилось увеличить размер текстового поля 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. Короче, не факт, что не умея работать с метаданными, обойдётесь без «быдлокода».
Комментарии
Не въехал, зачем это надо, но разве вот это не даёт длину нужного поля?
SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'MYTABLE1' AND COLUMN_NAME = 'MYCOLUMN1'
А, ну ясно. Я имел в виду MS SQL.