考虑定义的表
CREATE TABLE Example (id INTEGER)
和一个用于向Example
添加元组的INSERT
语句,在SQL注释中有一个单引号:
my_cmd = """-- Comment's device
INSERT INTO Example (id) VALUES (?)
"""
我正在通过pyodbc
模块连接MySQL。意外的效果似乎是INSERT
命令始终失败。IFF。注释中有奇数个撇号。消息中提到HY000和:
'The SQL contains 0 parameter markers, but 1 parameters were supplied'
更新:MySQL支持人员现在已经验证了该行为,因此实际上它有可能被归类为bug。请参阅Gord的回答,其中列出了另一个样本,以及指向MySQL错误数据库的注释。
下面列出了完整的测试脚本。我想知道这句话是否只是一个明白?但奇怪的是:
如果语句文本是通过ODBC传递的,那么假设注释从--
开始并延伸到行的末尾是错误的吗?(我确实在--
后面放了一个空格,为了便于移植,我使用了SQL注释。不同的注释字符或MySLQ块注释不会改变效果。)
ODBC会话的跟踪显示,对于下面列出的成功和失败案例,SQLNumParams
分别为1和0。然而,这些陈述本身看起来是既定的。我很想认为换行符是无效的。但这与下面有两个引号(my_cmd_with_two_qutoes
)或没有引号(即用"*"代替"'"的my_cmd
)的工作示例相矛盾。
还是司机的问题?
import pyodbc
my_cmd = """-- Comment's device
INSERT INTO Example (id) VALUES (?)
"""
my_cmd_with_two_quotes = """-- Comment's device's
INSERT INTO Example (id) VALUES (?)
"""
conn = pyodbc.connect("DSN=Abcdef;PWD=...")
thing_named_cursor = conn.cursor()
# success, replacing the single apostrophe:
thing_named_cursor.execute(my_cmd.replace("'", "*"), (123, ))
# success, too:
thing_named_cursor.execute(my_cmd_with_two_quotes, (456, ))
# failure:
try:
thing_named_cursor.execute(my_cmd, (789, ))
except pyodbc.Error, e:
print("Error: %s" % e)
conn.commit()
conn.close()
或者是驱动程序问题?
是。我用以下针对MySQL数据库的测试代码重新创建了您的问题
import pyodbc
cnxn = pyodbc.connect("DSN=usbMySQL")
crsr = cnxn.cursor()
sql = """
-- Comment's device
INSERT INTO Example (id) VALUES (?)
"""
crsr.execute(sql, [11])
cnxn.commit()
cnxn.close()
但是它可以与指向Microsoft SQL Server数据库的DSN(使用SQL Server Native Client 11.0)配合使用
当对MySQL数据库使用pypyodbc时,代码也会失败,所以这不仅仅是pyodbc的问题。
此外,以下VBScript代码。。。
Option Explicit
Const adParamInput = 1
Const adInteger = 3
Dim con, cmd
Set con = CreateObject("ADODB.Connection")
con.Open "DSN=usbMySQL"
Set cmd = CreateObject("ADODB.Command")
cmd.ActiveConnection = con
cmd.CommandText = _
"-- Gord's test" & vbCrLf & _
"INSERT INTO Example (id) VALUES (?)"
cmd.Parameters.Append cmd.CreateParameter("?", adInteger, adParamInput, , 121)
cmd.Execute
con.Close
失败。。。
〔MySQL〕〔ODBC 5.2(w)驱动程序〕〔mysqld-5.6.3-log〕您有一个错误在您的SQL语法中;请查看与MySQL服务器版本对应的手册,了解在"?"附近使用的正确语法在2号线
。。。但是将CommandText中的CCD_ 10更改为CCD_。。。
cmd.CommandText = _
"-- Gord''s test" & vbCrLf & _
"INSERT INTO Example (id) VALUES (?)"
允许它毫无怨言地运行。
附加信息:
记录在案,MySQL连接器/Python对问题中的原始注释字符串没有问题。这很好:
import mysql.connector
cnxn = mysql.connector.connect(port=3307, user='root', password='whatever', database='mydb')
crsr = cnxn.cursor()
sql = """
-- Comment's device
INSERT INTO Example (id) VALUES (%s)
"""
crsr.execute(sql, [101])
cnxn.commit()
cnxn.close()
您尝试过阻止注释吗?/* mycomment */
我的猜测是,在这种情况下,MySQL不认为该语言的换行符是换行符;或者连接可以将"空白"处理到最低限度,以优化发送查询(有效地去除换行符)。
我相信ODBC调用可以将sql转换为单行流。双破折号注释随后对所有内容进行注释,包括有效的sql。您需要使用块注释/*和*/。我相信有些odbc驱动程序在提交sql之前会去掉注释,所以您可能不会在所有系统中都看到这个问题。