Python – PySimpleGUI – OracleDB – Input text passed into Oracle statement

Question:

I’ve made a simple Python app where I want two text fields ‘ID’ and ‘TEXT’ to be passed into the Oracle insert statement. The app opens correctly and the functions appear to work however the inputtext from those fields are not being passed into the Oracle statement.

Python Code below;

import PySimpleGUI as sg
import oracledb

oracledb.init_oracle_client(lib_dir=r"C:oracleinstantclient_11_2")

layout =[
           [sg.Text('Text',size=(10,1)),sg.InputText("", key='-TEXT-')],
           [sg.Button('Submit'),sg.Button('Quit')] ]
         
sg.theme('dark grey 6')
window = sg.Window('Oracle - Test Insert',layout)

event,values = window.read()
if event == 'Submit':
    with oracledb.connect(user="blinx", password="ComCraft8",
                          dsn="10.10.2.25:1521/ORCL") as connection:
        sql = """
            insert into danaos.z_blinx_notes (TEXT)
            values (:1)"""
        bind_values = ['-TEXT-']
        with connection.cursor() as cur:
            cur.execute(sql, bind_values)
    
elif event == 'Quit':
    window.close()

Tried this, the app loads/builds but it throws no error but doesn’t insert the record.

Asked By: M Davie

||

Answers:

Better to set the keys for all Input elements, like ‘UserName’, ‘Password’, ‘Hostname’, ‘Port’, ‘SID’, ‘-ID-‘ and ‘-TEXT-‘ (a dash missed in your code). Then you can get the content of Input elements by their key, like values['UserName'].

Syntax – Following is the syntax of the INSERT INTO statement of MySQL.

INSERT INTO TABLE_NAME (column1, column2,column3,…columnN)
VALUES (value1, value2, value3,…valueN);

It looks like following statement is wrong code, wrong values as the ['-ID-'] and ['-TEXT-']

sql2 = """insert into schema.table (ID, TEXT) values (['-ID-'], ['-TEXT-'])"""
Answered By: Jason Yang

Try this (written with python-oracledb, the upgraded version of cx_Oracle, but you can replace oracledb with cx_Oracle in the code below and it should still work):

import PySimpleGUI as sg
import oracledb

layout =[
           [sg.Text('Text',size=(10,1)),sg.InputText("", key='-TEXT-')],
           [sg.Button('Submit'),sg.Button('Quit')] ]
         
sg.theme('dark grey 6')
window = sg.Window('Oracle - Test Insert',layout)

event,values = window.read()
if event == 'Submit':
    with oracledb.connect(user="blinx", password="ComCraft8",
                          dsn="10.10.2.25:1521/ORCL" as connection:
        sql = """
            insert into schema.table (ID, TEXT)
            values (some_sequence_name.nextval, :1)"""
        bind_values = ['-TEXT-']
        with connection.cursor() as cur:
            cur.execute(sql, bind_values)
    
elif event == 'Quit':
    window.close()

In other words:

  • use bind variables for safety, performance, ease of use
  • you have to actually call cursor.execute() to have the database do something!
  • nextval isn’t valid; you must prefix that with the sequence name

The error ORA-00936 indicates an invalid SQL statement as there is a "missing expression".

Answered By: Anthony Tuininga

So with the help of the previous responses and some trial and error I’ve got it working with the below code. Thanks everyone for helping!

import cx_Oracle
import PySimpleGUI as sg

layout = [
    [sg.Text('Enter Text:'), sg.Input(key='text')],
    [sg.Text('Enter Author:'), sg.Input(key='author')],
    [sg.Button('Submit'), sg.Button('Clear'), sg.Button('Quit')]
]

window = sg.Window('Add Note - Test', layout)

while True:
    event, values = window.read()
    if event == sg.WIN_CLOSED or event == 'Quit':
        window.close()
        break
    elif event == 'Submit':
        # Clear all input fields
        for key in values:
            window[key]('')
    elif event == 'Clear':
        # Clear all input fields
        for key in values:
            window[key]('') 
    text = values['text']
    author = values['author']
    conn = cx_Oracle.connect('username/password@hostname:port/sid')
    cur = conn.cursor()
    query = 'INSERT INTO schema.tablename (ID, TEXT, AUTHOR) VALUES (schema.sequence.nextval, :text, :author)'
    cur.execute(query, {'text': text, 'author': author})
    conn.commit()
    cur.close()
    conn.close()

window.close()
Answered By: M Davie