>我有一个PostgreSQL 9.4.5表,其中有一列具有基本字符数据类型,即创建如下:
CREATE TABLE films (
code char(5) CONSTRAINT firstkey PRIMARY KEY,
title varchar(40) NOT NULL);
然后,我使用 QSqlQuery 插入数据,使用绑定的 QByteArray:
QSqlQuery query;
query.prepare("INSERT INTO films VALUES (1, ?)");
const QByteArray film("Avatar");
query.addBindValue(film);
query.exec();
在 Ubuntu 15.10 上,电影名称以字节形式进入表中:
x417661746172
在Windows上,它作为字符进入。
在不显式将QByteArray转换为QString的情况下,有没有办法告诉QSqlQuery或PostgreSQL将数据视为字符串,因此它可以像在Windows上一样在Ubuntu上运行?
QByteArray
没有关于它所包含的字符串编码的信息(甚至它包含的字节序列可以被解释为编码字符串(。
如果它恰好包含 UTF-8 编码的字符串,您可以
-
将其绑定为带有
QString::fromUtf8(film.constData())
的字符串,而不仅仅是film
-
让 Qt 驱动程序将其作为
bytea
传递,但让 PostgreSQL 通过 INSERT 查询将其转换为文本:query.prepare("INSERT INTO films VALUES (1, convert_from(?,'UTF-8')))");
这也适用于其他编码,UTF-8
上面就是一个例子。
关于Windows/Ubuntu之间的区别:目前尚不清楚为什么QtSql的行为会有所不同,但也许这是postgres配置的差异。
'x417661746172'
是 UTF-8 中 Avatar
的文本表示形式,但仅当 bytea_output
设置为 hex
时。如果bytea_output
设置为escape
,那将是完全Avatar
的,与文本本身无法区分。
psql 命令行客户端中的示例:
test=> set bytea_output=hex;
SET
test=> select 'Avatar'::bytea;
bytea
----------------
x417661746172
(1 row)
test=> set bytea_output=escape;
SET
test=> select 'Avatar'::bytea;
bytea
--------
Avatar
(1 row)
bytea
的转义也发生在客户端的驱动程序(如QPSQL
(中,并且hex
风格仅在PostgreSQL 9.0之后可用。在此之前,escape
是唯一的方法,bytea_output
参数不存在。我相信,简单地将QtSql与Windows机器上早于9.0
的libpq链接可能会解释为什么在最近的Ubuntu上你会得到"类似文本"的外观而不是"类似十六进制"的外观。
尝试使用 bindValue
而不是 addBindValue
。请参阅此链接。
我在Windows上有同样的Qt 5.6和debian上的PostgresSQL 9.6。当使用 64 位编译时,bytea 被读取为二进制。当使用 32 位编译时,bytea 被读取为十六进制。
CREATE TABLE image (
id serial,
name text,
picture bytea
);
sql_query.prepare("SELECT id, name, picture FROM image");
...
QByteArray name = sql_query.value("name").toByteArray();
QByteArray Picture = SQL_query.value("Picture").toByteArray();
varchar read with both (32-bit and 64-bit) into QByteArray as string.
//Output 64-Bit application:
name = "Test", Picture = "‰PNGrnx1an ..."
//Output 32-Bit application:
Name = "Test", Picture = "x89504e470d0a1a0a0000..."
我在打开以下查询后添加,现在可以工作了
QSqlQuery sql_query;
sql_query.exec("SET bytea_output = 'escape'");
两个 postgres 驱动程序都来自 pg 9.5,64 位来自已安装的 Postgres,32 位是在 zip 文件中下载的。两者都有相同的名称"libpq.dll">