2025, Sep 29 05:17
Исправляем DELTA_INSERT_COLUMN_ARITY_MISMATCH в PYODBC для Databricks: UseNativeQuery и корректное сопоставление столбцов
Почему INSERT ... SELECT в Databricks через PYODBC падает с DELTA_INSERT_COLUMN_ARITY_MISMATCH и как исправить: UseNativeQuery=1, нюансы параметров ODBC
При вставке в таблицу Delta в Databricks через PYODBC вы можете столкнуться с ошибкой, которой нет в интерфейсе Databricks. Типичный сценарий: вставка по части столбцов работает в рабочем пространстве, но тот же SQL через ODBC падает с несоответствием арности столбцов. В итоге проявляются странные симптомы: значения попадают не в те колонки или появляется ошибка о несовпадении количества столбцов.
Как воспроизвести проблему
Следующая прямая вставка с VALUES работает и в Databricks, и из Python:
INSERT INTO etl_delta_sink (INGESTED_AT, SRC_FILE_DATE)
VALUES (CURRENT_TIMESTAMP, 20250827);
Однако вариант на основе SELECT в Databricks проходит, а через PYODBC падает, несмотря на то что указаны только два целевых столбца:
INSERT INTO etl_delta_sink (INGESTED_AT, SRC_FILE_DATE)
SELECT CURRENT_TIMESTAMP, 20250827;
Через PYODBC это может привести к ошибке Delta вида:
[DELTA_INSERT_COLUMN_ARITY_MISMATCH] в целевой таблице 23 столбца, а во вставляемых данных — 2
В другом случае, если физический порядок столбцов в таблице не совпадает с порядком в выражении, через PYODBC значения могут разложиться неверно, тогда как тот же запрос в Databricks попадает в нужные столбцы.
Почему так происходит
Разница в поведении связана с преобразованием диалекта SQL на пути ODBC. Запрос, который Databricks в UI принимает «как есть», может быть изменён клиентом/драйвером так, что меняется интерпретация привязки столбцов движком. Отсюда — видимое несоответствие арности или путаница с порядком колонок.
Как исправить
Принудительно включите выполнение нативного SQL, добавив UseNativeQuery=1 в строку подключения ODBC. Это отключит трансляцию и сохранит ожидаемую семантику INSERT. Подробности — в документации по возможностям ODBC для Databricks: Документация Databricks ODBC.
Пример подключения и выполнения через PYODBC:
import pyodbc
conn_str = (
    "Driver={Databricks ODBC Driver};"
    "Host=YOUR_HOST;"
    "Port=YOUR_PORT;"
    "HTTPPath=YOUR_HTTP_PATH;"
    "UseNativeQuery=1;"
)
cn = pyodbc.connect(conn_str)
cur = cn.cursor()
sql_ins = (
    "INSERT INTO etl_delta_sink (INGESTED_AT, SRC_FILE_DATE) "
    "SELECT CURRENT_TIMESTAMP, 20250827"
)
cur.execute(sql_ins)
cn.commit()
При включённом нативном выполнении форма INSERT ... SELECT начинает вести себя так же, как в интерфейсе Databricks.
Замечание по параметризованным запросам
После включения UseNativeQuery=1 наблюдалась ошибка при параметризованной вставке следующего вида через PYODBC:
INSERT INTO etl_delta_sink (SRC_FILE_DATE, INGESTED_AT)
VALUES (?, CURRENT_TIMESTAMP)
В такой конфигурации в одном из отчётов драйвер возвращал «Expected 0 parameters, supplied 1» (HY000). Отключение UseNativeQuery возвращало работоспособность именно этой параметризованной вставки. Проблема была подтверждена и после её устранения код работал корректно. Если увидите похожее сообщение, сравните поведение с UseNativeQuery и без него и проверьте, как в вашей среде привязываются параметры.
Почему это важно
Клиентская трансляция SQL может незаметно менять то, как Databricks интерпретирует ваши выражения. Это проявляется как несоответствия арности в Delta или как некорректное сопоставление значений столбцам, даже если вы явно перечисляете целевые поля. Умение включить нативный SQL на пути ODBC даёт вам контроль и единообразие работы в разных инструментах.
Итоги
Если INSERT по подмножеству столбцов работает в интерфейсе Databricks, но падает через PYODBC с [DELTA_INSERT_COLUMN_ARITY_MISMATCH], включите UseNativeQuery=1 в строке подключения ODBC, чтобы избежать трансляции диалекта. После этого перепроверьте и буквальные, и параметризованные запросы. Если при привязке параметров увидите «Expected 0 parameters, supplied 1 (HY000)», сравните поведение с флагом и без него и соответствующим образом скорректируйте настройки подключения. Так поведение Databricks SQL останется предсказуемым во всех клиентах и убережёт вас от незаметного смещения столбцов.
Статья основана на вопросе на StackOverflow от Jason Wiest и ответе от Kertis van Kertis.