【问题标题】:DATALENGTH SQL function for (utf-8) TEXT in Sqlite?Sqlite 中 (utf-8) TEXT 的 DATALENGTH SQL 函数?
【发布时间】:2020-04-07 13:34:43
【问题描述】:

我正在使用 SQLite 的 C 接口,需要列出存储在 TEXT 列中的字符串的大小,即某些数据库支持使用的大小

SELECT DATALENGTH(body) FROM table;

但是,SQLite 没有DATALENGTH 函数。由于有问题的文本很大,我想避免从磁盘加载实际的body 列。由于TEXT 是utf8,LENGTH(body) 不会返回所需的结果(它会返回字符数,而我需要知道存储大小)。将列转换为BLOB 不是一种选择,因为数据库是由第三方程序创建的。

问:除了写custom SQL function之外,有什么方法可以直接从数据库中获取这些信息? SQLite file format 确实存储了 TEXT 字段的长度,所以如果这些信息真的没有公开,我会感到惊讶。

相关:

【问题讨论】:

    标签: c sqlite


    【解决方案1】:

    转换为 blob 以从 length() 获取大小(以字节为单位):

    SELECT length(cast(body AS BLOB)) FROM table;
    

    【讨论】:

    • 感谢指向cast 的指针,我已经浏览了一些文档,它应该可以解决问题!查看 sqlite3 源码表面上表明不会以这种方式分配新内存。
    【解决方案2】:

    除了@Shawn 的回答,事实证明实现自定义 SQL 函数实际上相当简单:

    /* Implement the DATALENGTH() SQL function. Code adapted from the SQLite source
     * for the LENGTH() function.
     */
    static void db_sqlite_datalength(sqlite3_context *context, int argc,
            sqlite3_value **argv)
    {
        (void) argc;
    
        switch(sqlite3_value_type(argv[0])) {
        case SQLITE_BLOB:
        case SQLITE_INTEGER:
        case SQLITE_FLOAT:
        case SQLITE_TEXT:
            sqlite3_result_int(context, sqlite3_value_bytes(argv[0]));
            break;
        default:
            sqlite3_result_null(context);
            break;
        }
    }
    
    static int db_register_custom_functions(sqlite3 *db)
    {
        return sqlite3_create_function(db, "datalength", 1,
                SQLITE_UTF8 | SQLITE_DETERMINISTIC, NULL,
                &db_sqlite_datalength, NULL, NULL);
    }
    

    由于内置length 函数的实现方式完全相同,因此性能应该没问题。我浏览了一下 sqlite3 源代码,但要准确判断磁盘访问何时发生并不容易。据推测,sqlite3 mmaps 的一切,对于性能来说重要的是不会不必要地访问长 TEXT 字段的可能溢出页面。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-04
      • 2011-04-22
      • 1970-01-01
      相关资源
      最近更新 更多