sqlite executemmany()返回“只能执行DML语句”

guz6ccqo  于 2023-08-06  发布在  SQLite
关注(0)|答案(1)|浏览(147)

我的查询适用于execute,但executemany()返回:
编程错误:executemmany()只能执行DML语句。
查询:

c.execute("SELECT * FROM Donors WHERE firstname=:First AND lastname=:Last",ds[1].donor).fetchall()

字符串
对比:

c.executemany("SELECT * FROM Donors WHERE firstname=:First AND lastname=:Last",[ds[1].donor,ds[2].donor]).fetchall()


其中ds[i].donor看起来像{'First': 'Cathy', 'Last': 'Lee'}。我是不是漏掉了什么?

jdgnovmf

jdgnovmf1#

您不能使用SELECTexecutemany()。DML代表DataModificationLanguage,SELECT不被视为modification。
你需要做的可能是在数据上循环:

for d in donors:
    cursor.execute("""
                   SELECT * FROM Donors
                   WHERE firstname=:First AND lastname=:Last
                   """, d.donor)
    print(cur.fetchall())

字符串

**更新:发现它是,见下面的更新!**编辑,我还不能弄清楚,使其可复制粘贴:您也可以使用IN(...)操作,它应该是沿着于以下内容的操作:

cur.execute("""
            SELECT * FROM Donors
            WHERE firstname IN ({0})"""
            .format(', '.join(x.donor for x in donors)))

IN子句更新:

这是一个演示如何使用占位符动态构造具有绑定参数的查询的工作示例,由@olepinto的评论引发:

import sqlite3

sqlite3.enable_callback_tracebacks(True)
con = sqlite3.connect(":memory:")
con.set_trace_callback(print)

cur = con.execute("CREATE TABLE Donors(firstname, lastname, dob)")
data = (
    {"First": "Jane", "Last": "Doe", 'Dob': 1957},
    {"First": "John", "Last": "Doe", 'Dob': 1972},
    {"First": "John", "Last": "Bar", 'Dob': 1980},
    {"First": "Jane", "Last": "Foo", 'Dob': 1943},
)
cur.executemany("INSERT INTO Donors VALUES(:First, :Last, :Dob)", data)
print("--- setup done ---", end="\n\n")

def format_with_in_clause(query, in_vals):
    # Interpolate the required number of placeholders
    return query + " IN ({0})".format(",".join(["?"] * len(in_vals)))

base_query = "SELECT * FROM Donors WHERE lastname"

# The happy path
params = ["Bar", "Foo"]
print("Happy path, all good:")
cur.execute(format_with_in_clause(base_query, params), (*params,))
print(cur.fetchall(), end="\n\n")

# DANGER: plain string interpolation is a pool of sharks :(
# Assume this is some user-input that is simply parsed into a list by upstream code
params = ["'') OR TRUE; --"] 
print("Oh dear, SQL injection at play:")
cur.execute("SELECT * FROM Donors WHERE lastname IN (%s)" % params[0])
print(cur.fetchall(), end="\n\n")

# But bound parameters tame those sharks :)
params = ["'') OR TRUE; --"]
print("Bound parameters correctly escape the attacker's payload:")
cur.execute(format_with_in_clause(base_query, params), (*params,))
print(cur.fetchall(), end="\n\n")

# Also works for other data-types than string:
base_query = "SELECT * FROM Donors WHERE dob"
params = [1943, 1957]
print("Works with numbers:")
cur.execute(format_with_in_clause(base_query, params), (*params,))
print(cur.fetchall())


这将输出以下内容:

CREATE TABLE Donors(firstname, lastname, dob)
BEGIN 
INSERT INTO Donors VALUES('Jane', 'Doe', 1957)
INSERT INTO Donors VALUES('John', 'Doe', 1972)
INSERT INTO Donors VALUES('John', 'Bar', 1980)
INSERT INTO Donors VALUES('Jane', 'Foo', 1943)
--- setup done ---

Happy path, all good:
SELECT * FROM Donors WHERE lastname IN ('Bar','Foo')
[('John', 'Bar', 1980), ('Jane', 'Foo', 1943)]

Oh dear, SQL injection at play:
SELECT * FROM Donors WHERE lastname IN ('') OR TRUE;
[('Jane', 'Doe', 1957), ('John', 'Doe', 1972), ('John', 'Bar', 1980), ('Jane', 'Foo', 1943)]

Bound parameters correctly escape the attacker's payload:
SELECT * FROM Donors WHERE lastname IN (''''') OR TRUE; --')
[]

Works with numbers:
SELECT * FROM Donors WHERE dob IN (1943,1957)
[('Jane', 'Doe', 1957), ('Jane', 'Foo', 1943)]

相关问题