SQLite 的绑定错误数量不正确

Incorrect Number of Bindings Error with SQLite

一些背景知识我在 python 2.7 中这样做是为了通过 SeoLib 获得 Alexa 排名,但如果这有助于解决这个问题或可能解决未来的问题,我完全愿意更新。

现在这个程序对我在预先确定的 csv 中拥有的网站进行排序,如下所示:

site
00rbt.com

我特别收到以下错误:

 File "igorPanda.py", line 84, in <module>
    update_site(site,cur_ip,cur_rank,cur_hash)
  File "igorPanda.py", line 30, in update_site
    (site))
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 9 supplied.

发生此错误的位置是:

def update_site(site,cur_ip,cur_rank,cur_hash):
    conn = sqlite3.connect('/root/Database/Sites.db')
    cursor = conn.cursor()
    with conn:
        cursor.execute("SELECT EXISTS(SELECT * from sites WHERE site = ?)",
                       (site))
        record = cursor.fetchone()
        if record[0] == 1:
            cursor.execute("UPDATE sites SET cur_ip = ?, cur_rank = ?, cur_hash = ? WHERE site = ?",
                       (cur_ip,cur_rank,cur_hash,site))
        else:
            cursor.execute("INSERT into sites values (?,?,?,?,?,?,?,?)",
                       (site,cur_ip,None,cur_rank,None,None,cur_hash,None))

除了导入之外,我的整个代码是:

#Updates the DB
def update_site(site,cur_ip,cur_rank,cur_hash):
    conn = sqlite3.connect('/root/Database/Sites.db')
    cursor = conn.cursor()
    with conn:
        cursor.execute("SELECT EXISTS(SELECT * from sites WHERE site = ?)",
                       (site))
        record = cursor.fetchone()
        if record[0] == 1:
            cursor.execute("UPDATE sites SET cur_ip = ?, cur_rank = ?, cur_hash = ? WHERE site = ?",
                       (cur_ip,cur_rank,cur_hash,site))
        else:
            cursor.execute("INSERT into sites values (?,?,?,?,?,?,?,?)",
                       (site,cur_ip,None,cur_rank,None,None,cur_hash,None))
#Moves CSV for Historical Savings
bashmove = "mv top.csv /root/Desktop/scripts/results-igor/top-$(date +%m-%d-%Y).csv"
#Sets file with all sites to variable
filename='/root/Desktop/scripts/sorted.csv'
#Creates hash algorithm for later use
hasher = hashlib.sha256()
sess = requests.Session()
x = datetime.datetime.now()
date = x.strftime('%Y-%m-%d')
regex = r"^(?:https?:)?(?:\/\/)?(?:[^@\n]+@)?(?!www\.)?([^:\/\n]+)\w*\.\b(com|org|co|be|de|br|(\w+\b))" #regex to get stripepd website no https://www. or anything afte$

df = pd.DataFrame()
df = df.append(pd.read_csv(filename), ignore_index=True)
ip = "NOT FOUND"
for i in df.index:
    #print(i)
    site = df['site'][i]
    try :
     ip = socket.gethostbyname(site)
     page = requests.get('http://' + df['site'][i], timeout=5)
     hasher.update((page.text).encode('utf-8'))
    except: #ignore errors if the site is bad
        pass
    try :
     alexa_rank = seo.get_alexa('http://{}'.format(site)) #seolib gets the alexa ranking
     #alexa_rank = None
    except:
     pass
    site = site
    cur_ip = ip
    cur_rank = alexa_rank
    cur_hash = hasher.hexdigest()
    update_site(site,cur_ip,cur_rank,cur_hash)  
    rd = call(["/root/Desktop/scripts/./rDNSlookup.sh", site, ip]) #call bash script to get reverse DNS of ip
    wi = call(["/root/Desktop/scripts/./whois.sh", site]) #call bash script to print host info
    with open('/root/Desktop/scripts/IGOR_His/'+ date + 'sites.csv', 'a') as f:
      print >> f, 'site: ',site,', ip: ',ip,', rank: ',alexa_rank, ', hash', cur_hash
shutil.copy("/root/Database/Sites.db", "/var/www/html/sites/Sites.db")

table有以下列:

site,cur_ip,prev_ip,cur_rank,prev_rank,play,cur_hash,prev_hash

TL;DR: 使用 (site,)

详细:

cursor.execute 期望第二个参数是可迭代的。

当您的代码显示:

cursor.execute("SELECT EXISTS(SELECT * from sites WHERE site = ?)", (site))

那么 (site) 不是元组 - 您可能打算通过将其包装在 ().

中将其转换为元组

所以你 meant/want 是:

cursor.execute("SELECT EXISTS(SELECT * from sites WHERE site = ?)", (site,))

注意额外的 ,!

为避免这种元组混淆,您还可以使用列表:

cursor.execute("SELECT EXISTS(SELECT * from sites WHERE site = ?)", [site])

问题更详细:

cursor.execute("SELECT EXISTS(SELECT * from sites WHERE site = ?)", (site))

等同于:

cursor.execute("SELECT EXISTS(SELECT * from sites WHERE site = ?)", site)

与(在您的情况下)相同:

cursor.execute("SELECT EXISTS(SELECT * from sites WHERE site = ?)", "00rbt.com")

字符串 00rbt.com 被用作可迭代对象,由于它有 9 个字符,您会得到错误:

sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 9 supplied.

你得到这个错误,因为这里:

cursor.execute("SELECT EXISTS(SELECT * from sites WHERE site = ?)", (site))

你应该传递,作为 execute() 的第二个参数网络,一个元组而不仅仅是一个字符串。
这很容易通过添加这样的逗号来解决:

cursor.execute("SELECT EXISTS(SELECT * from sites WHERE site = ?)", (site,))

但是,如果您的 SQLite 版本是 3.24.0+,您应该考虑采取不同的方法,选择 UPSERT 作为执行您想要的操作的方法。
如果 site 值在 table 中不存在,您想要插入一个新行,或者如果它存在,则更新现有行。

因此,假设列 site 已经有一个唯一约束,您可以使用以下方法更有效地做到这一点:

sql = """
INSERT into sites values (?,?,?,?,?,?,?,?)
ON CONFLICT(site) DO UPDATE SET
cur_ip = EXCLUDED.cur_ip, cur_rank = EXCLUDED.cur_rank, cur_hash = EXCLUDED.cur_hash
"""
cursor.execute(sql, (site,cur_ip,None,cur_rank,None,None,cur_hash,None))