2025, Sep 29 05:32

PYODBC पर Databricks Delta INSERT में column arity mismatch: UseNativeQuery=1 से समाधान

Databricks में PYODBC से Delta टेबल पर INSERT करते समय column arity mismatch या गलत कॉलम मैपिंग हो रही है? UseNativeQuery=1 से native SQL चलाएँ, समस्या ठीक करें

Databricks पर PYODBC के जरिए Delta टेबल में डेटा डालते समय ऐसा त्रुटि संदेश मिल सकता है, जो Databricks UI में दिखाई नहीं देता। एक आम स्थिति: वर्कस्पेस में partial-column INSERT काम कर जाता है, लेकिन वही SQL ODBC पर column arity mismatch के साथ असफल हो जाता है। नतीजतन उलझन पैदा होती है—कभी मान गलत कॉलमों में चले जाते हैं, तो कभी कॉलम की संख्या न मिलने की गलती आती है।

समस्या को दोहराना

निम्नलिखित सीधे VALUES वाला insert 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] target table has 23 column(s) but the inserted data has 2 column(s)

एक अन्य परिदृश्य में, अगर टेबल में कॉलमों का वास्तविक क्रम आपके स्टेटमेंट से मेल नहीं खाता, तो PYODBC के जरिए मान गलत कॉलमों में जा सकते हैं, जबकि Databricks में वही स्टेटमेंट इच्छित कॉलमों में ही इंसर्ट करता है।

ऐसा क्यों होता है

यह फर्क ODBC मार्ग पर होने वाले SQL dialect translation से उपजता है। जो स्टेटमेंट Databricks UI में ज्यों‑का‑त्यों स्वीकार होता है, उसे क्लाइंट/ड्राइवर इस तरह बदल सकता है कि इंजन कॉलम बाइंडिंग को अलग ढंग से समझे—और नतीजे में दिखने वाला arity mismatch या कॉलम क्रम को लेकर भ्रम पैदा हो।

समाधान

ODBC कनेक्शन स्ट्रिंग में UseNativeQuery=1 जोड़कर native SQL execution लागू करें। इससे translation से बचाव होता है और इच्छित INSERT semantics सुरक्षित रहते हैं। विवरण के लिए Databricks ODBC capabilities दस्तावेज देखें: Databricks ODBC docs.

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()

Native query execution सक्षम होने पर, INSERT ... SELECT का व्यवहार Databricks UI में दिखने वाले व्यवहार से मेल खाता है।

Parameterized स्टेटमेंट्स पर एक नोट

UseNativeQuery=1 सक्षम करने के बाद, नीचे दिए गए रूप वाला parameterized INSERT PYODBC पर एरर देता हुआ देखा गया है:

INSERT INTO etl_delta_sink (SRC_FILE_DATE, INGESTED_AT)
VALUES (?, CURRENT_TIMESTAMP)

उस सेटअप में, एक रिपोर्ट में ड्राइवर ने “Expected 0 parameters, supplied 1” (HY000) लौटाया। UseNativeQuery हटाने पर वही parameterized INSERT फिर से काम करने लगा। मूल समस्या की पुष्टि हुई और उसे संबोधित करने के बाद कोड सही चला। यदि आपको ऐसा संदेश मिले, तो UseNativeQuery के साथ और बिना—दोनों स्थितियों में व्यवहार की तुलना करें और अपने वातावरण में पैरामीटर कैसे बाइंड होते हैं, इसकी जाँच करें।

यह क्यों मायने रखता है

क्लाइंट-साइड SQL translation, Databricks द्वारा आपके स्टेटमेंट्स की व्याख्या को सूक्ष्म रूप से बदल सकता है। इसका असर Delta arity mismatches के रूप में या मानों के गलत कॉलमों में मैप होने के रूप में दिख सकता है, भले ही आपके SQL में लक्षित कॉलम स्पष्ट हों। ODBC मार्ग पर native SQL कैसे लागू करना है, यह जानने से टूल्स के बीच नियंत्रण और स्थिरता मिलती है।

मुख्य बातें

यदि कोई INSERT जो कुछ कॉलमों को लक्षित करता है, Databricks UI में काम करता है, पर PYODBC पर [DELTA_INSERT_COLUMN_ARITY_MISMATCH] के साथ असफल हो जाता है, तो dialect translation से बचने के लिए ODBC कनेक्शन स्ट्रिंग में UseNativeQuery=1 सक्षम करें। यह बदलाव करने के बाद literal और parameterized—दोनों तरह के स्टेटमेंट्स को फिर से जाँचें। अगर parameter binding के साथ “Expected 0 parameters, supplied 1 (HY000)” मिले, तो फ्लैग ऑन/ऑफ—दोनों स्थितियों का व्यवहार तुलना करें और उसी अनुसार अपनी कनेक्शन सेटिंग्स संरेखित करें। इससे Databricks SQL का व्यवहार विभिन्न क्लायंट्स में पूर्वानुमेय रहता है और आपको बिना शोर के होने वाली कॉलम मिसअलाइनमेंट से सुरक्षा मिलती है।

यह लेख StackOverflow पर दिए गए एक प्रश्न (लेखक: Jason Wiest) और Kertis van Kertis के उत्तर पर आधारित है।