sqlite3.OperationalError:near"?":语法错误随机发生

时间:2018-01-01 19:51:12

标签: python python-3.x tkinter sqlite syntax-error

我作为一个有趣的副项目一直在使用的代码一直工作得非常好,直到运行搜索功能时我才更新了我以前从未遇到过的错误。我试图弄清楚它为什么起作用,因为过去它已经突然之间没有了。

import sqlite3

def connect():
    """Set up a connection with the database."""
    conn_obj = sqlite3.connect("movies.db")
    cur_obj = conn_obj.cursor()
    cur_obj.execute("CREATE TABLE IF NOT EXISTS "
                    "movie (id integer PRIMARY KEY, "
                            "title text, "
                            "director text, "
                            "year integer, "
                            "studio integer)")
    conn_obj.commit()
    conn_obj.close()

def insert(title, director, year, studio):
    """Insert entry into database."""
    conn_obj = sqlite3.connect("movies.db")
    cur_obj = conn_obj.cursor()
    cur_obj.execute("INSERT INTO movie "
                    "VALUES (NULL, ?, ?, ?, ?)", (title, director, year, studio))
    conn_obj.commit()
    conn_obj.close()

def view():
    """View all database entries."""
    conn_obj = sqlite3.connect("movies.db")
    cur_obj = conn_obj.cursor()
    cur_obj.execute("SELECT * FROM movie")
    rows = cur_obj.fetchall()
    conn_obj.close()
    return rows

def update(id, title, author, year, isbn):
    """Update a database entry."""
    conn_obj = sqlite3.connect("movies.db")
    cur_obj = conn_obj.cursor()
    cur_obj.execute("UPDATE movie "
                    "SET title = ?, "
                    "director = ?, "
                    "year = ?, "
                    "studio = ? "
                    "WHERE id = ?", 
                    (title, director, year, studio, id))
    conn_obj.commit()
    conn_obj.close()

def delete(id):
    """Delete a database entry."""
    conn_obj = sqlite3.connect("movies.db")
    cur_obj = conn_obj.cursor()
    cur_obj.execute("DELETE FROM movie "
                    "WHERE id = ?", (id,))
    conn_obj.commit()
    conn_obj.close()

def search(title = "", director = "", year = "", studio = ""):
    """Search for a database entry."""
    conn_obj = sqlite3.connect("movies.db")
    cur_obj = conn_obj.cursor()
    cur_obj.execute("SELECT * "
                    "FROM movie "
                    "WHERE title = ? OR director = ? OR year = ? OR studio = ?", 
                    (title, director, year, studio))
    rows = cur_obj.fetchall()
    conn_obj.close()
    return rows

connect()

这是代码的后端,主要处理代码的主干,而前端处理tkinter GUI。问题在于代码后端的第68行,由于附近的错误,它是搜索功能的一部分。解释问题在于这行代码(标题,导演,年份,工作室,运行时,rtscore,id))因为 sqlite3.OperationalError:near"?":语法错误

from tkinter import *
import backend
import urllib.request
import urllib.parse
import re
import webbrowser
def add_command():
    """Insert entry via button."""
    backend.insert(title_text.get(),
                    director_text.get(),
                    year_text.get(),
                    studio_text.get(),
                    runtime_text.get(),
                    rtscore_text.get())
    listing.delete(0, END)
    listing.insert(END, 
                    (title_text.get(), 
                    director_text.get(), 
                    year_text.get(), 
                    studio_text.get(),
                    runtime_text.get(),
                    rtscore_text.get()))

def view_command():
    """View entries via button."""
    listing.delete(0, END)
    for row in backend.view():
        listing.insert(END, row)

def update_command():
    """Update entry via button."""
    backend.update(selected_tuple[0], 
                    title_text.get(), 
                    director_text.get(), 
                    year_text.get(), 
                    studio_text.get(),
                    runtime_text.get(),
                    rtscore_text.get())

def delete_command():
    """Delete entry via button."""
    backend.delete(selected_tuple[0])

def search_command():
    """Search entry via button."""
    listing.delete(0, END)
    for row in backend.search(title_text.get(), 
                                director_text.get(), 
                                year_text.get(), 
                                studio_text.get(),
                                runtime_text.get(),
                                rtscore_text.get()):
        listing.insert(END, row)


def get_selected_row(event):
    """Pre-fill fields for selected entry."""
    global selected_tuple
    index = listing.curselection()[0]
    selected_tuple = listing.get(index)

    entry1.delete(0, END)
    entry1.insert(END, selected_tuple[1])
    film = selected_tuple[1]
    entry2.delete(0, END)
    entry2.insert(END, selected_tuple[2])

    entry3.delete(0, END)
    entry3.insert(END, selected_tuple[3])

    entry4.delete(0, END)
    entry4.insert(END, selected_tuple[4])

    entry5.delete(0, END)
    entry5.insert(END, selected_tuple[5])

    entry6.delete(0, END)
    entry6.insert(END, selected_tuple[6])

def get_trailer():
    global selected_tuple
    index = listing.curselection()[0]
    selected_tuple = listing.get(index)
    film = selected_tuple[1]
    year = selected_tuple[3]
    years = str(year)
    print(year)
    print(film)
    query_string = urllib.parse.urlencode({"search_query" : film + years + 'trailer'})
    html_content = urllib.request.urlopen("http://www.youtube.com/results?" + query_string)
    search_results = re.findall(r'href=\"\/watch\?v=(.{11})', html_content.read().decode())
    web = ("http://www.youtube.com/watch?v=" + search_results[0])
    print(web)
    webbrowser.open(web)


window = Tk()

window.wm_title("Film Directory")

# Labels for entry fields.
label1 = Label(window, text = "Title")
label1.grid(row = 0, column = 0)

label2 = Label(window, text = "Director")
label2.grid(row = 0, column = 2)

label3 = Label(window, text = "Year")
label3.grid(row = 1, column = 0)

label4 = Label(window, text = "Studio")
label4.grid(row = 1, column = 2)

label5 = Label(window, text = "RunTime")
label5.grid(row = 2, column = 0)

label6 = Label(window, text = "RtScore")
label6.grid(row = 2, column = 2)

# Entry Fields.
title_text = StringVar()
entry1 = Entry(window, textvariable = title_text)
entry1.grid(row = 0, column = 1)

director_text = StringVar()
entry2 = Entry(window, textvariable = director_text)
entry2.grid(row = 0, column = 3)

year_text = StringVar()
entry3 = Entry(window, textvariable = year_text)
entry3.grid(row = 1, column = 1)

studio_text = StringVar()
entry4 = Entry(window, textvariable = studio_text)
entry4.grid(row = 1, column = 3)

runtime_text = StringVar()
entry5 = Entry(window, textvariable = runtime_text)
entry5.grid(row = 2, column = 1)

rtscore_text = StringVar()
entry6 = Entry(window, textvariable = rtscore_text)
entry6.grid(row = 2, column = 3)

# List all data.
listing = Listbox(window, height = 6, width = 35)
listing.grid(row = 2, column = 0, rowspan = 6, columnspan = 2)

# Scrollbar.
scroller = Scrollbar(window)
scroller.grid(row = 2, column = 2, rowspan = 6)

# Configure scrollbar for Listbox.
listing.configure(yscrollcommand = scroller.set)
scroller.configure(command = listing.yview)

listing.bind('<<ListboxSelect>>', get_selected_row)

# Buttons for various operations on data.
button1 = Button(window, 
                text = "View All", 
                width = 12, 
                command = view_command)
button1.grid(row = 3, column = 3)

button2 = Button(window, 
                text = "Search Entry", 
                width = 12, 
                command = search_command)
button2.grid(row = 4, column = 3)

button3 = Button(window, 
                text = "Add Entry", 
                width = 12, 
                command = add_command)
button3.grid(row = 5, column = 3)

button4 = Button(window, 
                text = "Update Selected", 
                width = 12, 
                command = update_command)
button4.grid(row = 6, column = 3)

button5 = Button(window, 
                text = "Delete Selected", 
                width = 12, 
                command = delete_command)
button5.grid(row = 7, column = 3)

button6 = Button(window, 
                text = "Close", 
                width = 12, 
                command = window.destroy)
button6.grid(row = 8, column = 3)

button7 = Button(window, 
                text = "Trailer", 
                width = 12, 
                command = get_trailer)
button7.grid(row = 9, column = 3)


# Keep window open until closed.
window.mainloop()

1 个答案:

答案 0 :(得分:0)

Gui更新了运行时和rt_score条目 你的后端使用数据库访问不是。

我更新并修复了有限的测试,你可以 修复任何未完成或获得进一步帮助。

我将运行时列设置为数据库中的文本,您可以 如果不合适,请更改类型。

在主tk脚本中,函数中发生错误 get_selected_row。我添加了一个临时解决方案,可能是tk 需要一个设置来避免这个问题。请参阅脚本注释。

您可能需要重新创建或更改现有数据库文件 backend.py将创建并使用另外2列的表。

tk脚本

from tkinter import *
import backend
import urllib.request
import urllib.parse
import re
import webbrowser
def add_command():
    """Insert entry via button."""
    backend.insert(title_text.get(),
                    director_text.get(),
                    year_text.get(),
                    studio_text.get(),
                    runtime_text.get(),
                    rtscore_text.get())
    listing.delete(0, END)
    listing.insert(END,
                    (title_text.get(),
                    director_text.get(),
                    year_text.get(),
                    studio_text.get(),
                    runtime_text.get(),
                    rtscore_text.get()))

def view_command():
    """View entries via button."""
    listing.delete(0, END)
    for row in backend.view():
        listing.insert(END, row)

def update_command():
    """Update entry via button."""
    backend.update(selected_tuple[0],
                    title_text.get(),
                    director_text.get(),
                    year_text.get(),
                    studio_text.get(),
                    runtime_text.get(),
                    rtscore_text.get())

def delete_command():
    """Delete entry via button."""
    backend.delete(selected_tuple[0])

def search_command():
    """Search entry via button."""
    listing.delete(0, END)
    for row in backend.search(title_text.get(),
                                director_text.get(),
                                year_text.get(),
                                studio_text.get(),
                                runtime_text.get(),
                                rtscore_text.get()):
        listing.insert(END, row)


def get_selected_row(event):
    """Pre-fill fields for selected entry."""
    global selected_tuple
    # *** unsure fix to avoid index out of range error.
    # *** callback issue when double click in a input ctrl.
    if not listing.curselection(): return

    index = listing.curselection()[0]
    selected_tuple = listing.get(index)

    entry1.delete(0, END)
    entry1.insert(END, selected_tuple[1])
    film = selected_tuple[1]
    entry2.delete(0, END)
    entry2.insert(END, selected_tuple[2])

    entry3.delete(0, END)
    entry3.insert(END, selected_tuple[3])

    entry4.delete(0, END)
    entry4.insert(END, selected_tuple[4])

    entry5.delete(0, END)
    entry5.insert(END, selected_tuple[5])

    entry6.delete(0, END)
    entry6.insert(END, selected_tuple[6])

def get_trailer():
    global selected_tuple
    index = listing.curselection()[0]
    selected_tuple = listing.get(index)
    film = selected_tuple[1]
    year = selected_tuple[3]
    years = str(year)
    print(year)
    print(film)
    query_string = urllib.parse.urlencode({"search_query" : film + years + 'trailer'})
    html_content = urllib.request.urlopen("http://www.youtube.com/results?" + query_string)
    search_results = re.findall(r'href=\"\/watch\?v=(.{11})', html_content.read().decode())
    web = ("http://www.youtube.com/watch?v=" + search_results[0])
    print(web)
    webbrowser.open(web)


window = Tk()

window.wm_title("Film Directory")

# Labels for entry fields.
label1 = Label(window, text = "Title")
label1.grid(row = 0, column = 0)

label2 = Label(window, text = "Director")
label2.grid(row = 0, column = 2)

label3 = Label(window, text = "Year")
label3.grid(row = 1, column = 0)

label4 = Label(window, text = "Studio")
label4.grid(row = 1, column = 2)

label5 = Label(window, text = "RunTime")
label5.grid(row = 2, column = 0)

label6 = Label(window, text = "RtScore")
label6.grid(row = 2, column = 2)

# Entry Fields.
title_text = StringVar()
entry1 = Entry(window, textvariable = title_text)
entry1.grid(row = 0, column = 1)

director_text = StringVar()
entry2 = Entry(window, textvariable = director_text)
entry2.grid(row = 0, column = 3)

year_text = StringVar()
entry3 = Entry(window, textvariable = year_text)
entry3.grid(row = 1, column = 1)

studio_text = StringVar()
entry4 = Entry(window, textvariable = studio_text)
entry4.grid(row = 1, column = 3)

runtime_text = StringVar()
entry5 = Entry(window, textvariable = runtime_text)
entry5.grid(row = 2, column = 1)

rtscore_text = StringVar()
entry6 = Entry(window, textvariable = rtscore_text)
entry6.grid(row = 2, column = 3)

# List all data.
listing = Listbox(window, height = 6, width = 35)
listing.grid(row = 2, column = 0, rowspan = 6, columnspan = 2)

# Scrollbar.
scroller = Scrollbar(window)
scroller.grid(row = 2, column = 2, rowspan = 6)

# Configure scrollbar for Listbox.
listing.configure(yscrollcommand = scroller.set)
scroller.configure(command = listing.yview)

listing.bind('<<ListboxSelect>>', get_selected_row)

# Buttons for various operations on data.
button1 = Button(window,
                text = "View All",
                width = 12,
                command = view_command)
button1.grid(row = 3, column = 3)

button2 = Button(window,
                text = "Search Entry",
                width = 12,
                command = search_command)
button2.grid(row = 4, column = 3)

button3 = Button(window,
                text = "Add Entry",
                width = 12,
                command = add_command)
button3.grid(row = 5, column = 3)

button4 = Button(window,
                text = "Update Selected",
                width = 12,
                command = update_command)
button4.grid(row = 6, column = 3)

button5 = Button(window,
                text = "Delete Selected",
                width = 12,
                command = delete_command)
button5.grid(row = 7, column = 3)

button6 = Button(window,
                text = "Close",
                width = 12,
                command = window.destroy)
button6.grid(row = 8, column = 3)

button7 = Button(window,
                text = "Trailer",
                width = 12,
                command = get_trailer)
button7.grid(row = 9, column = 3)


# Keep window open until closed.
window.mainloop()

backend.py脚本

import sqlite3

def connect():
    """Set up a connection with the database."""
    conn_obj = sqlite3.connect("movies.db")
    cur_obj = conn_obj.cursor()
    cur_obj.execute("CREATE TABLE IF NOT EXISTS "
                    "movie (id INTEGER PRIMARY KEY, "
                            "title TEXT,"
                            "director TEXT,"
                            "year INTEGER,"
                            "studio INTEGER,"
                            "runtime TEXT,"
                            "rt_score INTEGER)")
    conn_obj.commit()
    conn_obj.close()

def insert(title, director, year, studio, runtime, rt_score):
    """Insert entry into database."""
    conn_obj = sqlite3.connect("movies.db")
    cur_obj = conn_obj.cursor()
    cur_obj.execute("INSERT INTO movie "
                    "(title,director,year,studio,runtime,rt_score) "
                    "VALUES (?, ?, ?, ?, ?, ?)",
                    (title, director, year, studio, runtime, rt_score))
    conn_obj.commit()
    conn_obj.close()

def view():
    """View all database entries."""
    conn_obj = sqlite3.connect("movies.db")
    cur_obj = conn_obj.cursor()
    cur_obj.execute("SELECT * FROM movie")
    rows = cur_obj.fetchall()
    conn_obj.close()
    return rows

def update(id, title, director, year, studio, runtime, rt_score):
    """Update a database entry."""
    conn_obj = sqlite3.connect("movies.db")
    cur_obj = conn_obj.cursor()
    cur_obj.execute("UPDATE movie "
                    "SET title = ?, "
                    "director = ?, "
                    "year = ?, "
                    "studio = ?, "
                    "runtime = ?, "
                    "rt_score = ? "
                    "WHERE id = ?",
                    (title, director, year, studio, runtime, rt_score, id))
    conn_obj.commit()
    conn_obj.close()

def delete(id):
    """Delete a database entry."""
    conn_obj = sqlite3.connect("movies.db")
    cur_obj = conn_obj.cursor()
    cur_obj.execute("DELETE FROM movie "
                    "WHERE id = ?", (id,))
    conn_obj.commit()
    conn_obj.close()

def search(title="", director="", year="", studio="", runtime="", rt_score=""):
    """Search for a database entry."""
    conn_obj = sqlite3.connect("movies.db")
    cur_obj = conn_obj.cursor()
    cur_obj.execute("SELECT * "
                    "FROM movie "
                    "WHERE title = ? "
                    "OR director = ? "
                    "OR year = ? "
                    "OR studio = ? "
                    "OR runtime = ?"
                    "OR rt_score = ?",
                    (title, director, year, studio, runtime, rt_score))
    rows = cur_obj.fetchall()
    conn_obj.close()
    return rows

connect()