首页 > 解决方案 > 使用 Python 根据上次选择的列中提供的整数在 Postgresql 数据库中选择动态行

问题描述

我今天刚开始使用 Python,所以我处于新手级别。

我正在尝试制作一个数据库驱动的“决策树”。一旦完成,它将像在线 Python 示例中看到的“选择你自己的冒险”故事一样运行。

我在 PostgreSQL 中有一个包含以下列的表:id、textfield、nextitem

这是我要做的事情: - 脚本将从表中的某个记录开始。现在出于所有目的,我们将从 id 1 开始。我们将查询第一行(或任何可能成为未来起点的行)。因此,如果我要在 Postgres 中直接引用它,我只需 SELECT * FROM mytable 或 SELECT * FROM mytable WHERE id=1

- 如果列 [nextitem] 不为空,则继续处理列中的整数。因此,如果 SELECT * FROM mytable WHERE id=1 在 [nextitem] 中的值为“4”,则下一个查询应该是 SELECT * FROM mytable WHERE id=4。此过程将重复,直到 [nextitem] 为 NULL。

我在带有 PostgreSQL 9.6 和 psycopg2 的 Ubuntu Server 16.04.3 上使用 Python3。

我相信我需要做的是将列中的值拉出到一个变量中,然后允许 python 将其反馈给未来的查询,而不是循环它。

这是我到目前为止所拥有的(它需要大量清洁,因为我在被卡住的区域尝试了不同的东西而弄得一团糟——我的挂断似乎是将查询中的数据分离到 python 变量中并提供它回到):

import psycopg2
try:
    connect_str = "dbname='mydatabase' user='myuser' host='localhost' " + \
                  "password='mypassword'"
    # establish a connection
    conn = psycopg2.connect(connect_str)
    # cursor that to execute queries
    cursor = conn.cursor()
    # start at the beginning, select the first text field
    sql = "SELECT textfield FROM mytable WHERE id=1"
    cursor.execute(sql)
    rows = cursor.fetchall()
    print(rows)
    cont = raw_input('Type Accept Continue')
    # if user accepts it is ok to proceed, advance to display data from next textfield
    if cont=='Accept':
        print("Accepted")
        sqn = "SELECT textfield, nextitem FROM mytable WHERE id=2"
        cursor.execute(sqn)
        rows = cursor.fetchall()
        print(rows)
        result_set = cursor.fetchall()
        #ideally, this should grab the integer in the [nextitem] column from last query and select the row corresponding to the integer
        for row in result_set:
        #print the integer to test the value and make sure it is correct
            print "%s" % (row["nextitem"])
        #attempt to assign this integer to a variable?
        x=["nextitem"]
        #attempt feeding the integer previously selected in [nextitem] into the next query
        sqv = "SELECT text FROM mytable WHERE id=%s"
        cursor.execute(sqv,x)
        result = cursor.fetchall()
        print(result)
    else:
        print("Rejected or Not Accepted")
except Exception as e:
    print("No Connection Available")
    print(e)

标签: pythonpython-3.xpostgresqlpostgresql-9.6

解决方案


将您的数据库操作拆分为单独的函数。这将使程序流程更容易。

然后简单地循环,使用输入 ID 获取消息文本,显示消息,获取输入 -> 下一个 ID,重复。

您不需要“接受”条件,只需将其作为第一个文本的一部分(在 mytable.id=1 上):“输入 2 接受,q 退出”。

def openDatabase():
    connect_str = "dbname='mydatabase' user='myuser' host='localhost' password='mypassword'"
    try:
        conn = psycopg2.connect(connect_str)
    except:
        sys.stderr.write("Unable to connect to database\n")
        conn = None
    return conn

def fetchSQL(db_conn, sql_query):
    cursor = db_conn.cursor()
    # start at the beginning, select the first text field
    cursor.execute(sql_query)
    rows = cursor.fetchall()
    #print(rows)
    return rows

def fetchItemText(db_conn, item_index):
    query = "SELECT textfield FROM mytable WHERE id=" + str(item_index)
    rows = fetchSQL(db_conn, query)
    if (len(rows) > 0):
        return rows[0][0] # Maybe just be rows[0]? Coding of the top of my head
    else:
        return ""

### Main
db = openDatabase()
if (db != None):
    # do some stuff
    finished = False
    user_choice = 1
    # Prompt the user with the text, get their input
    while (not finished):
        prompt = fetchItemText(db, user_choice)
        user_choice = raw_input(prompt + "\n>>>")
        if (user_choice == 'q'):
            finished = True
        else:
            user_choice = int(user_choice)  # TODO handle errors

推荐阅读