【问题标题】:Query SQLite3 database with SELECT and parameters like with INSERT使用 SELECT 和 INSERT 等参数查询 SQLite3 数据库
【发布时间】:2019-10-11 18:37:35
【问题描述】:

我有一个带有 1 个表和许多列的 SQLite3 数据库。这些列是 REAL、INTEGERS 和 TEXT 的混合。一些文本条目包含日期时间。

我想在表格中插入行而不添加重复项。该表的列比我插入的数据多。为此,我想首先在表中查询包含我要插入的所有数据的任何行。如果表中不包含具有匹配参数集的行,则插入该行。

如果表当前有 2 行并且如下所示:

a, b, c, d 
2019-09-20 00:00:00, 1.1, 'DOG', nan 
2019-10-20 10:00:00, 2.2, 'CAT', -2000

插入一行很简单:

insert_vals = [datetime.datetime(2019, 9, 27, 0, 0), 123.4, 'DOG']
column_names = ['a', 'b', 'c']
strDBInsert = "INSERT INTO table_name ({}) VALUES ({})".format(column_names, strQuestions)
conn = sqlite3.connect('db_name.db')
c= conn.cursor()
c.execute(strDBquery, insert_vals)
conn.commit()

但是,是否可以像下面类似的方式查询数据库?

strDBquery = "SELECT * FROM table_name WHERE {} LIKE {}".format(column_names, insert_vals)
c.execute(strDBquery, insert_vals)
queryData = c.fetchall()

我得到的错误是

 sqlite3.OperationalError: near ",": syntax error

我希望输出:

print(queryData)
Output: [datetime.datetime(2019, 9, 27, 0, 0), 123.4, 'DOG', nan]

我认为我需要选择的另一个选项是:

c.execute("SELECT * FROM table_name WHERE a == datetime.datetime(2019, 9, 27, 0, 0), AND b == 123.4 AND c == DOG")

关于更多上下文,我正在使用 python 和 pandas 来读取包含股票交易的 csv,并且我想用新交易更新数据库。然后我想在该交易表中填写其他信息,并使用数据库中的另一个表来保存投资组合信息。也许有一种更简单的方法可以在没有查询然后插入选项的情况下完成大部分操作。

其他一些类似的问题:

SQLite3 querying a database with '?' placeholders

SQLite3 LIKE query with UTF-8 encoding

【问题讨论】:

  • 也许另一种选择只是构建一个带有列标题和值的字符串conditions = " AND ".join("{0} == {1}".format(x,y) for x,y in zip(column_names,insert_vals))
  • 现在最后的提示:如果您在构造 SQL 语句时遇到问题,第一步应该始终是检查(即打印和查看)完整的 SQL 字符串。这直接触及了问题的核心,而不是猜测各种代码可能会做什么。目标是创建格式正确的 SQL,那么为什么不直接查看呢?在执行之前查看strDBquery 的最终值,看看它的样子。这些细节也应该包含在 Stack Overflow 上的问题中。编辑问题以添加此类详细信息。
  • 主要问题是有效的,但头脑风暴的风格是......呃......在 Stack Overflow 上不是传统的。如果您有想法(例如各种选项和其他 SO 问题),那么最好先尝试一下,如果所有可能的解决方案都没有按预期运行,请提出问题。所有选项都非常接近工作,但只是有小的语法问题或误解,所以感觉就像您要求我们修复您的拼写错误和语法错误......通常可以通过审查和研究自己发现的细节语法等

标签: python sql pandas sqlite


【解决方案1】:

当出现语法和参数问题时,首先转到文档。一般 SO 答案不是完整的教程,但是问题和示例有许多语法错误,因此以下段落解释了一些基本的 sqlite SQL 概念。要继续编写这样的代码并避免出现这么多问题,就应该学习 SQL 语法。

字符串值must be in quotes,就像在任何其他编程语言中一样。像 c == DOG 这样的东西会被解释为 DOG 一个数据库对象或关键字,而不是一个值。

LIKE operator 用于将字符串与模式匹配。一般值的相等比较不一定好。它也不是用于比较任何数据类型的值的自动操作符。它支持单个参数,而不是参数列表。如果您需要匹配多个字符串,则必须包含多个 LIKE 语句,每个列和/或比较一个。

没有实际的日期或时间data types for sqlitefunctions 用于处理日期,但它们用于将日期值生成为字符串和/或数字朱利安表示。预期的字符串格式是 ISO-8601 格式,例如 YYYY-MM-DD HH:MM:SS.SSS。有一个datetime() 函数,但它不接受问题中猜测的参数。还有没有从 SQL 引用宿主语言函数,所以像 datetime.datetime() 这样的东西不起作用。

小心杂乱的逗号。


这个猜测中的整体模式将最接近一个好的解决方案:

c.execute("SELECT * FROM table_name WHERE a == datetime.datetime(2019, 9, 27, 0, 0), AND b == 123.4 AND c == DOG")

该语句的更正版本如下所示。日期时间比较将作为与列a 的字符串比较执行,因此假定列a 先前使用相同格式保存。如果不是这样,则需要对任何日期时间值进行不同的操作和比较。

c.execute("SELECT * FROM table_name WHERE a == datetime('2019-09-27 00:00:00') AND b == 123.4 AND c == 'DOG'")

该语句当然可以从column_namesinsert_vals 之类的列表中生成,但由于数据类型不同,它不会像其他猜测那样是一个简单、统一的分隔符。您需要某种形式的数据类型条件来为每列准备比较表达式。

【讨论】:

    猜你喜欢
    • 2011-12-10
    • 2013-04-19
    • 1970-01-01
    • 2015-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多