英文:
MSSQL pyodbc insert failing due to range of computer representation (8 bytes)
问题
以下是您要翻译的内容:
错误信息是:
"pyodbc.DataError: ('22003', "[22003] [Microsoft][ODBC SQL Server Driver][SQL Server]The floating point value '9786E' is out of the range of computer representation (8 bytes)."
所以基本上,如果我去掉值前面的“OI-”,那么就没问题了。
值的类型是字符串。
尝试过在MSSQL中将列类型设置为varchar(max),nvarchar(max),text等等。
英文:
Can someone help me how to insert"OI-9786E543971246B29470AFA10414A1E2" value as a string to MSSQL db in python?
Error I get is:
"pyodbc.DataError: ('22003', "[22003] [Microsoft][ODBC SQL Server Driver][SQL Server]The floating point value '9786E' is out of the range of computer representation (8 bytes)."
for client in clients:
counts += 1
insert_stmt += f"INSERT INTO [x].[dbo].[x] ([commcell],[clientName],[clientDisplayName],[clientHostName],[instanceId]) VALUES ('{client['commcell']}','{client['clientName']}','{client['clientDisplayName']}','{client['clientHostName']}','{client['instanceId']}') \r\n"
if counts % 300 == 0:
insert_stmt += "COMMIT TRANSACTION"
cursor.execute(insert_stmt)
cursor.commit()
insert_stmt = "BEGIN TRANSACTION \r\n"
if insert_stmt != "BEGIN TRANSACTION \r\n":
insert_stmt += "COMMIT TRANSACTION"
cursor.execute(insert_stmt)
cursor.commit()
So basically if I would to remove OI- at the front of the value it would be ok..
Type of the value is string.
Tried column types in MSSQL to be as varchar(max), nvarchar(max), text and so on.
答案1
得分: 2
通过这种方式连接字符串,你正在对自己的代码进行SQL注入攻击。
SQL Server的插入行在SQL Server的概念验证教程中展示了如何安全地传递值给任何SQL查询,而不仅仅是对SQL Server的INSERT操作:
#示例插入查询
sql = """
INSERT INTO SalesLT.Product (Name, ProductNumber, StandardCost, ListPrice, SellStartDate)
VALUES (?,?,?,?,?)
"""
count = cursor.execute(sql,
'SQL Server Express New 20', 'SQLEXPRESS New 20', 0, 0, CURRENT_TIMESTAMP).rowcount
cnxn.commit()
print('Rows inserted: ' + str(count))
我稍微修改了示例以明确SQL查询不包括任何值。这也不是格式化字符串。参数值从不成为查询本身的一部分。它们被发送到数据库服务器,只在查询被编译成执行计划之后使用。
至少,Python代码应该更改为以下内容:
sql = """
INSERT INTO [x].[dbo].[x] ([commcell],[clientName],[clientDisplayName],[clientHostName],[instanceId])
VALUES (?,?,?,?,?)
"""
count = cursor.execute(sql,
client['commcell'],
client['clientName'],
client['clientDisplayName'],
client['clientHostName'],
client['instanceId'])
...
还可以使用executemany
一次插入多行,并设置cursor.fast_executemany = True
:
cursor.fast_executemany = True
..
tuples=[('foo','bar', 'ham'), ('hoo','far', 'bam')]
cursor.executemany(sql, tuples)
cursor.commit()
这将将所有值缓存在内存中,并一次性发送到服务器。
英文:
By concatenating strings this way you're causing a SQL injection attack against your own code.
The Insert a row in SQL Server's proof-of-concept tutorial shows how to safely pass values to any SQL query, not just INSERTs against SQL Server:
#Sample insert query
sql="""
INSERT INTO SalesLT.Product (Name, ProductNumber, StandardCost, ListPrice, SellStartDate)
VALUES (?,?,?,?,?)"""
count = cursor.execute(sql,
'SQL Server Express New 20', 'SQLEXPRESS New 20', 0, 0, CURRENT_TIMESTAMP).rowcount
cnxn.commit()
print('Rows inserted: ' + str(count))
I modified the example a bit to make it clear that the SQL query doesn't include any values. This isn't a format string either. The parameter values never become part of the query itself. They're sent to the database server and used only after the query gets compiled into an execution plan.
At the very least, the python code should change to this:
sql = """
INSERT INTO [x].[dbo].[x] ([commcell],[clientName],[clientDisplayName],[clientHostName],[instanceId]) "
VALUES (?,?,?,?,?)
"""
count = cursor.execute(sql,
client['commcell'],
client['clientName'],
client['clientDisplayName'],
client['clientHostName'],
client['instanceId'])
...
It's also possible to insert multiple rows at a time using executemany
and setting cursor.fast_executemany = True
:
cursor.fast_executemany = True
..
tuples=[('foo','bar', 'ham'), ('hoo','far', 'bam')]
cursor.executemany(sql, tuples)
cursor.commit()
This caches all values in memory and sends all of them at once to the server
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论