【问题标题】:psycopg2 Only Displays First Row of Postgresql Databasepsycopg2 仅显示 Postgresql 数据库的第一行
【发布时间】:2018-07-08 16:02:24
【问题描述】:

我在 tkinter 窗口中运行 Python3.5 和 Psycopg2 2.6。 我在一个名为 backend.py 的文件中有这个函数

import psycopg2


def search(year=0, month=0):
    '''Search the database for entries.'''
    conn = psycopg2.connect("dbname='birth_years'")
    cur = conn.cursor()
    cur.execute("SELECT * FROM birthdays WHERE year=year OR month=month;")
    row = cur.fetchone()
    conn.close()
    return row

我有这个代码的frontend.py。

from tkinter import *
import backend


def search_command(year, month):
    '''Run queries on the database.'''
    listbox1.delete(0, END)
    row = backend.search(year_text.get(), month_text.get())
    listbox1.insert(END, row)

window = Tk()
window.wm_title("Birthdays")
window.resizable(width=False, height=False)

Grid.rowconfigure(window, 0, weight=1)
Grid.columnconfigure(window, 0, weight=1)

b1 = Button(window, text="Search", width=15, command=search_command)
b1.grid(row=2, column=5)


window.mainloop()

数据库:

    id year month

    1 1999 2
    2 2005 5
    3 1987 11
    4 1988 12
    5 1978 10

postgresql 数据库包含这些数据。 PGAdmin2 能够很好地运行查询并只选择我想要的行。当我使用函数运行 1988 年的查询时,我在数据库的第一行中得到所有信息。

1 1999 2

【问题讨论】:

  • 呃,是的,因为您使用的是row = cur.fetchone() 而不是fetchall()。你明确要求它只返回一个值。
  • 尽管问题还有其他问题,因为您显然查询 1988 并返回 1999 的结果?这是一个错字还是一个真正的问题?
  • 无论我使用 cur.fetchone() 还是 cur.fetchall(),我都会得到相同的结果。它只获取数据库的第一行。没有错别字,如果我搜索 2005,我会得到 1999。这没有意义。
  • cur.fetchall() 只是获取整个数据库。

标签: python database postgresql psycopg2


【解决方案1】:

我认为这是一个逻辑错误,但我无法具体测试以确定。

您的查询目前是:

cur.execute("SELECT * FROM birthdays WHERE year=year OR month=month;")
row = cur.fetchone()

这有两个问题:

  1. 您使用了fetchone() 而不是fetchall(),因此很明显您只会得到一个结果;这就是你的要求。
  2. 您的查询只是一个简单的字符串。您实际上没有将任何参数传递给您的函数到查询中。 每个行在year 中都有一个值,该值等于year 中的值(您要求每个值与自身进行比较),这意味着您的查询对于所有行始终为True (所以你会拉整个数据库)。警告:可能存在不正确的 NaN 类型值,但总体上是正确的。

试试:

cur.execute("SELECT * FROM birthdays WHERE year=%s OR month=%s;", (year, month))
row = cur.fetchone()

您可能需要将%s 占位符括在引号中,我无法测试并且不知道您的数据库设置。这是一个参数化查询,其中yearmonth 根据传递给函数的值是动态的。你可以通过字符串格式化来做到这一点(你会看到很多人在此处的问题中这样做)但这确实让你暴露于 SQL 注入:记住Bobby Tables

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-25
    • 1970-01-01
    • 2011-11-13
    • 2012-10-30
    相关资源
    最近更新 更多