使用带有MySQL-Python的INSERT INTO语句的语法错误

时间:2014-10-05 06:04:21

标签: python mysql sql mysql-python

我尝试使用以下SQL语法填充MySQL数据库中的表,其中每行的值来自文本文件:

INSERT INTO Table SET
  fieldname1 = "value1",
  fieldname2 = "value2",
  fieldname3 = "value3";

我使用嵌套的for循环来打印一个字符串(名为SQL3),该字符串对文本文件的每一行使用相同的字段名称,试图以正确的方式处理语法。好像我已经接近但它仍然向我抛出SQL语法错误,我似乎对可能发生的事情视而不见。在第一次尝试通过Python连接到数据库时,可能还有更多隐藏在下面的问题。

希望有人可以帮助找到问题。是否缺少一些重要信息?

这是代码:

import MySQLdb 

fieldNames = """Org_rowNr_countsheet
Orig_row_10604
pt3
pt3_ensembl_id
status
pt2_meth
pt3_meth
pt2_kegg_id
pt2_uniprotID
pt3_kegg_hit
pt3_uniprot
pt2_contig
pt2_start
pt2_stop
pt2_strand
pt3_contig
pt3_start
pt3_stop  
pt3_strand
"""
fieldnames = fieldnames.strip().split("\n")

myconnection = MySQLdb.connect(host = "localhost", user = 'root', passwd = "mock", db="pt3_annot")
mycursor = myconnection.cursor()

infilename = "/home/oaklander114/winshare/mysql_pt3/pt3_annot_ids_reduced.csv"
infile =  open(infilename, 'r')
linenumber = 0 

for line in infile:
    if linenumber > 0:
    line =  line.strip("\n\r")
    fields = line.split(',')
    print 'INSERT INTO ids SET '
    for i, fieldname in enumerate(fieldnames):
        query = []
        if i < 18:
            SQL1 = """
             %s = '%s',
             """ % (fieldname, fields[i])
            query.append(SQL1)
        else:
            SQL2 = """
             %s = '%s';
             """ % (FieldName, Fields[i])
            query.append(SQL2)
        SQL3 = " ".join(query)
        print SQL3
        mycursor.execute(SQL3)

    linenumber += 1
infile.close()
mycursor.close()
myconnection.commit()
myconnection.close()

这是错误消息:

ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'Org_rowNr_countsheet = '10578',' at line 1")

我认为在错误点显示语法的打印会很有用,因为脚本似乎正在生成它(看起来对我来说):

INSERT INTO ids SET
  Org_rowNr_countsheet = '10579',
  Orig_row_10604 = '',
  pt3 = '300002',

等...但错误与第一行有关。这是一个更详细的错误报告:

%run /home/oaklander114/winshare/mysql_pt3/insert_rows_ids.py
INSERT INTO ids SET
Org_rowNr_countsheet='10578',
---------------------------------------------------------------------------
ProgrammingError                          Traceback (most recent call last)
/home/oaklander114/Canopy/appdata/canopy-1.4.1.1975.rh5-x86_64/lib/python2.7/site-   packages/IPython/utils/py3compat.pyc in execfile(fname, *where)
202             else:
203                 filename = fname
--> 204             __builtin__.execfile(filename, *where)

/home/oaklander114/winshare/mysql_pt3/insert_rows_ids.py in <module>()
 52             SQL3 = " ".join(query)
 53             print SQL3
---> 54             MyCursor.execute(SQL3)
 55 
 56     LineNumber += 1

/home/oaklander114/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/MySQL_python-1.2.5-    py2.7-linux-x86_64.egg/MySQLdb/cursors.pyc in execute(self, query, args)
203             del tb
204             self.messages.append((exc, value))
--> 205             self.errorhandler(self, exc, value)
206         self._executed = query
207         if not self._defer_warnings: self._warning_check()

/home/oaklander114/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/MySQL_python-1.2.5-py2.7-linux-x86_64.egg/MySQLdb/connections.pyc in defaulterrorhandler(***failed resolving arguments***)
 34     del cursor
 35     del connection
---> 36     raise errorclass, errorvalue
 37 
 38 re_numeric_part = re.compile(r"^(\d+)")

ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds     to your MySQL server version for the right syntax to use near 'Org_rowNr_countsheet='10578',' at line 1") 

这些是ids表的列:

mysql>  SHOW COLUMNS FROM ids;
+----------------------+--------------+------+-----+---------+-------+
| Field                | Type         | Null | Key | Default | Extra |
+----------------------+--------------+------+-----+---------+-------+
| Org_rowNr_countsheet | varchar(255) | NO   | PRI | NULL    |       |
| Org_row_10604        | varchar(255) | YES  |     | NULL    |       |
| pt3                  | varchar(255) | YES  |     | NULL    |       |
| pt3_ensembl_id       | varchar(255) | YES  |     | NULL    |       |
| status               | varchar(255) | YES  |     | NULL    |       |
| pt2_meth             | varchar(255) | YES  |     | NULL    |       |
| pt3_meth             | varchar(255) | YES  |     | NULL    |       |
| pt2_kegg_id          | varchar(255) | YES  |     | NULL    |       |
| pt2_uniprotID        | varchar(255) | YES  |     | NULL    |       |
| pt3_kegg_hit         | varchar(255) | YES  |     | NULL    |       |
| pt3_uniprot          | varchar(255) | YES  |     | NULL    |       |
| pt2_contig           | varchar(255) | YES  |     | NULL    |       |
| pt2_start            | varchar(255) | YES  |     | NULL    |       |
| pt2_stop             | varchar(255) | YES  |     | NULL    |       |
| pt2_strand           | varchar(255) | YES  |     | NULL    |       |
| pt3_contig           | varchar(255) | YES  |     | NULL    |       |
| pt3_start            | varchar(255) | YES  |     | NULL    |       |
| pt3_stop             | varchar(255) | YES  |     | NULL    |       |
| pt3_strand           | varchar(255) | YES  |     | NULL    |       |
+----------------------+--------------+------+-----+---------+-------+
19 rows in set (0.00 sec)

2 个答案:

答案 0 :(得分:1)

您的代码存在许多问题,包括功能问题和风格问题。对于样式问题,我建议您阅读PEP 8 -- Style Guide for Python Code。具体来说,为包,模块和类保留CamelCase将在StackOverflow上产生更合适的语法高亮。

您在评论中说,您在FieldNames字符串中发现了拼写错误,但INSERT语句在您切换到VALUES语法之前仍然无声地失败。我没有看到INSERT语法变体与SET经常使用,但它是正确的,它确实可以使用MySQL-Python工作:

>>> curs.execute('create temporary table tbl (col1 varchar(10), col2 varchar(10))')
0L
>>> statement = r"""
... INSERT INTO tbl SET
...   col1 = "value1",
...   col2 = "value2";
... """
>>> curs.execute(statement)
1L
>>> curs.execute("select * from tbl")
1L
>>> curs.fetchall()
(('value1', 'value2'),)

所以问题出在其他地方,无论是代码还是期望。除非你清楚地描述这个新问题(并且很可能会涉及重写你的大部分问题),否则我无法确切地说出出了什么问题。但是,我可以指出你的方法存在的一些问题;解决这些问题可能会引导您找到解决方案。

当你应该编写parameterized queries时,你会浪费大量的空间从混乱的字符串构建查询。忘记从字符串到列表的所有来回,并找出你需要逗号或分号的时间;只需使用%s作为每个值的占位符来编写查询,并将这些值作为execute方法as shown in the User's Guide的第二个参数提供。

自己解析csv文件而不是简单地使用a standard library module for parsing csv files也是一种浪费,如果familiarize yourself with the with statement用于文件对象(除其他外),您将编写更好的代码。这是一种不那么容易出错的方式来做你想做的事情:

import csv
import MySQLdb 

INSERT_STATEMENT = """
  INSERT INTO ids
    VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
            %s, %s, %s, %s, %s, %s, %s, %s, %s);
"""

INPUT_PATH = '/home/oaklander114/winshare/mysql_pt3/pt3_annot_ids_reduced.csv'

connection = MySQLdb.connect(host='localhost', user='root', passwd='mock',
                             db='pt3_annot')

with open(INPUT_PATH, 'r') as input_file, connection as cursor:
    reader = csv.reader(input_file)
    next(reader, None)  # skip the header row
    for row in reader:
        cursor.execute(INSERT_STATEMENT, row)

connection.close()

关于功能的说明:

  • 如果您认真对待Python,with关键字和csv模块是必不可少的。解析csv文件是一种基本任务,您将被要求在求职面试中展示,在那里您不会花费时间和编写一百行代码。
  • 确保在使用之前了解代码,如果您遇到问题,请在此期间使用您 理解的代码。例如,next(reader, None)没有知道那里有一个标题行;我这样做,从阅读你的代码。如果您将此确切代码与没有标题的文件一起使用,那么它就会出错。
  • 使用with关键字以这种方式创建MySQLdb游标,会在with块的末尾自动提交事务。如果您想要执行单独的事务,请在单独的with块中执行。
  • 另一方面,此代码中的游标对象在程序结束之前不会关闭 - 但鉴于MySQLdb实现游标的方式,这并不是真正的问题。如果您想阅读更多内容,我对When to close cursors using MySQLdb的回答将深入探讨这一主题。
  • 您可以明确地将INSERT_STATEMENT的列名列为idsVALUES之间的元组。我把它们留在了答案中以节省空间,但这确实使SQL语句和输入文件中隐含了列的顺序。如果要重用此代码,则可能更安全地使列列表显式化。

关于风格的说明:

  • 以这种方式将SQL语句与三引号分隔符分开,可以更容易地在视觉上区分Python代码。如果您希望在SQL客户端应用程序之间进行复制和粘贴以进行测试,它还可以更轻松地选择语句。
  • 将值列表拆分到我所做的位置,可以更轻松地计算占位符的数量 - 您只需手动计算第一行的10,即可看到总共有19个。
  • 以明确标识占位符数量的方式构造MySQL语句可能更具可读性和可维护性,而无需手动计算(例如'INSERT INTO ids VALUES ({});'.format(','.join(['%s'] * 19))。请注意,此方法依然依赖于游标的execute方法来正确处理要插入的值,这非常重要。
  • 这个例子并不遵循PEP 8中的每一条准则,主要是为了保持长度不变,但它跟随大部分(你也应该如此)。

答案 1 :(得分:-1)

2件事。我会将if块从你的循环中取出并确保预先安装正确的SQL。

SQL3 = 'UPDATE table SET ' + " ".join(query) + ';'  #don't forget WHERE clause as well...

或者如果你要插入......有效的INSERT语句

您在文件中遇到空行吗?也许试试......

而不是这个(在你的问题中没有正确格式化)

for line in InFile:
    if LineNumber > 0:
    line =  line.strip("\n\r")
    #print line
    Fields = line.split(',')

试试这个:

for line in InFile:
    line =  line.strip("\n\r")
    if LineNumber > 0 and line != '':
        #print line
        Fields = line.split(',')
        #....rest of your code...