无法将路径保存到数据库(Python/Windows)

1 投票
2 回答
1552 浏览
提问于 2025-04-18 01:52

我正在制作一个程序,目的是移动文件并把它们的新路径保存到数据库里。不过,我在拼接和执行插入数据库的SQL查询时遇到了很大的问题。

这是我的程序:

#logspc.py
import os
import sqlite3 as lite
import sys
import time

def getspc(path):
    dirs = os.listdir(path)
    spcfiles = []
    for filename in dirs:
        (shortname, extension) = os.path.splitext(filename)
        if extension == '.spc':
            spcfiles.append(filename)
    return spcfiles

src=os.path.normpath(r'C:\users\python\nonpython')
dest=os.path.normpath(r'C:\users\python\target')
files=getspc(src)
con = lite.connect('spcbase.db')
cur=con.cursor()
for mfile in files:
    oldpath=os.path.normpath(os.path.join(src,mfile))
    newpath=os.path.normpath(os.path.join(dest,mfile))
    os.rename(oldpath,newpath)
    query="INSERT INTO spectra VALUES ('" + newpath + "',SELECT date('now'))"
    print query
    cur.execute(query)
con.close()    

在“cur.execute(query)”这一行程序崩溃了,出现了以下错误:

Traceback (most recent call last):
  File "C:/Users/Python/logspc2.py", line 27, in <module>
    cur.execute(query)
OperationalError: near "SELECT": syntax error

打印出来的query变量的值是

INSERT INTO spectra VALUES ('C:\users\python\target\Bertil.spc',SELECT date('now'))

接下来我该怎么做呢?

2 个回答

0

我也遇到了同样的问题,找到了解决办法:

http://www.experts-exchange.com/questions/28401790/Inserting-dir-filename-to-mysql-from-Python.html

在我的程序中,我在一个微软的驱动器里进行递归搜索,fpath是在for循环中用os.path定义的。

print fpath returns -> C:\myfolder\myfile.zip

我发现它会按照打印的内容进行插入。

fpath2 = fpath.replace('\\','\\\\')
SQL = 'INSERT INTO all_zip_files(fpath_zip,status) VALUES("%s", "0");' % (fpath2)

我还发现需要以一种特殊的方式定义根目录:

PATH = r"c:\" #fails
PATH = r"c:" #works however execute(SQL) fails becaue path becomes c:myfolder\myfile.zip after using fpath.replace('\\',\\\\')
PATH = os.path.normpath("c:/") #WORKS with fpath.replace('\\','\\\\') to create desired windows path for my db

这个方法对我有效,不过这里还有一个“更好”的解决方案:

在Python中将文件夹位置作为SQL参数传递会导致错误

3

在SQLite中,获取当前日期的语法是CURRENT_DATE(CURRENT_TIME和CURRENT_TIMESTAMP也可以用):

 INSERT INTO spectra VALUES ('C:\users\python\target\Bertil.spc', CURRENT_DATE)

另外,养成使用参数化查询的习惯,而不是把SQL语句写成字符串,这样做是个好习惯:

 cur.execute(
     'INSERT INTO spectra (PathCol, DateCol) VALUES (?, CURRENT_DATE)',
     [newpath]
 )

这样可以让你的程序更“安全”,因为没有人能通过把SQL代码夹带在你用来构建字符串的值中来偷偷修改你的语句。虽然在你的程序中这不是个大问题*(因为newpath的值不是用户提供的),但如果文件名中包含一些可能让SQLite的字符串解析器困惑的字符,这样做也会有所帮助。

最后,另一个好习惯是在INSERT语句中包含你要插入值的列名。这样可以让你的代码更稳健——如果没有列名的话,如果表的结构被重新定义,列的数量或顺序发生变化,你的代码就会出错。通过明确列出列名,你的代码可以在很多常见的表结构重新定义情况下继续正常工作。

* 其实这是个有趣的问题——在任何文件系统中,是否存在通过路径和文件名进行SQL注入的方法?我觉得这可能是可行的!

撰写回答