Почему 1С заключает имена таблиц в кавычки при работе с PostgreSQL и как исправить ошибку "отношение не существует"?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При работе с внешними источниками данных, особенно при подключении к СУБД PostgreSQL, разработчики 1С могут столкнуться с неожиданной проблемой. Платформа формирует SQL-запросы, в которых имена таблиц и полей заключены в двойные кавычки и написаны в верхнем регистре, что приводит к ошибке ОШИБКА: отношение "..." не существует. Давайте детально разберемся, почему это происходит и как настроить взаимодействие между 1С и PostgreSQL, чтобы избежать подобных ошибок.

Проанализируем ситуацию, с которой столкнулся автор. Есть задача — из метаданных 1С создать структуру таблиц во внешней базе данных PostgreSQL, а затем работать с этими данными из 1С. Однако после создания таблиц запросы из платформы завершаются с ошибкой.

Анализ проблемы: конфликт кавычек и регистра

Корень проблемы лежит в одновременном действии двух факторов: специфики формирования SQL-запросов платформой 1С и правил обработки идентификаторов в PostgreSQL.

Рассмотрим пример. Допустим, в PostgreSQL была создана таблица с помощью следующего скрипта:


CREATE TABLE "uod_teamcenter".spm_pz_gm_rev(
    item_id CHARACTER VARYING (128),
    revision CHARACTER VARYING (20),
    revision_id CHARACTER VARYING (160),
    last_mod_date TIMESTAMP,
    name CHARACTER VARYING (256),
    tc_uid CHARACTER VARYING (20),
    guid_pac CHARACTER VARYING (40)
);

Несмотря на то, что имя схемы uod_teamcenter взято в кавычки, имя самой таблицы spm_pz_gm_rev и имена ее полей — нет. Здесь и кроется первая важная особенность PostgreSQL.

Правило PostgreSQL №1: Если идентификатор (имя таблицы, поля, схемы) не заключен в двойные кавычки, PostgreSQL автоматически приводит его к нижнему регистру. Таким образом, приведенный выше скрипт на самом деле создаст таблицу с именем spm_pz_gm_rev.

Теперь посмотрим, какой запрос генерирует платформа 1С для чтения данных из этой таблицы:


SELECT
    T1."ITEM_ID",
    T1.REVISION,
    T1."REVISION_ID",
    T1."LAST_MOD_DATE",
    T1.NAME,
    T1."TC_UID",
    T1."GUID_PAC"
FROM
    "UOD_TEAMCENTER"."SPM_PZ_GM_REV" T1
LIMIT 1000

Обратите внимание на несколько моментов:

  1. Имя таблицы SPM_PZ_GM_REV и схемы UOD_TEAMCENTER написано в верхнем регистре и заключено в двойные кавычки.
  2. Часть полей (например, ITEM_ID, REVISION_ID) также в верхнем регистре и в кавычках, а другая часть (REVISION, NAME) — без кавычек.

Здесь мы сталкиваемся со второй важной особенностью PostgreSQL.

Правило PostgreSQL №2: Если идентификатор заключен в двойные кавычки, он становится чувствительным к регистру. СУБД будет искать объект с именем, в точности совпадающим с тем, что указано в кавычках.

В итоге возникает конфликт: мы создали таблицу spm_pz_gm_rev (в нижнем регистре), а 1С пытается обратиться к таблице "SPM_PZ_GM_REV" (в верхнем регистре). Для PostgreSQL это два совершенно разных объекта, и, конечно, она не находит второй, возвращая ошибку "отношение не существует".

Почему 1С ведет себя именно так?

Платформа "1С:Предприятие" стремится обеспечить точное соответствие имени объекта в метаданных (свойство Имя в источнике данных) и имени в физической базе. Чтобы гарантировать это, особенно при наличии в именах спецсимволов или разного регистра, 1С заключает такие идентификаторы в кавычки.

Как показало обсуждение на форуме, триггером для такого поведения часто служит наличие в имени символа подчеркивания _. Хотя этот символ является стандартным для SQL, платформа 1С, видя его, перестраховывается и заключает идентификатор в кавычки, чтобы сохранить имя "как есть". Попутно, как мы видим, она также преобразует его в верхний регистр.

Поля REVISION и NAME не были взяты в кавычки, потому что их имена состоят только из латинских букв и не содержат спецсимволов.

Решение: как обеспечить совместимость

Чтобы подружить 1С и PostgreSQL, нужно привести их к "общему знаменателю". Необходимо создавать структуру таблиц в PostgreSQL именно в том виде, в котором 1С ожидает ее увидеть. Вот пошаговая инструкция.

  1. Используйте единый стиль именования. Самой надежной и общепринятой практикой для PostgreSQL является стиль snake_case, то есть все слова в нижнем регистре, разделенные символом подчеркивания (например, user_invoices, contract_date).

  2. Создавайте объекты в PostgreSQL с кавычками и в верхнем регистре. Это самый прямой способ решить проблему. Если вы знаете, что 1С будет генерировать запрос к таблице "SPM_PZ_GM_REV", то и создавать ее нужно с таким же именем. Ваш скрипт создания таблицы должен выглядеть так:

    
    CREATE TABLE "uod_teamcenter"."SPM_PZ_GM_REV" (
        "ITEM_ID" CHARACTER VARYING(128),
        "REVISION" CHARACTER VARYING(20),
        "REVISION_ID" CHARACTER VARYING(160),
        "LAST_MOD_DATE" TIMESTAMP,
        "NAME" CHARACTER VARYING(256),
        "TC_UID" CHARACTER VARYING(20),
        "GUID_PAC" CHARACTER VARYING(40)
    );
    

    Важный момент: в этом случае все идентификаторы, включая те, что не содержат подчеркивания, следует заключать в кавычки и писать в верхнем регистре. Это создаст в базе данных объекты с именами в верхнем регистре, и запросы от 1С будут успешно их находить.

  3. Соблюдайте точное соответствие в метаданных 1С. Убедитесь, что в конфигураторе 1С, в объекте метаданных "Внешний источник данных", свойство Имя в источнике данных для таблиц и полей в точности совпадает с тем, как они будут созданы в PostgreSQL (с учетом регистра). Если вы решили использовать верхний регистр в базе, то и в метаданных 1С имена должны быть в верхнем регистре (SPM_PZ_GM_REV, ITEM_ID и т.д.).

  4. Альтернативный вариант: только нижний регистр. Можно попробовать другой подход: создавать все объекты в PostgreSQL в нижнем регистре и без кавычек, и точно так же указывать их имена в метаданных 1С (в свойстве Имя в источнике данных). В теории, если 1С увидит в своих метаданных имя spm_pz_gm_rev, она может сгенерировать запрос вида FROM "spm_pz_gm_rev", который PostgreSQL поймет правильно. Этот вариант требует проверки, так как поведение платформы может зависеть от ее версии, но он более идеологически верен для PostgreSQL.

Итог: Проблема "отношение не существует" при работе 1С с PostgreSQL — это классический конфликт чувствительности к регистру. 1С заключает идентификаторы со спецсимволами в кавычки и приводит к верхнему регистру, а PostgreSQL по умолчанию работает с нижним регистром (если имена не в кавычках). Самое надежное решение — принудительно создавать таблицы и поля в PostgreSQL с именами в верхнем регистре и в двойных кавычках, чтобы они в точности соответствовали тому, как к ним будет обращаться платформа 1С.

← На главную