Как правильно использовать SQL-процедуры из 1С через внешние источники данных и почему возникают ошибки?

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

При интеграции информационных систем часто возникает необходимость обмениваться данными или вызывать логику, реализованную на стороне внешней СУБД, например, SQL Server. Платформа 1С предоставляет для этого мощный механизм Внешние источники данных (ВИД). Однако работа с ним требует понимания специфики взаимодействия между 1С и СУБД, особенно при вызове хранимых процедур.

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

Разбираемся с ошибкой "Обращение к процедуре объекта как к функции (dbo_MC_UpdateCard)"

Эта ошибка является одной из наиболее частых при попытке вызвать SQL-процедуру, которая не возвращает никакого значения, из кода 1С, используя ее как "функцию" внешнего источника данных. Система 1С ожидает, что любая функция, к которой идет обращение, вернет определенный результат, будь то скалярное значение или набор данных. Если SQL-процедура выполняет только операции модификации данных (UPDATE, INSERT, DELETE) и не содержит операторов, возвращающих результат (например, SELECT), платформа 1С интерпретирует такое поведение как ошибку.

Рассмотрим исходную SQL-процедуру, которая была предметом обсуждения:


USE [DDS]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALT ER PROCEDURE [dbo].[MC_UpdateCard]
(
    *Code int
)
AS
BEGIN
    UPD ATE [DDS].[dbo].[c_Cards] SE T [Balance]=11 where Code = *Code
END

В этой процедуре мы видим оператор UPDATE, который изменяет данные в таблице. Процедура не возвращает никаких значений. Когда мы пытаемся вызвать ее из 1С следующим образом:

ВнешниеИсточникиДанных.DDS.dbo_MC_UpdateCard(11);

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

Решение 1: Проверка флага "Возвращает значение"

Первым шагом всегда следует проверить настройки функции внешнего источника данных в конфигураторе 1С:

  1. Откройте конфигуратор.
  2. Перейдите к вашему внешнему источнику данных (например, DDS).
  3. Найдите соответствующую функцию, в нашем случае dbo_MC_UpdateCard, в списке "Функции источника".
  4. Откройте свойства этой функции.
  5. Убедитесь, что флаг "Возвращает значение" снят (то есть, не установлен).

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

Решение 2: Коррекция синтаксиса параметров в SQL-процедуре

Внимательно посмотрим на объявление параметра в исходной SQL-процедуре: *Code int. В синтаксисе SQL Server параметры хранятся в переменных, которые традиционно начинаются с символа "собачки" (@). Использование *Code является неверным синтаксисом для объявления параметра.

Исправьте SQL-процедуру следующим образом:


USE [DDS]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALT ER PROCEDURE [dbo].[MC_UpdateCard]
(
    <strong>@Code int</strong>
)
AS
BEGIN
    UPD ATE [DDS].[dbo].[c_Cards] SE T [Balance]=11 where Code = <strong>@Code</strong>
END

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

Решение 3: Использование прямого ADODB-соединения для выполнения процедур без возвращаемого значения

Когда стандартный механизм внешних источников данных 1С не справляется с вызовом SQL-процедур, не возвращающих значения, или когда требуется более тонкий контроль над параметрами и выполнением, лучшим решением является прямое использование ADODB-соединения (ActiveX Data Objects). Этот подход позволяет выполнять произвольные SQL-запросы и вызывать хранимые процедуры с полной гибкостью. Для изучения примеров прямой работы с СУБД можно использовать руководство по подключению и получению данных из SQL в 1С.

Давайте рассмотрим подробный пример кода 1С для вызова нашей процедуры MC_UpdateCard через ADODB:


&НаКлиенте
Процедура ВыполнитьSQLПроцедуруADODB(КодКарты = 0)

    // Если процедура выполняется на клиенте, убедитесь, что компоненты ADODB доступны.
    // Если на сервере 1С, то COM-объекты создаются на сервере.

    Перем СоединениеADODB, КомандаADODB, ПараметрКод;

    Попытка
        // 1. Создаем объект соединения ADODB.Connection
        // Этот объект отвечает за установление связи с базой данных.
        СоединениеADODB = Новый COMОбъект("ADODB.Connection");

        // 2. Формируем строку подключения (Connection String).
        // Это наиболее важная часть, она определяет параметры доступа к SQL Server.
        // Замените "Ваш_Сервер_SQL", "Ваш_Логин", "Ваш_Пароль" на актуальные данные.
        // Рекомендуется использовать актуальный ODBC-драйвер, например, "ODBC Driver 17 for SQL Server".
        // Убедитесь, что этот драйвер установлен на машине, где будет выполняться код 1С (клиент или сервер).
        СтрокаПодключения = "DRIVER={ODBC Driver 17 for SQL Server};SERVER=Ваш_Сервер_SQL;DATABASE=DDS;UID=Ваш_Логин;PWD=Ваш_Пароль;";

        // Если вы используете аутентификацию Windows (Integrated Security):
        // СтрокаПодключения = "DRIVER={ODBC Driver 17 for SQL Server};SERVER=Ваш_Сервер_SQL;DATABASE=DDS;Trusted_Connection=Yes;";

        // 3. Открываем соединение с SQL Server.
        СоединениеADODB.Open(СтрокаПодключения);
        Сообщить("Соединение с SQL Server успешно установлено.");

        // 4. Создаем объект команды ADODB.Command.
        // Этот объект используется для выполнения команд (запросов или процедур) на сервере базы данных.
        КомандаADODB = Новый COMОбъект("ADODB.Command");
        КомандаADODB.ActiveConnection = СоединениеADODB; // Связываем команду с активным соединением

        // 5. Указываем имя хранимой процедуры для выполнения.
        // Синтаксис вызова хранимой процедуры через ADODB с параметрами часто выглядит как "{call ИмяПроцедуры(?)}".
        // Вопросительный знак (?) является плейсхолдером для параметров.
        КомандаADODB.CommandText = "{call dbo.MC_UpdateCard(?)}";
        КомандаADODB.CommandType = 4; // adCmdStoredProc - указывает, что мы выполняем хранимую процедуру.

        // 6. Добавляем параметры в команду.
        // adCmdStoredProc = 4
        // adParamInput = 1  (входной параметр)
        // adInteger = 3   (целочисленный тип данных)
        // adVarChar = 200 (строковый тип данных)
        // adSmallInt = 2  (короткое целое)
        // adTinyInt = 16  (малое целое)
        // adDecimal = 14  (десятичный)
        // adNumeric = 13  (числовой)

        // Создаем параметр для кода карты.
        // Имя, Тип, Направление, Размер (для int часто не указывается или 4 байта), Значение
        ПараметрКод = КомандаADODB.CreateParameter("Code", 3, 1, 4, КодКарты);
        // "Code" - имя параметра в SQL-процедуре (соответствует @Code)
        // 3 - adInteger (целое число)
        // 1 - adParamInput (входной параметр)
        // 4 - размер в байтах для int
        // КодКарты - значение, которое мы передаем в процедуру
        КомандаADODB.Parameters.Append(ПараметрКод); // Добавляем параметр к команде

        // 7. Выполняем процедуру.
        // Для процедур, не возвращающих Recordset, используется .Execute().
        КомандаADODB.Execute();

        Сообщить("Процедура MC_UpdateCard успешно выполнена для Code = " + КодКарты + ".");

    Исключение
        // В случае ошибки выводим подробное описание.
        Сообщить("Ошибка при выполнении SQL-процедуры: " + ОписаниеОшибки(), СтатусСообщения.Важное);
        Если СоединениеADODB <> Неопределено И СоединениеADODB.Errors.Count > 0 Тогда
            Для Каждого ОшибкаADODB Из СоединениеADODB.Errors Цикл
                Сообщить("ADODB Error: " + ОшибкаADODB.Description + " (Source: " + ОшибкаADODB.Source + ", SQLState: " + ОшибкаADODB.SQLState + ")");
            КонецЦикла;
        КонецЕсли;
    КонецПопытки;

    // 8. Обязательно закрываем соединение.
    // Это освобождает ресурсы на сервере базы данных.
    Если СоединениеADODB <> Неопределено И СоединениеADODB.State = 1 Тогда // adStateOpen = 1
        СоединениеADODB.Close();
        СоединениеADODB = Неопределено;
        Сообщить("Соединение с SQL Server закрыто.");
    КонецЕсли;

КонецПроцедуры

Важные моменты при использовании ADODB:

  1. ODBC Драйвер: Убедитесь, что на компьютере, где выполняется код 1С (клиент или сервер), установлен соответствующий ODBC-драйвер для SQL Server. Современные версии SQL Server обычно требуют ODBC Driver 17 for SQL Server или более новый.
  2. Строка Подключения: Тщательно проверьте строку подключения. Любая ошибка в ней (неверный сервер, база данных, логин, пароль) приведет к невозможности соединения.
  3. Типы Параметров: При создании объекта Parameter через КомандаADODB.CreateParameter, указывайте правильные ADODB-константы для типа и направления параметра. Несоответствие типов между 1С и SQL Server может вызвать ошибки.
  4. Обработка Ошибок: Всегда используйте блоки Попытка...Исключение и логируйте подробную информацию об ошибках ADODB, так как они могут помочь в диагностике проблем.
  5. Закрытие Соединения: Крайне важно всегда закрывать соединение с базой данных после выполнения всех операций, чтобы избежать утечек ресурсов и блокировок.

Что делать, если данные не отображаются в таблице внешнего источника (Сообщение 9)

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

  1. Повторная настройка соединения в режиме "Предприятие":

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

    Как решить: После первого запуска в режиме "Предприятие" после создания или изменения внешнего источника данных, вам потребуется явно "Подключиться" к нему. Сделать это можно через меню "Все функции" -> "Стандартные" -> "Управление внешними источниками данных". Выберите ваш источник, введите необходимые параметры (если они отличаются от конфигурационных или требуют ввода) и нажмите кнопку "Подключиться". Убедитесь, что статус соединения стал "Подключено".

  2. Права доступа:

    Причина: У пользователя, под которым вы запускаете управляемое приложение, может не быть достаточных прав на работу с внешними источниками данных или конкретными объектами в них.

    Как решить: Проверьте роли пользователя. Убедитесь, что для роли пользователя есть установленные права на "Использование" для самого внешнего источника данных, а также права на "Чтение" и/или "Просмотр" для конкретных таблиц и функций, к которым вы пытаетесь получить доступ. Стандартная роль "Запуск внешнего соединения" может быть недостаточной для чтения данных из таблиц.

  3. Обновление данных:

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

    Как решить: После успешного подключения к внешнему источнику данных, а также при просмотре таблиц, попробуйте обновить данные, нажав клавишу F5 на клавиатуре или соответствующую кнопку обновления в форме.

  4. Некорректное определение таблицы типа "Выражение":

    Причина: Если вы создали таблицу внешнего источника данных с типом "Выражение", то в свойстве "Выражение в источнике данных" должен быть указан корректный SQL-запрос или вызов табличной функции, которая возвращает данные в табличном виде. Ошибка в этом выражении приведет к отсутствию данных.

    Как решить: Тщательно проверьте синтаксис SQL-выражения, указанного в свойстве "Выражение в источнике данных". Убедитесь, что это выражение возвращает корректный набор данных при выполнении непосредственно в СУБД.

  5. Ошибки драйвера или соединения:

    Причина: Проблемы могут быть на более низком уровне, такие как отсутствие или несовместимость ODBC-драйвера, некорректная строка соединения (даже если она позволяет подключиться, но не дает читать данные), или сетевые проблемы.

    Как решить:

    • Убедитесь, что соответствующий ODBC-драйвер установлен и обновлен на сервере 1С (если база файловая, то на клиентской машине) и на сервере SQL.
    • Проверьте логи ошибок SQL Server на наличие записей о неудачных подключениях или запросах от 1С.
    • Попробуйте использовать утилиту odbcad32.exe на машине с 1С для проверки DSN (Data Source Name) и тестового подключения к SQL Server.
    • Проверьте сетевое соединение между сервером 1С и SQL Server.

Ошибки при записи строки параметров или конфигурации внешнего источника данных (Сообщение 7)

Иногда проблемы возникают еще на этапе настройки внешнего источника данных в конфигураторе, например, при попытке сохранить параметры функции или таблицы.

  1. Некорректный синтаксис параметров:

    Причина: В конфигураторе 1С при описании параметров функции или выражений для таблиц, необходимо строго следовать синтаксису, ожидаемому платформой 1С и СУБД. Опечатки, неверный порядок или несоответствие типов могут вызывать ошибки.

    Как решить: Внимательно перепроверьте каждое свойство параметра (имя, тип, длина, направление), указанное в конфигураторе для функции. Убедитесь, что они полностью соответствуют определению процедуры или функции на стороне SQL Server.

  2. Несоответствие типов:

    Причина: Типы данных параметров, указанные в 1С, должны точно соответствовать или быть совместимыми с типами данных параметров хранимой процедуры или функции в SQL Server.

    Как решить: Сравните типы данных в 1С (например, "Строка", "Число", "Дата") с соответствующими типами в SQL Server (NVARCHAR, INT, DATETIME). При необходимости используйте преобразование типов на стороне SQL или более общий тип в 1С, если это возможно.

  3. Проблемы с метаданными или кэшем 1С:

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

    Как решить:

    • Попробуйте очистить кэш 1С. Это можно сделать, удалив файлы кэша из каталога пользователя (например, %LOCALAPPDATA%\1C\1Cv8 или %APPDATA%\1C\1Cv8).
    • Выполните "Тестирование и исправление" информационной базы через конфигуратор (меню "Конфигурация" -> "Тестирование и исправление"). Рекомендуется сделать резервную копию базы перед этим, если процессы архивирования и тестирования информационных баз еще не выполняются автоматически по расписанию.
    • Перезапустите конфигуратор и саму платформу 1С.

Работа с внешними источниками данных в 1С, безусловно, предоставляет мощные возможности для интеграции, но требует внимательности к деталям. Тщательная проверка каждого шага, от синтаксиса SQL-процедуры до настройки параметров в 1С и выбора метода вызова (через ВИД или ADODB), поможет избежать большинства распространенных ошибок и обеспечить стабильное взаимодействие между системами.

← На главную