使用pyodbc在Ubuntu上插入SQL Server的像场(using pyodbc on ub

2019-06-24 11:18发布

我使用Ubuntu 9.04

我已经安装了以下包版本:

unixodbc and unixodbc-dev: 2.2.11-16build3
tdsodbc: 0.82-4
libsybdb5: 0.82-4
freetds-common and freetds-dev: 0.82-4
python2.6-dev

我已经配置/etc/unixodbc.ini是这样的:

[FreeTDS]
Description             = TDS driver (Sybase/MS SQL)
Driver          = /usr/lib/odbc/libtdsodbc.so
Setup           = /usr/lib/odbc/libtdsS.so
CPTimeout               = 
CPReuse         = 
UsageCount              = 2

我已经配置/etc/freetds/freetds.conf是这样的:

[global]
    tds version = 8.0
    client charset = UTF-8
    text size = 4294967295

我已经抓住pyodbc修订31e2fae4adbf1b2af1726e5668a3414cf46b454fhttp://github.com/mkleehammer/pyodbc ,它使用“安装python setup.py install

我有一个Windows机器安装在我的本地网络上的Microsoft SQL Server 2000中 ,并监听本地IP地址10.32.42.69。 我有一个名为“公共”创建一个空数据库。 我有用户“sa”,密码为“秘密”具有完全权限。

我用下面的python代码设置的连接:

import pyodbc
odbcstring = "SERVER=10.32.42.69;UID=sa;PWD=secret;DATABASE=Common;DRIVER=FreeTDS"
con = pyodbc.connect(odbcstring)
cur = con.cursor()

cur.execute("""
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
      WHERE TABLE_NAME = 'testing')
   DROP TABLE testing
""")
cur.execute('''
CREATE TABLE testing (
    id INTEGER NOT NULL IDENTITY(1,1), 
    myimage IMAGE NULL, 
    PRIMARY KEY (id)
)
    ''')
con.commit()

一切正常了这一点。 我用的SQLServer的企业管理器的服务器和新的表是存在的。 现在我想要插入表中的某些数据。

cur = con.cursor()
# using web data for exact reproduction of the error by all.
# I'm actually reading a local file in my real code.
url = 'http://www.forestwander.com/wp-content/original/2009_02/west-virginia-mountains.jpg'
data = urllib2.urlopen(url).read()

sql = "INSERT INTO testing (myimage) VALUES (?)"

现在,在这里我原来的问题,我在使用麻烦cur.execute(sql, (data,))但现在我已经编辑了问题,因为以下(感谢)以下的Vinay Sajip的回答,我已经把它改为:

cur.execute(sql, (pyodbc.Binary(data),)) 
con.commit()

插入正常使用 。 我可以确认使用以下测试代码插入数据的大小:

cur.execute('SELECT DATALENGTH(myimage) FROM testing WHERE id = 1')
data_inside = cur.fetchone()[0]
assert data_inside == len(data)

其中通过完美

现在的问题是上回数据的检索。

我想了常用的方法:

cur.execute('SELECT myimage FROM testing WHERE id = 1')
result = cur.fetchone()
returned_data = str(result[0]) # transforming buffer object
print 'Original: %d; Returned: %d' % (len(data), len(returned_data))
assert data == returned_data

但是失败了!

Original: 4744611; Returned: 4096
Traceback (most recent call last):
  File "/home/nosklo/devel/teste_mssql_pyodbc_unicode.py", line 53, in <module>
    assert data == returned_data
AssertionError

我已经把所有的代码上面的在一个文件在这里 ,对于希望帮助人的简单的测试。

现在的问题:

我想Python代码插入图像文件到MSSQL。 我要查询的图像回来了,它显示给用户。

我不关心MSSQL列类型。 我现在用的是“ IMAGE的例子”列的类型,但我得到我插回未受破坏的文件中的二进制数据的任何二进制/ BLOB类型会做,只要。 维奈Sajip下面说,这是在SQL SERVER 2000该优选数据类型。

现在的数据被插入没有错误,但是当我检索数据,只有4K返回。 (数据被截断上4096)。

我怎样才能使这项工作?


EDITS:维奈Sajip的回答下面给我提示使用pyodbc.Binary在球场上。 我有相应的更新问题。 感谢维奈Sajip!

亚历克斯·马尔泰利的评论给我使用的想法DATALENGTH MS SQL函数测试数据被完全加载在柱上。 感谢亚历克斯·马尔泰利!

Answer 1:

呵呵,只是提供赏金后,我已经找到了解决办法。

你必须使用SET TEXTSIZE 2147483647上查询,除了在文字大小配置选项的/etc/freetds/freetds.conf

我用过

cur.execute('SET TEXTSIZE 2147483647 SELECT myimage FROM testing WHERE id = 1')

和一切工作正常。

奇怪的是什么freetds的文件说,有关文本大小配置选项:

默认值TEXTSIZE ,以字节为单位。 textimage数据类型,设定任何返回的列的最大宽度。 参看 set TEXTSIZE将在T-SQL为您的服务器文档。

该配置还表示,最大值(和默认值)为4,294,967,295。 但是试图使用该值在查询中我得到一个错误时,最大数量,我可以在查询中使用为2,147,483,647(一半)。

从这个解释,我以为只有设置此配置选项就足够了。 事实证明,我错了,在解决了该问题的查询设置TEXTSIZE。

下面是完整的工作代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pyodbc
import urllib2

odbcstring = "SERVER=10.32.42.69;UID=sa;PWD=secret;DATABASE=Common;DRIVER=FreeTDS"
con = pyodbc.connect(odbcstring)
cur = con.cursor()

cur.execute("""
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
      WHERE TABLE_NAME = 'testing')
   DROP TABLE testing
""")

cur.execute('''
CREATE TABLE testing (
    id INTEGER NOT NULL IDENTITY(1,1), 
    myimage IMAGE NULL,
    PRIMARY KEY (id)
)
    ''')

con.commit()
cur = con.cursor()
url = 'http://www.forestwander.com/wp-content/original/2009_02/west-virginia-mountains.jpg'
data = urllib2.urlopen(url).read()

sql = "INSERT INTO testing (myimage) VALUES (?)"
cur.execute(sql, (pyodbc.Binary(data),))
con.commit()

cur.execute('SELECT DATALENGTH(myimage) FROM testing WHERE id = 1')
data_inside = cur.fetchone()[0]
assert data_inside == len(data)

cur.execute('SET TEXTSIZE 2147483647 SELECT myimage FROM testing WHERE id = 1')
result = cur.fetchone()
returned_data = str(result[0])
print 'Original: %d; Returned; %d' % (len(data), len(returned_data))
assert data == returned_data


Answer 2:

我想你应该使用pyodbc.Binary实例来包装数据:

cur.execute('INSERT INTO testing (myimage) VALUES (?)', (pyodbc.Binary(data),))

检索应

cur.execute('SELECT myimage FROM testing')
print "image bytes: %r" % str(cur.fetchall()[0][0])

更新:问题出在插入。 更改插入SQL以下几点:

"""DECLARE @txtptr varbinary(16)

INSERT INTO testing (myimage) VALUES ('')
SELECT @txtptr = TEXTPTR(myimage) FROM testing 
WRITETEXT testing.myimage @txtptr ?
"""

我也更新我在使用中检索代码的价值属性所犯的错误。

有了这个变化,我能够插入和检索一个320K JPEG图像到数据库(检索的数据是相同的插入的数据)。

NB的image数据类型已被弃用,被替换varbinary(max)在SQL Server的更高版本。 用于插入/检索相同的逻辑应适用,然而,对于较新的列类型。



Answer 3:

我有一个类似4096上截断问题TEXT字段, SET TEXTSIZE 2147483647固定的,对我来说这也是固定对我来说:

import os
os.environ['TDSVER'] = '8.0'


文章来源: using pyodbc on ubuntu to insert a image field on SQL Server