ОШИБКА PYODBC: аргумент данных SQL выходит за пределы диапазона (30030) (параметр привязки SQL)

#python #python-3.x #tkinter #db2

Вопрос:

Я пытаюсь вставить данные с помощью Python в базу данных DB2, вот код, который у меня есть:

 window=Tk()
window.title('Seguimiento')
window.geometry("1200x628")
titulo = Label(text="Base de Datos de Seguimiento", font=("Arial", 16, 'bold'), fg="White", bg="Blue")
titulo.pack()

conn_db2 = pyodbc.connect('DSN=AS400; UID=%s; PWD=%s' % ( uname, password ) )

centro_cursor = conn_db2.cursor()
resultado_centro = []
buscar_centro = "SELECT centro FROM BIUMO220.TICKCENTRO"
centro_cursor.execute(buscar_centro)
for loop_centro in centro_cursor:
     resultado_centro.append(loop_centro[0])

intervencion_cursor = conn_db2.cursor()
resultado_intervencion = []
buscar_intervencion = "SELECT tipo_intervencion FROM BIUMO220.TICKINTERVENCION"
intervencion_cursor.execute(buscar_intervencion)
for loop_intervencion in intervencion_cursor:
     resultado_intervencion.append(loop_intervencion[0])

resultado_intervencion = list(dict.fromkeys(resultado_intervencion))

responsable = StringVar()
fecha = IntVar()
centro = StringVar()
tipo_intervencion = StringVar()
subtipo_intervencion = StringVar()
comentario = StringVar()
ref_producto_final = StringVar()
descripcion_producto_final = StringVar()
ref_componente = StringVar()
util = StringVar()
tiempo_aprox_intervencion = StringVar()

responsable_ = "Responsable: "   uname
hoy = date.today()
global insertar_fecha
insertar_fecha = hoy.strftime("%Y/%m/%d")
fecha_hoy = hoy.strftime("%d/%m/%Y")
fecha_ = "Fecha: "   fecha_hoy

def seleccionar_subtipo(e):
    subtipo_intervencion_cursor = conn_db2.cursor()
    global resultado_subtipo_intervencion
    resultado_subtipo_intervencion = []
    seleccion_intervencion = tipo_intervencion_desplegable.get()
    buscar_subtipo = "SELECT subtipo FROM BIUMO220.TICKINTERVENCION WHERE 
    tipo_intervencion = ?"
    subtipo_intervencion_cursor.execute(buscar_subtipo, seleccion_intervencion)
    for loop_subtipo_intervencion in subtipo_intervencion_cursor:
        resultado_subtipo_intervencion.append(loop_subtipo_intervencion[0])
        subtipo_intervencion_desplegable.config(value=(resultado_subtipo_intervencion))

def producto_final_descripcion_familia(i):
    global res
    global ref
    cur = conn_db2.cursor()
    ref = referencia_producto_final_entrada.get()
    res = []
    sql = "SELECT E.TEBEZ1, E.TEBEZ2, A.TXTXB1 FROM BIDBD220.TEIL E, BIDBD220.TABDS A WHERE E.TETENR = ? AND A.TXTXRT = 'TL' AND E.TEPRKL = LTRIM(A.TXTXNR)  AND A.TXSPCD = 'S'"
    cur.execute(sql, ref)
    row = cur.fetchall()
    for rows in row:
        res.append(rows)
        descripcion_producto_final_entrada1.config(text=res)

def componente_descripcion_familia(j):
    global referencia_componente
    global componente_resultado
    componente_cursor = conn_db2.cursor()
    componente_resultado = []
    referencia_componente = referencia_componente_entrada.get()
    componente_query = "SELECT E.TEBEZ1, E.TEBEZ2, A.TXTXB1 FROM BIDBD220.TEIL E, BIDBD220.TABDS A WHERE E.TETENR = ? AND A.TXTXRT = 'TL' AND E.TEPRKL = LTRIM(A.TXTXNR)  AND A.TXSPCD = 'S'"
    componente_cursor.execute(componente_query, referencia_componente)
    componente_row = componente_cursor.fetchall()
    for com in componente_row:
        componente_resultado.append(com)
        descripcion_componente_entrada.config(text=componente_resultado)

def util_descripcion_familia(k):
    global referencia_util
    global util_resultado
    util_cursor = conn_db2.cursor()
    referencia_util = util_entrada.get()
    util_resultado = []
    util_query = "SELECT TRIM(E.TEBEZ1), TRIM(E.TEBEZ2), TRIM(A.TXTXB1) FROM BIDBD220.TEIL E, BIDBD220.TABDS A WHERE E.TETENR = ? AND A.TXTXRT = 'TL' AND E.TEPRKL = LTRIM(A.TXTXNR)  AND A.TXSPCD = 'S'"
    util_cursor.execute(util_query, referencia_util)
    util_row = util_cursor.fetchall()
    for uti in util_row:
        util_resultado.append(uti)
        descripcion_util_entrada.config(text=util_resultado)

def registrar_intervencion():
    registrar_intervencion_cursor = conn_db2.cursor()

    insertar_centro = centro_desplegable.get()
    insertar_intervencion = tipo_intervencion_desplegable.get()
    insertar_subtipo_intervencion = subtipo_intervencion_desplegable.get()
    insertar_comentario = comentario_entrada.get()
    insertar_producto_final = referencia_producto_final_entrada.get()
    insertar_componente = referencia_producto_final_entrada.get()
    insertar_util = util_entrada.get()
    insertar_tiempo = tiempo_aprox_intervencion_entrada.get()

** This is the line to intert the form information.**
    registrar_intervencion_query = "INSERT INTO BIUMO220.TICKREGINTERVENCION(numerador, responsable, fecha, centro, tipo_intervencion, subtipo, comentario, ref_producto_final, df_producto_final, ref_componente, df_componente, util, df_util, tiempo_intervencion) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
    registrar_intervencion_cursor.execute(registrar_intervencion_query, (numerador, uname, insertar_fecha, insertar_centro, insertar_intervencion, insertar_subtipo_intervencion, insertar_comentario, insertar_producto_final, res, insertar_componente, componente_resultado, insertar_util, util_resultado, insertar_tiempo))
    registrar_intervencion_cursor.commit()
            
numero_ticket_etiqueta = Label(text="Ticket N:", font=("Arial", 12))
numero_ticket_etiqueta.place(x=20, rely=.1, anchor="w")
global numerador
numerador = 0

responsable_etiqueta = Label(text=responsable_, font=("Arial", 12))
responsable_etiqueta.place(relx=.5, rely=.1, anchor="center")

fecha_etiqueta = Label(text=fecha_, font=("Arial", 12))
fecha_etiqueta.place(x=1100, rely=.1, anchor="e")

tipo_intervencion_etiqueta = Label(text="Tipo de Intervencion:", font=("Arial", 12))
tipo_intervencion_etiqueta.place(x=20, y=100)
tipo_intervencion_desplegable = ttk.Combobox(window, value=resultado_intervencion, font=("Arial", 12))
tipo_intervencion_desplegable.place(x=170, y=100)

tipo_intervencion_desplegable.bind("<<ComboboxSelected>>", seleccionar_subtipo)

subtipo_intervencion_etiqueta = Label(text="Subtipo:", font=("Arial", 12))
subtipo_intervencion_etiqueta.place(x=480, y=100)
subtipo_intervencion_desplegable = ttk.Combobox(window, value=[" "], font=("Arial", 12))
subtipo_intervencion_desplegable.place(x=550, y=100)

centro_etiqueta = Label(text="Centro:", font=("Arial", 12))
centro_etiqueta.place(x=850, y=100)
centro_desplegable = ttk.Combobox(window, value=resultado_centro, font=("Arial", 12))
centro_desplegable.place(x=910, y=100)

comentario_etiqueta = Label(text="Comentario:", font=("Arial", 12))
comentario_etiqueta.place(x=20, y=150)
comentario_entrada = Entry(textvariable=comentario, width="110", font=("Arial", 12))
comentario_entrada.place(x=120, y=150)

referencia_producto_final_etiqueta = Label(text="Ref. Producto Final:", font=("Arial", 12))
referencia_producto_final_etiqueta.place(x=20, y=200)
referencia_producto_final_entrada = Entry(textvariable=ref_producto_final, width="15", font=("Arial", 12))
referencia_producto_final_entrada.place(x=170, y=200)

referencia_producto_final_entrada.bind('<Return>', producto_final_descripcion_familia)

descripcion_producto_final_entrada1 = Label(font=("Arial", 12))
descripcion_producto_final_entrada1.place(x=320, y=200)

descripcion_producto_final_entrada2 = Label(font=("Arial", 12))
descripcion_producto_final_entrada2.place(x=520, y=200)

referencia_componente_etiqueta = Label(text="Ref. Componente:", font=("Arial", 12))
referencia_componente_etiqueta.place(x=20, y=250)
referencia_componente_entrada = Entry(textvariable=ref_componente, width="15", font=("Arial", 12))
referencia_componente_entrada.place(x=160, y=250)

referencia_componente_entrada.bind('<Return>', componente_descripcion_familia)

descripcion_componente_entrada = Label(font=("Arial", 12))
descripcion_componente_entrada.place(x=300, y=250)

util_etiqueta = Label(text="Util:", font=("Arial", 12))
util_etiqueta.place(x=20, y=300)
util_entrada = Entry(textvariable=util, width="15", font=("Arial", 12))
util_entrada.place(x=60, y=300)

util_entrada.bind('<Return>', util_descripcion_familia)

descripcion_util_entrada = Label(font=("Arial", 12))
descripcion_util_entrada.place(x=200, y=300)

tiempo_aprox_intervencion_etiqueta = Label(text="Tiempo Aprox. Intervencion:", font=("Arial", 12))
tiempo_aprox_intervencion_etiqueta.place(x=20, y=350)
tiempo_aprox_intervencion_entrada = Entry(textvariable=tiempo_aprox_intervencion, width="15", font=("Arial", 12))
tiempo_aprox_intervencion_entrada.place(x=220, y=350)

registrar_intervencion_boton = Button(window, text="REGISTRAR", font=("Arial", 12), command=registrar_intervencion)
registrar_intervencion_boton.place(x=20, y=400)


window.mainloop()
 

И это моя табличная информация:

 CREATE TABLE BIUMO220/TICKREGINTERVENCION(                          
     numerador int not null,
     responsable char(50) not null,              
     fecha date not null,
     centro char(50) not null,                      
     tipo_intervencion char(50) not null,
     subtipo char(50) not null,     
     comentario char(500),
     ref_producto_final char(50),                  
     df_producto_final char(500),
     ref_componente char(50),               
     df_componente char(500),
     util char(50),
     df_util char(500),          
     tiempo_intervencion char(5) not null)                               
 

Я создал эту таблицу с очень большими полями таблицы, потому что я думал, что ошибка заключалась в том, что одно поле было недостаточно большим для информации, но я ошибался.

Это ошибка Python, которую я получаю при попытке вставить информацию в форму:

 Exception in Tkinter callback
Traceback (most recent call last):
  File "C:py_installpy_394libtkinter__init__.py", line 1892, in __call__
    return self.func(*args)
  File "<string>", line 157, in registrar_intervencion
pyodbc.Error: ('00000', '[00000] [IBM][System i Access ODBC Controller]SQL dat argument out of range. (30030) (SQLBindParameter)')
 

Комментарии:

1. Какие значения вы вставляли? Не могли бы вы свернуть код так, чтобы он включал только необходимые строки?

2. Я не знаю, смогу ли я, все необходимое для формы. Например, вся информация о выпадающих списках является динамической, поэтому мне нужен запрос для каждого из них. Но я пытаюсь вставить все переменные «.get ()», которые вы видите над инструкцией insert. И у меня есть несколько статических переменных, таких как «числитель, имя и insertar_fecha».

3. @1511 Просто выведите значения переменных (в строке отладки) перед выполнением инструкции INSERT. Может быть ожидание, что символ не будет длиннее 254 байт.

4. Я только что попробовал, и все вроде нормально, самое большое поле состоит из 97 символов, следует ли мне отредактировать таблицу и на всякий случай поставить символ(200)?

5. Не получилось, я попытался поместить большие лагеря буквально на все, просто на случай, если вводятся какие-то случайные белые пространства, но я получаю ту же самую ошибку… Иисус…

Ответ №1:

Неправильное кодирование было непосредственной причиной этого симптома:

pyodbc.Ошибка: (‘00000’, ‘[00000] [IBM][Система i Доступ к контроллеру ODBC]Аргумент SQL dat вне диапазона. (30030) (параметр SQLBindParameter)’)

Вы передаете массивы в качестве параметров .execute() методу, но вместо этого интерфейс может ожидать скаляров. Например, в вашем фрагменте кода этими объектами являются массивы res и componente_resultado и util_resultado .

Разумно нормализовать модель данных для хранения одного скалярного значения в определенном столбце. Неразумно хранить список значений в одном столбце. Любой хороший учебник по моделированию данных объяснит обоснование этого и последствия денормализации для нарушения этих правил.

Если вы решите денормализовать и сохранить список значений в одном столбце, вы можете .join() сделать записи массива скалярными (с некоторым разделителем), прежде чем предоставлять результат в качестве параметра, до .execute() тех пор, пока вы понимаете, что это плохая практика и будет иметь последствия, и вы уже убедились, что целевой столбец достаточно большой.