我使用的 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

我已经从31e2fae4adbf1b2af1726e5668a3414cf46b454f使用抓起pyodbc修订http://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()

一切的 WORKS 到这一点。我用的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,))但现在我已经编辑了问题,因为按照以下(感谢)维奈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 :下面的Vinay Sajip的回答给了我一个提示使用pyodbc.Binary在球场上。我有相应的更新问题。感谢维奈Sajip!

亚历克斯·马尔泰利的评论给我使用DATALENGTH MS SQL函数测试数据是否完全上柱的主意。感谢亚历马尔泰利!

有帮助吗?

解决方案

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

您必须使用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文档。

该配置还表示,最大值(和默认值)是4294967295。但是试图使用该值在查询中我得到一个错误时,最大数量,我可以在查询中使用为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

其他提示

我觉得你应该使用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图像到数据库(检索到的数据是相同的插入的数据)。

N.B。该image数据类型已过时,并通过varbinary(max)在SQL Server的更高版本所取代。用于插入同样的逻辑/检索应适用,然而,对于较新的列类型。

我对4096领域,其中TEXT固定对我来说是类似SET TEXTSIZE 2147483647截断的问题,但是这也固定为我:

import os
os.environ['TDSVER'] = '8.0'
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top