← Назад к вопросам

Как определить, есть ли колонка в таблице или нет?

1.3 Junior🔥 101 комментариев
#Запросы и оптимизация#Стандарты разработки

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Определение наличия колонки в таблице

Это типичная задача при работе с СУБД напрямую или при динамическом формировании SQL запросов. Подходы зависят от СУБД и контекста.

1. PostgreSQL (основная СУБД 1С)

Способ 1: Information Schema (стандартный SQL)

SELECT EXISTS (
    SELECT 1
    FROM information_schema.columns
    WHERE table_name = '_Reference123'  -- Имя таблицы
      AND column_name = 'Description'    -- Имя колонки
      AND table_schema = 'public'
);

Возвращает TRUE/FALSE — удобно в условиях и процедурах.

Способ 2: PostgreSQL системный каталог (быстрее)

SELECT EXISTS (
    SELECT 1
    FROM pg_attribute
    JOIN pg_class ON pg_class.oid = pg_attribute.attrelid
    WHERE pg_class.relname = '_Reference123'
      AND pg_attribute.attname = 'Description'
      AND pg_attribute.attnum > 0  -- Исключаем системные колонки
      AND NOT pg_attribute.attisdropped
);

Данный метод быстрее, но менее переносим.

Способ 3: \d команда в psql

# Интерактивно в psql
\d _Reference123
# Вывелет все колонки таблицы

2. MS SQL Server

Information Schema:

IF EXISTS (
    SELECT 1
    FROM INFORMATION_SCHEMA.COLUMNS
    WHERE TABLE_NAME = '_Reference123'
      AND COLUMN_NAME = 'Description'
)
BEGIN
    PRINT 'Колонка существует';
END;

Системные представления:

IF COL_LENGTH('dbo._Reference123', 'Description') IS NOT NULL
BEGIN
    PRINT 'Колонка существует';
END;

3. В коде 1С (высокоуровневый подход)

Использование объектной модели платформы:

// Для справочника
МетаОбъект = Метаданные.Справочники.Контрагенты;

КолонкаНайдена = Ложь;
Для Каждого Реквизит Из МетаОбъект.Реквизиты Цикл
    Если Реквизит.Имя = "ИНН" Тогда
        КолонкаНайдена = Истина;
        Прерывание;
    КонецЕсли;
КонецЦикла;

Если КолонкаНайдена Тогда
    Сообщение = Новый СообщениеПользователю;
    Сообщение.Текст = "Реквизит найден";
    Сообщение.Сообщить();
КонецЕсли;

Этот способ безопаснее, работает независимо от версии СУБД.

Более универсальный подход через метаданные:

Процедура ПроверитьНаличиеРеквизита(МетаОбъект, ИмяРеквизита) Экспорт
    
    Для Каждого Реквизит Из МетаОбъект.Реквизиты Цикл
        Если Реквизит.Имя = ИмяРеквизита Тогда
            Возврат Истина;
        КонецЕсли;
    КонецЦикла;
    
    // Проверяем табличные части
    Для Каждого ТабЧасть Из МетаОбъект.ТабличныеЧасти Цикл
        Если ТабЧасть.Имя = ИмяРеквизита Тогда
            Возврат Истина;
        КонецЕсли;
    КонецЦикла;
    
    Возврат Ложь;
    
КонецПроцедуры;

4. Динамический SQL в 1С

При использовании прямых запросов к СУБД:

Процедура ПроверитьКолонкуВПостгресе(ТаблицаИмя, КолонкаИмя) Экспорт
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ ПЕРВЫЕ 1
        |    1
        |ИЗ
        |    information_schema.columns
        |ГДЕ
        |    table_name = &ТаблицаИмя
        |    И column_name = &КолонкаИмя";
    
    Запрос.УстановитьПараметр("ТаблицаИмя", НижРегистр(ТаблицаИмя));
    Запрос.УстановитьПараметр("КолонкаИмя", НижРегистр(КолонкаИмя));
    
    РезультатЗапроса = Запрос.Выполнить();
    
    Возврат НЕ РезультатЗапроса.Пусто();
    
КонецПроцедуры;

5. Практический сценарий: миграция данных

Проверка при обновлении конфигурации:

Процедура ОбработатьСтарыеДанные() Экспорт
    
    МетаОбъект = Метаданные.Справочники.Контрагенты;
    
    // Проверяем наличие устаревшего реквизита
    Если ПроверитьНаличиеРеквизита(МетаОбъект, "СтарыйФормат") Тогда
        // Мигрируем данные
        Запрос = Новый Запрос;
        Запрос.Текст = 
            "ВЫБРАТЬ
            |    Ссылка,
            |    СтарыйФормат
            |ИЗ
            |    Справочник.Контрагенты";
        
        ТаблицаДанных = Запрос.Выполнить().Выгрузить();
        
        Для Каждого Строка Из ТаблицаДанных Цикл
            Объект = Строка.Ссылка.ПолучитьОбъект();
            Объект.НовыйФормат = ПреобразоватьСтарыеДанные(Строка.СтарыйФормат);
            Объект.Записать();
        КонецЦикла;
    КонецЕсли;
    
КонецПроцедуры;

6. Оптимизация запроса

Неправильно (медленно):

-- Это попытается отобрать все данные и потом проверить
SELECT COUNT(*) FROM _Reference123;

Правильно (быстро):

-- Проверяем метаинформацию, не трогаем данные
SELECT EXISTS (
    SELECT 1 FROM information_schema.columns
    WHERE table_name = '_Reference123' AND column_name = 'Description'
);

Рекомендации

  1. В 1С коде — используй метаданные (Метаданные.*), это безопаснее и переносимее
  2. Для прямого SQL — используй information_schema в PostgreSQL или COL_LENGTH в MS SQL
  3. В критичных операциях — проверяй наличие колонки перед USE, чтобы избежать ошибок
  4. Производительность — проверка метаинформации намного дешевле, чем SELECT данных

Вывод: Выбор метода зависит от контекста. В 1С коде — метаданные, в СУБД напрямую — information_schema. Всегда проверяй наличие перед использованием в динамических запросах.

Как определить, есть ли колонка в таблице или нет? | PrepBro