简体   繁体   English

python将二进制数据插入和检索到mysql中

[英]python inserting and retrieving binary data into mysql

I'm using the MySQLdb package for interacting with MySQL.我正在使用 MySQLdb 包与 MySQL 交互。 I'm having trouble getting the proper type conversions.我无法获得正确的类型转换。

I am using a 16-byte binary uuid as a primary key for the table and have a mediumblob holding zlib compressed json information.我使用 16 字节的二进制 uuid 作为表的主键,并有一个 mediumblob 保存 zlib 压缩的 json 信息。

I'm using the following schema:我正在使用以下架构:

CREATE TABLE repositories (
    added_id int auto_increment not null,
    id binary(16) not null,
    data mediumblob not null,
    create_date int not null,
    update_date int not null,
    PRIMARY KEY (added_id),
    UNIQUE(id)
) DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ENGINE=InnoDB;

Then I create a new row in the table using the following code:然后我使用以下代码在表中创建一个新行:

data = zlib.compress(json.dumps({'hello':'how are you :D'})
row_id = uuid.uuid(4).hex
added_id = cursor.execute('
    INSERT INTO repositories (id, data, create_date, update_date) 
    VALUES (%s, %s, %s, %s)',
    binascii.a2b_hex(row_id), 
    data, 
    time.time(), 
    time.time()
)

Then to retrieve data I use a similar query:然后为了检索数据,我使用了一个类似的查询:

query = cursor.execute('SELECT added_id, id, data, create_date, update_date ' \
    'FROM repositories WHERE id = %s',
    binascii.a2b_hex(row_id)
)

Then the query returns an empty result.然后查询返回一个空结果。

Any help would be appreciated.任何帮助,将不胜感激。 Also, as an aside, is it better to store unix epoch dates as integers or TIMESTAMP?另外,顺便说一句,将unix纪元日期存储为整数还是TIMESTAMP更好?

NOTE: I am not having problems inserting the data, just trying to retrieve it from the database.注意:我在插入数据时没有问题,只是试图从数据库中检索它。 The row exists when I check via mysqlclient.当我通过 mysqlclient 检查时,该行存在。

Thanks Alot!@多谢!@

One tip: you should be able to call uuid.uuid4().bytes to get the raw bytes.一个提示:您应该能够调用uuid.uuid4().bytes来获取原始字节。 As for timestamps, if you want to perform time/date manipulation in SQL it's often easier to deal with real TIMESTAMP types.至于时间戳,如果您想在 SQL 中执行时间/日期操作,处理真正的 TIMESTAMP 类型通常更容易。

I created a test table to try to reproduce what you're seeing:我创建了一个测试表来尝试重现您所看到的内容:

CREATE TABLE xyz (
    added_id INT AUTO_INCREMENT NOT NULL,
    id BINARY(16) NOT NULL,
    PRIMARY KEY (added_id),
    UNIQUE (id)
) DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ENGINE=InnoDB;

My script is able to insert and query for the rows using the binary field as a key without problem.我的脚本能够使用二进制字段作为键插入和查询行,没有问题。 Perhaps you are incorrectly fetching / iterating over the results returned by the cursor?也许您错误地获取/迭代游标返回的结果?

import binascii
import MySQLdb
import uuid

conn = MySQLdb.connect(host='localhost')

key = uuid.uuid4()
print 'inserting', repr(key.bytes)
r = conn.cursor()
r.execute('INSERT INTO xyz (id) VALUES (%s)', key.bytes)
conn.commit()

print 'selecting', repr(key.bytes)
r.execute('SELECT added_id, id FROM xyz WHERE id = %s', key.bytes)
for row in r.fetchall():
    print row[0], binascii.b2a_hex(row[1])

Output:输出:

% python qu.py    
inserting '\x96\xc5\xa4\xc3Z+L\xf0\x86\x1e\x05\xebt\xf7\\\xd5'
selecting '\x96\xc5\xa4\xc3Z+L\xf0\x86\x1e\x05\xebt\xf7\\\xd5'
1 96c5a4c35a2b4cf0861e05eb74f75cd5
% python qu.py
inserting '\xac\xc9,jn\xb2O@\xbb\xa27h\xcd<B\xda'
selecting '\xac\xc9,jn\xb2O@\xbb\xa27h\xcd<B\xda'
2 acc92c6a6eb24f40bba23768cd3c42da

To supplement existing answers, there's also an issue with the following warning when dealing with binary strings in queries:为了补充现有答案,在处理查询中的二进制字符串时还存在以下警告问题:

Warning: (1300, "Invalid utf8 character string: 'ABCDEF'") 

It is reproduced by the following:它是通过以下方式复制的:

cursor.execute('''
    CREATE TABLE `table`(
        bin_field` BINARY(16) NOT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
''')

bin_value = uuid.uuid4().bytes
cursor.execute('INSERT INTO `table`(bin_field) VALUES(%s)', (bin_value,))

Whenever MySQL sees that a string literal in a query isn't valid against current character_set_connection it will emit the warning.每当 MySQL 发现查询中的字符串文字对当前character_set_connection无效时,它会发出警告。 There are several solutions to it:有几种解决方案:

  1. Explicitly set _binary charset literal显式设置_binary字符集文字

     INSERT INTO `table`(bin_field) VALUES(_binary %s)
  2. Manually construct queries with hexadecimal literals使用十六进制文字手动构造查询

     INSERT INTO `table`(bin_field) VALUES(x'abcdef')
  3. Changeconnection charset if you're only working with binary strings如果您只使用二进制字符串,请更改连接字符集

For more details see MySQL Bug 79317 .有关更多详细信息,请参阅MySQL 错误 79317

Update更新

As @charlax pointed out, there's binary_prefix flag which can be passed to the connection's initialiser to automatically prepend _binary prefix when interpolating arguments.正如@charlax 指出的那样,可以将binary_prefix标志传递给连接的初始化程序,以在插入参数时自动添加_binary前缀。 It's supported by recent versions of both, mysql-client and pymysql . mysql-clientpymysql的最新版本都支持它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM