QSqlQuery 将 QByteArray 作为字符串插入 PostgreSQL

QSqlQuery inserting QByteArray as string into PostgreSQL

我有一个 PostgreSQL 9.4.5 table 有一个基本字符数据类型的列,即像这样创建的:

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,电影名称进入 table 作为字节:

\x417661746172

在 Windows 上,它作为字符输入。

在不显式地将 QByteArray 转换为 QString 的情况下,有什么方法可以告诉 QSqlQuery 或 PostgreSQL 将数据视为字符串,因此它可以像在 Windows 上一样在 Ubuntu 上工作?

尝试使用 bindValue 而不是 addBindValue。参考这个 link.

A 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'Avatar 在 UTF-8 中作为二进制字符串的文本表示,但仅当 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 链接可以解释为什么你得到 'text-like' 外观与最近 'hex-like' 外观59=].

我在 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 = "‰PNG\r\n\x1a\n[=10=][=10=]..."
//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"