sqlite - SQLite 中的 TEXT NOT NULL UNIQUE 列是否有字符长度限制?
问题描述
我想避免在具有 2 个空间表和非唯一坐标的简单 SpatiaLite 数据库中出现重复。对于每个表,我都为标识符创建了一个 TEXT NOT NULL UNIQUE 列。一个表有 14 个字符的标识符,它工作正常,但第二个表有 51 个字符的标识符,文本被损坏为 6 个不可打印的字符。经过多次试验和错误,我确定我必须将这些标识符限制为 15 个字符。在 16 到 22 个字符之间,我收到“唯一约束失败”错误。超过 22 个字符时,我会遇到上述损坏,并且偶尔会出现约束失败。我和同事搜索并发现没有任何关于 TEXT NOT NULL UNIQUE 列特有的此类限制的文档,无论是否有 SpatiaLite 扩展。那么这是什么?
- SQLite 或 SpatiaLite 中的错误?
- TEXT NOT NULL UNIQUE 列的已知 15 个字符限制?
- 我在某个地方的一个糟糕的假设?
我在用着:
- SQLite 版本:3.22.0
- SpatiaLite 版本:4.3.0a
解决方案
问题似乎是使用 ostringstream 来生成和包含标识符字符串。这是代码:
std::ostringstream blid;
blid << ...
sqlite3_bind_text(pStmt, 1, blid.str().c_str(), blid.str().length(), nullptr);
str() 方法返回 ostringstream 的内部字符串对象的临时副本,并且该副本在它使用的语句之后被销毁。所以看起来绑定调用保留了字符串指针,直到后面的语句,可能是步骤调用,此时临时文件已被销毁。棘手的一点是,这段代码适用于最多 15 个字节的短标识符,如果字符串对象包含一个特殊的 16 字节数组来存储短字符串,并且它在未损坏的情况下存在足够长的时间以使代码可以处理短字符串,则可以解释这一点。解决方案是将标识符的副本保留足够长的时间,以便 SQLite 完成它。就像是:
std::ostringstream idBuf;
idBuf << ...
std::string blid = idBuf.str();
sqlite3_bind_text(pStmt, 1, blid.str().c_str(), blid.str().length(), nullptr);
...
int rc = sqlite3_step(pStmt);
推荐阅读
- mysql - 获得平均成绩最高的两条记录对
- html - HTML5 音频流操作
- r - 闪亮的传递输入到 dbplyr 过滤器管道
- progress-bar - 4 名玩家的进度条
- android - 在 api 30 中返回 false BindService
- c# - 如何在用户 pc 上创建本地 postgresql 数据库
- laravel - 如何在 Laravel 中使用 spatie 权限中间件?
- java - Android Studio BackgroundService 在没有用户交互的情况下一直运行?
- java - 如何在spring中创建自定义查询方法生成器
- javascript - HTML输入元素在EJS中使用电子返回空格