sqlite: error when using another sqlite command inside a custom function (sqlite3.Connection.create_function)

Question:

I’m learning to create custom sqlite3 functions in Python. This is my code:

import sqlite3

conn = sqlite3.connect("data.db")
c = conn.cursor()


query = "CREATE TABLE IF NOT EXISTS names (ID INTEGER UNIQUE PRIMARY KEY NOT NULL, name TEXT)"
c.execute(query)


query = "INSERT INTO names (name) VALUES ('foo')"
c.execute(query)

query = "INSERT INTO names (name) VALUES ('boo')"
c.execute(query)

conn.commit()


def get_ID(name):
    
    query = "SELECT ID FROM names WHERE name = '{}'".format(name)
    c.execute(query)
    id = c.fetchall()
    print(id)
    return id

print(get_ID("foo"))

conn.create_function("GETID", 1, get_ID)

query = "SELECT GETID(?)"
c.execute(query, ("foo",))
print(c.fetchall())

c.close()
conn.close()

This is the ouptut:

[(1,)]
[(1,)]
Traceback (most recent call last):
  File "D:Sync1CodePython3test.py", line 33, in <module>
    c.execute(query, ("foo",))
sqlite3.OperationalError: user-defined function raised exception

Why does my function give an error?

Asked By: Abel Gutiérrez

||

Answers:

Use a different local cursor inside the function to execute the SELECT statement.
Also, fetchall() returns a list of sublists (a list of all the rows that are returned by the query) and not a scalar value.
Instead, take the ID with fetchone()[0].
Finally, be consistent about the way that you pass the parameters to any query, better (my opinion) with ? placeholders:

def get_ID(name):
    query = "SELECT ID FROM names WHERE name = ?"
    local_cursor = conn.cursor()
    local_cursor.execute(query, (name,))
    id = None
    if local_cursor.rowcount > 0:
        id = local_cursor.fetchone()[0]
    local_cursor.close()
    print(id)
    return id
Answered By: forpas
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.