- 论坛徽章:
- 0
|
最近由于工作需要,研究了下不同数据库之间的数据移植,尤其是图像数据的移植。
有些收获,也有些疑问,写下来还请大家指点。
文本信息的移植我就不多说了,主要说下图像数据的移植。
首先谈谈将mysql里的image数据移植到sybase下:
先看mysql.
当你用python获取一个image字段值的时候:
import MySQLdb
db = MySQLdb.connect('localhost','root','','testdb')
c = db.cursor()
c.execute("select imagerow from imagetable where imageid='xx'")
getimage = c.fetchone()
这个时候 getimage是个元组,但是如果取它的值的话:
getimage = getimage[0],然后你执行 type(getimage),python会告诉你这是一个array. ( 'array.array')
它的值类似于:
array('c', '\x02\xc2\x12\x00\x00\x01\x00\x00\x00\x80\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x
0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf4\xff\xff\xb4\xe7L:nKP@!\xc9m\'\xa1\xce\xbd;m\t\x8
\n\x85B\xe1\x16\xecw\x0b\xf8\xd3\xd8O\xdc-\xe5\x0f\\xff\'\xb9o\xf6\x98}\xdc\xad\xfe\x99\x90sy\x9d\xc7\
5Ec\x9e\xf1\xe0\x1e\x93\xae(z\xc7p9\\\xd0\xecmh\xdb ..... )
关于array模块,大家可以查看python自带的手册,有详细说明。
现在,我们来看获取sybase数据库的image字段:
import Sybase
db = Sybase.connect("database_server_name","user","pswd","testdb")
c = db.cursor()
c.execute("select imagerow from imagetable where imageid='xx'")
getimage = c.fetchone()
同样的,我们用type(getimage[0]),python告诉你这是一个'str'。
它的值类似于:
'bdm\xae]_\xf7y\x15\x98o<^m\xb9\xa1\xaa\x04"\x14\xa7\x1\x89\xe3H\xd8\x01\xe9\x813\xe4\xaf\xc3\xc0\x82\xc0\
x83d\x81\xb0\x91\xf7\x80|\xe9BG43\x9f\x82\xf2\xad\r\xeb\x .... '
问题出来了:从mysql里弄出来的图像数据肯定要转换一下,否则即使你直接插到sybase里了,前台程序在读取这个图像的时候也会报错。
回到上面,从mysql里获取的图像给了getimage之后它是一个array,换个说法就是:getimage有array模块的属性。
array模块有个 'tostring()'方法,可以将array转换成一个字符串(机器码),那么,这就好办了,我们执行:
ss = getimage.tostring().这个时候,我们得到一个字符串,类似于从sybase里获取的图像文件的一个字符串。
如果这个时候把这个字符串直接插到数据库里是不可能的,仔细观察就会发现,这个字符串(可能用字符串不太合适)包含大量的
有特殊含义的字符,直接插SQL 肯定报错。
这个时候又要用到array模块了。这也是我不理解的地方,还请前辈指教。
刚才我们得到的 ss 是array转换后的字符串,现在执行:
import array
ss = array.array('B',ss)
('B'代表int型。)
现在的ss是个列表,呵呵,python就这么神奇。它的值类似:
[40, 20, 10, 133, 66, 161, 80, 40, 20, 10, 133, 6 161, 80, 40, 20
,10, 133, 66, 161, 80, 40, 20,, 133, 191, 138, 250, 55, 85, 223,
15, 249, 95,91, 244, 31, 128, 50, 225, 2, 212, 127, 32, 226 ...]
然后: ss = array.array('B',ss).tostring()
又得到一个字符串~! 你可能会说我带你绕弯那,转来转去又转成字符串了。这也是我的疑问所在:
为什么从mysql里获取array后,使用tostring()方法得到的字符串不能直接插到sybase里,而使用
ss = array.array('B',ss)得到一个列表,然后把这个列表转换成一个字符串就可以了哪?
我对比过这两个字符串,并没有转义特殊字符。关于这一点,恳请前辈指教。
好了,现在我们可以把 ss = array.array('B',ss).tostring() 转换后的字符串插到sybase的imagerow里了:
c.execute("update imagetable set imagerow='%s'"%(ss))
但是每个数据库的特性也决定了写入图像数据的时候有不同的方法,如果对于mysql,这样做就可以了,
但是对与sybase,这样做其实并没有把数据真正写入,只写入了图像的基本信息。还需要用如下方法。
c.execute("select imagerow from imagetable where imageid='xx'")
r = c.getImageDesc(0)
c.writeImageData(r[0],ss)
如果返回1代表成功,0代表失败。
至此,从mysql里选择的图像数据才真正写入sybase里了。
这个脚本整理一下大概是这样:
import MySQLdb
import Sybase
import array
dbmysql = MySQLdb('localhost','root','','testdb')
dbsybase = Sybase('database_server_name','user','pswd','testdb')
my = dbmysql.cursor()
sy = dbsybase.cursor()
my.execute("select imagerow from imagetable where imageid='xx'")
b = my.fetchone()
b = b[0].tostring()
b = array.array('B',b)
ss = array.array('B',b).tostring()
sy.execute("update imagetable set imagerow='%s' where imageid='xx'"%(ss))
dbsybase.commit()
sy.execute("select imagerow from imagetable where imageid='xx'")
r = sy.getImageDesc(0)
sy.writeImageData(r[0],ss)
另外要说明几点:
要把一个图像数据写入mysql里的时候,要用MySQLdb.escape_string(ss) 把字符串的特殊字符转义掉。
关于这一点在《python cookbook》一书中有详细说明。
如果你操作的是informix数据库,那么用select 语句查出来的图像数据是一个dbiRaw对象,你需要
str(dbiRaw)转换成字符串。
这些是我这几天的心得和疑问,如果有什么不对的地方恳请指点一二。 |
|