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

时间:2014-04-08 13:23:49

标签: python sql

我制作的程序可以移动文件并将新路径保存在数据库中。 但是,我确实将组合并执行将它们插入数据库的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(查询)",呈现此错误:

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

打印的查询变量的值是

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

我从哪里开始?

2 个答案:

答案 0 :(得分: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注入您用于构建字符串的值之一来将SQL隐藏到语句中。虽然这对您的特定程序来说并不是真正的问题*(因为用户不提供newpath值),但在文件名包含可能会混淆SQLite的字符串解析器的字符的情况下,它也会帮助您。 / p>

最后,另一个好的做法是在INSERT语句中包含INSERT值的列的名称。这使得您的代码不那么脆弱 - 没有列名,如果表使用不同的列数或不同的列顺序重新定义,那么您的代码将会中断。通过明确列出列名,您的代码可以在许多常见的表重新定义方案中存活下来。

* 实际上,这是一个有趣的问题 - 在任何文件系统上是否存在通过路径和文件名执行SQL注入的方法?我认为它实际上是可能的!

答案 1 :(得分:0)

遇到同样的问题并找到解决方案:

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

对于我的程序我在Microsoft驱动器中进行递归搜索,fpath是用for循环中的os.path定义的。

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

我认为它会完全按照打印的方式插入INTO。

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

这对我有用,但是这里提出了一个“更好”的解决方案:

Passing a folder location as an SQL parameter in python causes an error