从python中的sqlite表读取原始数据

时间:2015-10-02 08:40:43

标签: python database python-3.x sqlite

我目前正在尝试创建一个登录系统,只是为了学习一些更高级的python脚本。

最初,我使用.txt个文件来保存所有信息,但最终变得混乱和不安全。

完成第一组脚本后,我决定尝试将信息保存到数据库文件中。我已经想出如何从表中读取数据,但它周围有[(''),]

这是一个问题,因为我需要使用原始数据来比较输入,而不能用它周围的符号来完成。

所以,我想知道是否可以将数据作为原始字符串读取,而不是符号。我一直在主项目的单独文件中这样做。以下是所述文件的内容:

import sqlite3 as sql

con = sql.connect(r"E:\Users.db")
c = con.cursor()
con.row_factory = sql.Row
username = input("What is your username: ")

readdata = input("Select the message you wish to read: ")
c.execute("SELECT * FROM Mail WHERE (Subject LIKE '"+readdata+"') AND   (Recipient LIKE '"+username+"')")

component = c.fetchall()

for row in component:
    c.execute("SELECT Recipient FROM Mail WHERE (Subject LIKE '"+readdata+"') AND (Recipient LIKE '"+username+"')")
    rc = list(c.fetchall())
    rec = str(rc)
    c.execute("SELECT Sender FROM Mail WHERE (Subject LIKE '"+readdata+"') AND (Recipient LIKE '"+username+"')")
    snt = list(c.fetchall())
    sent = str(snt)
    c.execute("SELECT Subject FROM Mail WHERE (Subject LIKE '"+readdata+"') AND (Recipient LIKE '"+username+"')")
    sbject = list(c.fetchall())
    subject = str(sbject)
    c.execute("SELECT Message FROM Mail WHERE (Subject LIKE '"+readdata+"') AND (Recipient LIKE '"+username+"')")
    mg = list(c.fetchall())
    msg = str(mg)

    print()
    print("Sender: " + sent)
    print("Recipient: " + rec)
    print("Subject: " + subject)
    print()
    print("Message: " + msg)

这是输出:

What is your username: James
Select the message you wish to read: LOL

Sender: [('Kieran',)]
Recipient: [('James',)]
Subject: [('LOL',)]

Message: [('Hey',)]

这是所有正确的数据,但我需要移除[(''),]才能比较它。我使用的是Python 3.4.2。

3 个答案:

答案 0 :(得分:4)

您正在做的事情很糟糕:您执行相同请求的4次以获得4个属性,并且您将输入数据连接到查询字符串中,这可能导致sql injection

你应该重写它:

import sqlite3 as sql

con = sql.connect(r"E:\Users.db")
c = con.cursor()
con.row_factory = sql.Row
username = input("What is your username: ")

readdata = input("Select the message you wish to read: ")
c.execute("SELECT Sender, Recipient, Subject, Message FROM Mail WHERE (Subject LIKE ?) AND   (Recipient LIKE ?)", (readdata, username))

component = c.fetchall()

for row in component:
    (sent, rec, subject, msg) = tuple(row)
    print()
    print("Sender: " + sent)
    print("Recipient: " + rec)
    print("Subject: " + subject)
    print()
    print("Message: " + msg)

答案 1 :(得分:3)

您有包含所有行的列表,每行包含一系列列。如果您只想要一行,则只获取一行:

rc = c.fetchone()

现在你只有一个带有列的元组。

您可以使用索引或使用元组赋值来获取一列:

first_column = rc[0]

first_column, = rc

请注意那里的逗号。

您可以将其与c.fetchone()电话结合使用:

first_column_of_first_row, = c.fetchone()

您需要考虑使用 SQL参数来避免SQL注入(攻击者接管您的数据库时出现安全问题),并使数据库驱动程序可以在删除时优化查询来自查询本身的特定数据。您应该使用占位符而不是字符串连接('<query part>' + data + '<query part'),而是在驱动程序中添加引号:

c.execute(
    "SELECT Recipient FROM Mail WHERE (Subject LIKE ?) AND (Recipient LIKE ?)",
    (readdata, username))

现在readdatausername将插入到您在查询中放置问号的位置,并使用适当的引号来处理数据本身中的引号转义。

对于LIKE查询,您可能希望包含%通配符:

c.execute(
    "SELECT Recipient FROM Mail WHERE (Subject LIKE ?) AND (Recipient LIKE ?)",
    ('%{}%'.format(readdata), '%{}%'.format(username)))

此处str.format()调用会在开始和结束时添加%个通配符。如果没有通配符,您也可以使用COLUMNNAME = ?,因为LIKE只会匹配整个列值。

接下来,由于您要检索 4列,您可以在一个查询中获取所有4个查询,然后在循环中提取每行的结果:

c.execute(
    "SELECT Recipient, Sender, Subject, Message FROM Mail WHERE (Subject LIKE ?) AND (Recipient LIKE ?)",
    ('%{}%'.format(readdata), '%{}%'.format(username)))

for rec, sent, subject, msg in c:
    print("Sender: " + sent)
    print("Recipient: " + rec)
    print("Subject: " + subject)
    print()
    print("Message: " + msg)

我在<{1}}光标上直接循环;除非您需要一个随机访问所有行的列表,否则不需要c调用。每行包含4列,因为fetchall()按特定顺序要求这些列,因此我们可以将这些列直接分配给4个变量。

答案 2 :(得分:2)

fetchall是查询返回的所有结果的迭代器。使用list显式将此迭代器转换为其元素列表。每个元素都是一个元组,其中包含您在查询中要求的列。

因此,获取所需的元素应该是rec = rc[0][0]sent = snt[0][0]而不是rec = str(rc)sent = str(snt)

但是,您的查询和检索方式都可以改进:

c.execute("SELECT Recipient, Sender, Subject, Message FROM Mail WHERE (Subject LIKE '"+readdata+"') AND (Recipient LIKE '"+username+"')")

将在一个查询中获取所有四个变量,这对您的数据库更有效。

但请注意,使用字符串连接将参数注入查询时容易出现SQL漏洞。特别是如果变量的内容是用户提交的。您应该让sqlite驱动程序按照the docs处理它:

c.execute("SELECT Recipient, Sender, Subject, Message FROM Mail WHERE (Subject LIKE ?) AND (Recipient LIKE ?)", (readdata, username))

使用c.fetchone()只会检索此查询中的一个结果,而不必将其转换为列表。

同时将此结果影响到所有四个变量,避免使用索引手动解压缩元组:

rec, sent, subject, msg = c.fetchone()

您可以通过仅使用第一个查询来进一步简化代码,而不必每次都执行新的查询:

import sqlite3 as sql

con = sql.connect(r"E:\Users.db")
c = con.cursor()
con.row_factory = sql.Row
username = input("What is your username: ")

readdata = input("Select the message you wish to read: ")
c.execute("SELECT Recipient, Sender, Subject, Message FROM Mail WHERE (Subject LIKE ?) AND   (Recipient LIKE ?)", (readdata, username))

for rec, sent, subject, msg in c.fetchall():
    print()
    print("Sender: " + sent)
    print("Recipient: " + rec)
    print("Subject: " + subject)
    print()
    print("Message: " + msg)