Sqlite3的JSON1扩展具体使用案例--基于C语言的C-API

SQLite数据库中JSON 函数和运算符(二十七) SQLite拥有别人无法比拟的装机量,究竟什么成就了SQLite呢,本文将SQLite的历史版本记录粗列一下,供各位朋友参详如何做一个高质量的程序的引文。SQLite拥有超过225个API,本系列文章将深入介绍 SQLite C/C++ 数据库接口的相关知识,包括如何连接和打开 SQLite 数据库、执行查询和事务管理、提取查询结果集等等,帮助开发者更好地了解和使用 SQLite 数据库接口。 阅读详情

在ROS系统中,因为消息种类太多,要对这些消息进行统一存储并且允许检索,就面临一个问题:如何存储,用什么存储,如何检索?

鉴于我们第一阶段使用了统一数据模型对各种消息进行了统一封装:将所有消息共有的部分提取出来生成各个字段,而将差异部分作为blob进行存储。这个模型存在的一个重要问题就是不能对差异部分进行检索。

为了解决或者部分解决上述问题,我们进行了调研,发现sqlite3存在json扩展,这个是从sliqte3.09版本之后就自带的。所以我们开始考虑进一步扩展统一数据封装模型,将差异性的部分放进去以支持检索。

由于目前sqlite3支持的数据格式还是传统的5种,json还没有独立升格为一种数据类型,所以目前仍然以text类型存储json数据,如{"key1":"1", "key2":"2"}这种样式存储。我们在原来的表设计基础上增加一个text字段来存储json数据。而ros中的各种msg使用我们前面的博客中介绍的ROS的msssage的Printer类和我们开发的msg2Json方法来实现ros消息到json的格式转换(里面的数组我们暂时不处理)。

后面的借助json1的函数实现json部分数据的检索,同时支持传统的sql检索和json检索混合模式检索。下面是我们使用json扩展的过程(摸索中出现了很多错误,很多所谓的介绍只是说了sqlite扩展是啥,怎么写一个扩展,怎么用并不清楚,官网给出的说明以及网上的使用教程基本没有):

1. 编译json库生成libjson.so

2. 打开数据库,获取数据库的句柄

3. 开启load_extension功能

4. 加载json库和入口函数

5. 使用json扩展

上述顺序中,2和3的顺序不能错,也就是说load_extension是要指定为哪个db加载扩展,这时候db不能是NULL,所以要先打开数据库获得句柄。这个是我不断调试摸索出来的(sqlite的扩展使用错误的话,只会报段错误,没有其他任何有用的提示信息)。

下面分别按上述步骤介绍:

1. 编译json扩展得到库文件

在Ubuntu16.04里面使用apt-get install sqlite3 libsqlite3的时候安装的是sqlite3 3.11.0-1ubuntu1.2这一版的二进制包。我调研后发现这里面也是开启了json功能的,至于怎么验证,请参考我的另一个博客。因为要加载扩展,所以首先要存在json库文件,所以我先编译它。那么第一步,我们要去下载对应版本的sqlite3的源码。具体地址: https://launchpad.net/ubuntu/+source/sqlite3/3.11.0-1ubuntu1.2 从下面的介绍我们还可以发现,我们使用apt-get 安装sqlite3中其实并没有json扩展的库文件,但是我们可以在sqlite3命令行中使用json扩展的相关函数。经过调研发现这其实是2套东西,一套sqlite3的sql扩展,一套是sqlite3的C-API扩展。sql扩展默认安装了,所以可以直接在命令行中使用json函数。但C-API扩展并没有安装,所以我们要手动编译得到库文件。

我们下载sqlite3_3.11.0.orig.tar.xz文件(sqlite3_3.11.0.orig-www.tar.xz是html版的api说明)。源码包里面有ext目录,里面是各种扩展,我们要使用的是misc下面的json1.c这个文件。进入到这个目录,执行如下命令

cp ../../sqlite3ext.h ./
gcc -fPIC -shared json1.c sqlite3ext.h -o libjson.so

注意:这里有的教程说不用sqlite3ext.h编译进去,这个为了安全考虑,我还是编译进入了,因为打开json1.c看一下,发现它上来就加载了sqlite3exe.h这个文件。

这样就可以得到json扩展的库文件了,接下来把它复制到/usr/lib/下面(也可以把它放到某个具体路径下)。

2. 打开数据库,得到数据库句柄

这里使用了spatialite插件,其作用是让sqlite3支持地理信息系统,支持二维空间索引,对应的需要安装spatialite和libspatialite包。

3. 启用json扩展

4. 加载json扩展

这里sqlite3_json_init是库文件的入口,可以打开json1.c来查看它的入口(这个是在很多教程里面介绍了的,默认的是sqlite3_extension_init)。根据说明文件来看,如果前面提供的库文件名字以lib开头和.so结尾,那么也可以不写入口函数名,它会先找sqlite3_extension_init,如果不存在,则会找库文件名lib和.so之间的名字x对应的入口sqlite3_x_init。如果库文件不是以lib或so结尾,也它考虑先去掉lib头和.so尾,然后把剩余部分当作x,找sqlite3_x_init作为入口函数。

5. 使用json扩展进行查询:

对于整个json扩展的使用过程中,最混乱的地方有2个:1)先打开数据库,然后启用扩展,然后加载扩展这个顺序(没有人说明白过);2)json扩展的使用,官网说了怎么制作一个扩展和链接一个扩展,但是没有一个例子。导致我费了很多功夫去按照教程制作了一个扩展,但是怎么都链不到json,后来好好研究了一下json1.c和其他几个类似vfs的扩展,发现json1.c文件的组成就是一个扩展的样子,然后开发思考,最后认为json1.c就是一个扩展,所以我们并不需要去写一个扩展,而是要直接使用这个扩展。后面就是探索使用扩展的方法(去读了load_extension()的源代码,发现关于扩展这部分的函数就那么多个,慢慢自己推测使用的组合方式,不断尝试,最后得到上述结果)。

最后,由于我中间不断的卸载/删除sqlite3和spatialite,导致最后虽然可以加载和使用,但是无法插入数据到sqlite3的问题,报错显示no such module: rtree。然后我就认为是sqlite3按照的时候没有把rtree加上去(我把apt-get安装的sqlite3卸载了,又用源码安装了一遍)。后来我又使用CFLAG和-D参数开启了一堆编译选项,发现还是没有rtree。后来发现rtree跟sqlite3没啥关系,是和spatialite有关,然后各种删和重装,还是不行。

最后把最初始的虚拟机解压缩,使用apt-get install 安装了sqlite3和spatialite及其lib库。然后又下载了sqlite3的源码,编译了json库文件,然后直接按照上述几个步骤使用json扩展就没有问题了。这说明我原来瞎折腾一通slqite3和spatialite是无用功。直接使用apt安装的sqlite3和spatialite就可以,不用自己编译,而libjson.so是需要从源码编译的。整个测试文件代码如下:

#include <sqlite3.h>
#include <stdio.h>
#include <stdlib.h>
#include <ros/ros.h>
#include "abstract_msgs/UnifiedData.h"
#include <spatialite/sqlite3.h>
#include <spatialite/gaiageo.h>
#include <spatialite.h>


using namespace std;


//创建"表"函数

int32_t createDB(string aDataBaseName, string aCreateTableSentence, string anAddGeoColSentence, string aCreateSpaIndexSentence)
{
  ROS_INFO("SqliteDao creating DB, please wait some minutes.\n");
  int32_t retCode;
  char sql[512];
  char* errMsg = NULL;
  sqlite3* handle;

  retCode = sqlite3_open_v2(aDataBaseName.c_str(), &handle, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
  if(retCode != SQLITE_OK)
  {
    ROS_INFO("cannot open '%s': %s\n", aDataBaseName.c_str(), sqlite3_errmsg(handle));
    sqlite3_close_v2(handle);
    return -1;
  }

  void* cache;
  cache = spatialite_alloc_connection();
  spatialite_init_ex(handle, cache, 0);

  // InitSpatialMetadata
  strcpy(sql, "SELECT InitSpatialMetadata()");
  retCode = sqlite3_exec(handle, sql, NULL, NULL, &errMsg);
  if(retCode != SQLITE_OK)
  {
    ROS_INFO("InitSpatialMetadata() error: %s\n", errMsg);
    goto abort;
  }

  // create ordinary part of table
  strcpy(sql, aCreateTableSentence.c_str());
  retCode = sqlite3_exec(handle, sql, NULL, NULL, &errMsg);
  if(retCode != SQLITE_OK)
  {
    ROS_INFO("CREATE TABLE  error: %s\n", errMsg);
    goto abort;
  }

  // add geo column uint32_to table
  strcpy(sql, anAddGeoColSentence.c_str());
  retCode = sqlite3_exec(handle, sql, NULL, NULL, &errMsg);
  if(retCode != SQLITE_OK)
  {
    ROS_INFO("AddGeometryColumn() error: %s\n", errMsg);
    goto abort;
  }

  // create spa index of geo column
  strcpy(sql, aCreateSpaIndexSentence.c_str());
  retCode = sqlite3_exec(handle, sql, NULL, NULL, &errMsg);
  if(retCode != SQLITE_OK)
  {
    ROS_INFO("CreateSpatialIndex() error: %s\n", errMsg);
    goto abort;
  }

  retCode = sqlite3_close_v2(handle);
  if(retCode != SQLITE_OK)
    ROS_INFO("close() error: %s\n", sqlite3_errmsg(handle));

  spatialite_cleanup_ex(cache);
  spatialite_shutdown();

  return 0;

abort:
  sqlite3_free(errMsg);

  sqlite3_close_v2(handle);
  if(retCode != SQLITE_OK)
    ROS_INFO("close() error: %s\n", sqlite3_errmsg(handle));

  spatialite_cleanup_ex(cache);
  spatialite_shutdown();
  return -1;
}

int32_t insertDB(uint64_t pOffset, uint64_t pSize, string aFileName, abstract_msgs::UnifiedData ud)
{
  sqlite3_stmt *stmt;
  char sql[512];
  char *errMsg = NULL;

  sqlite3 *db;
  char * dbName="/home/ok/storage_ws_jin/test.sql3";
  int rc = sqlite3_open(dbName,&db);
  if (rc != SQLITE_OK)
     {
       cout<<"打开数据库失败:"<<sqlite3_errmsg(db)<<endl;
       return 0;
     }
   else
     {
      cout<<"数据库打开成功"<<endl;
   }

  gaiaGeomCollPtr geo = NULL;
  unsigned char* blob;
  int32_t blobSize;
  int32_t retCode;
string content ;
  void* cache;
  cache = spatialite_alloc_connection();
  spatialite_init_ex(db, cache, 0);

  // prepare data, insert batch data to database

  strcpy(sql, "BEGIN");
  retCode = sqlite3_exec(db, sql, NULL, NULL, &errMsg);
  if (retCode != SQLITE_OK) {
    ROS_INFO("BEGIN error: %s\n", errMsg);
    goto abort;
  }
    std::cout<<"begin to insert record into observe!"<<std::endl;

  strcpy(sql,"INSERT INTO observe(swarmID, taskName, actorName, robotID, timeStamp, dataType, offset, size, fileName, content, positionZ, positionXY) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
  retCode = sqlite3_prepare_v2(db, sql, strlen(sql), &stmt, NULL);
  if (retCode != SQLITE_OK)
  {
    ROS_INFO("INSERT SQL error: %s\n", sqlite3_errmsg(db));
    goto abort;
  }


    geo = gaiaAllocGeomColl();
    geo->Srid = 3003;
    gaiaAddPointToGeomColl(geo, ud.robotPose.position.x, ud.robotPose.position.y);

    gaiaToSpatiaLiteBlobWkb(geo, &blob, &blobSize);
    gaiaFreeGeomColl(geo);

    sqlite3_reset(stmt);
    sqlite3_clear_bindings(stmt);

    sqlite3_bind_int(stmt, 1, ud.swarmID);
    sqlite3_bind_text(stmt, 2, ud.taskName.c_str(), std::strlen(ud.taskName.c_str()), SQLITE_TRANSIENT);
    sqlite3_bind_text(stmt, 3, ud.actorName.c_str(), std::strlen(ud.actorName.c_str()), SQLITE_TRANSIENT);
    //sqlite3_bind_text(stmt, 3, ud.robotID.c_str(), std::strlen(ud.robotID.c_str()), SQLITE_TRANSIENT);
    sqlite3_bind_int(stmt, 4, ud.robotID);
    sqlite3_bind_text(stmt, 5, ud.timeStamp.c_str(), std::strlen(ud.timeStamp.c_str()), SQLITE_TRANSIENT);
    sqlite3_bind_text(stmt, 6, ud.dataType.c_str(), std::strlen(ud.dataType.c_str()), SQLITE_TRANSIENT);
    sqlite3_bind_int64(stmt, 7, pOffset);
    sqlite3_bind_int64(stmt, 8, pSize);
    sqlite3_bind_text(stmt, 9, aFileName.c_str(), std::strlen(aFileName.c_str()), SQLITE_TRANSIENT);
    content = "{\"c\":\"3\",\"d\":\"4\"}";
    sqlite3_bind_text(stmt, 10, content.c_str(), std::strlen(content.c_str()), SQLITE_TRANSIENT);
    sqlite3_bind_double(stmt, 11, ud.robotPose.position.z);

    sqlite3_bind_blob(stmt, 12, blob, blobSize, free);

    cout<<"binding finished!"<<endl;


    retCode = sqlite3_step(stmt);
    if(retCode == SQLITE_DONE || retCode == SQLITE_ROW)
      ;
    else
    {
      ROS_INFO("sqlite3_step() error: %s\n", sqlite3_errmsg(db));
      sqlite3_finalize(stmt);
      goto abort;
    }


  sqlite3_finalize(stmt);

  strcpy(sql, "COMMIT");
  retCode = sqlite3_exec(db, sql, NULL, NULL, &errMsg);
  if (retCode != SQLITE_OK) {

    ROS_INFO("COMMIT error: %s\n", errMsg);
    goto abort;
  }

  sqlite3_close_v2(db);
  spatialite_cleanup_ex(cache);
  spatialite_shutdown();

  return 0;

abort:
   sqlite3_close_v2(db);
  sqlite3_free(errMsg);
  spatialite_cleanup_ex(cache);
  spatialite_shutdown();
  return -1;
}


void callback(const abstract_msgs::UnifiedData::ConstPtr& msg)
{

    insertDB(random(), random(), "/home/ok/data_store/file/1.txt",  *msg);
}

int main(int argc, char ** argv)
{
    ros::init(argc, argv, "sqlite3Test");
    ros::NodeHandle nh;
    ros::Subscriber sub;

    //sqlite3_db_config(db,SQLITE_)
    sqlite3_os_init();
    string dbname="/home/ok/storage_ws_jin/test.sql3";
    sqlite3 *db ;//=NULL;
    sqlite3_stmt *stmt=0;
    char *errMsg = NULL;
    //string createTableSentence = "CREATE TABLE IF NOT EXISTS observe(id INTEGER PRIMARY KEY AUTOINCREMENT, swarmID INTERGER NOT NULL, taskName TEXT NOT NULL, actorName TEXT NOT NULL, robotID INTEGER NOT NULL, timeStamp TEXT NOT NULL, dataType TEXT NOT NULL, offset INTERGER NOT NULL, size INTERGER NOT NULL, fileName TEXT NOT NULL, positionZ REAL NOT NULL)";

    string createTableSentence= " CREATE TABLE IF NOT EXISTS observe(id INTEGER PRIMARY KEY AUTOINCREMENT, \
            swarmID INTERGER NOT NULL, taskName TEXT NOT NULL, actorName TEXT NOT NULL, \
            robotID INTEGER NOT NULL, timeStamp TEXT NOT NULL, dataType TEXT NOT NULL, \
            offset INTERGER NOT NULL, size INTERGER NOT NULL, fileName TEXT NOT NULL, content TEXT, \
            positionZ REAL NOT NULL);";
    string addGeometryColumnSentence = "SELECT AddGeometryColumn('observe', 'positionXY', 3003, 'POINT', 'XY')";
    string createSpatialIndexSentence = "SELECT CreateSpatialIndex('observe', 'positionXY')";

    int retCode = sqlite3_open(dbname.c_str(),&db);
   if(access(dbname.c_str(), F_OK) == -1)
  {
       cout<<"create a new table!"<<endl;
       createDB(dbname, createTableSentence, addGeometryColumnSentence, createSpatialIndexSentence);

   }else{
       cout<<"table exists!"<<endl;
   }
   cout<<"here 0"<<endl;

    sqlite3_enable_load_extension(db,true);
   // sqlite3_enable_load_extension(db,1);
    cout<<" here 1 "<<endl;
    sqlite3_load_extension(db,"/usr/local/lib/libjson.so","sqlite3_json_init",0);
    cout<<"here 2 "<<endl;
    //sqlite3_auto_extension((void(*)(void))sqlite3_json_init);
    //sqlite3Json1Init(db);


   sqlite3_close(db);
    cout<<"I am Here 4!"<<endl;

    //select data from database

    stmt = NULL;
    const char* zTail;
    int ret = sqlite3_open(dbname.c_str(),&db);
    ret = sqlite3_prepare_v2(db,"select id, json_extract(observe.content,'$.c'), timeStamp from observe where id>10000;",-1,&stmt,&zTail);
    cout<<"retcode is "<< ret<<endl;
    if(ret ==SQLITE_OK){
        int num =0;
        while(sqlite3_step(stmt)==SQLITE_ROW){
            num++;
            int id = sqlite3_column_int(stmt,0);
            const unsigned char* value = sqlite3_column_text(stmt,1);
            const unsigned char* timestamp = sqlite3_column_text(stmt,2);
            cout<<num<<", row id: "<<id<<", timestamp: "<<timestamp<<", value :"<<value<<endl;

        }
    }
    sqlite3_finalize(stmt);
    sqlite3_close(db);


    sub = nh.subscribe("/data", 1000, &callback);

    ros::spin();

    return 1;
}

对应的CMakeList.txt文件如下(其实上述代码是可以独立运行的,不需要编译成ros包或者可运行程序):

cmake_minimum_required(VERSION 2.8.3)
project(storage)

## Compile as C++11, supported in ROS Kinetic and newer
 add_compile_options(-std=c++11)

## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  fastrtps_pubsub
)


catkin_package(
  INCLUDE_DIRS include
#  LIBRARIES storage
  CATKIN_DEPENDS roscpp rospy std_msgs fastrtps_pubsub
#  DEPENDS system_lib
)

include_directories(
  include
  ${catkin_INCLUDE_DIRS}
  /usr/include/
  /usr/local/include
  /usr/local/fastdb/include
  /usr/local/sqlite3/include
)

link_directories(
   /usr/lib/x86_64-linux-gnu/
   /usr/local/lib/
   /usr/local/fastdb/lib/
   /usr/local/sqlite3/lib/
)

## Declare a C++ library
 add_library(${PROJECT_NAME}
   src/fdbDao.cpp
   src/GUDC.cpp
   src/RUDC.cpp
   src/sqliteDao.cpp
   src/RingBuffer.cpp
   src/storage.cpp
 )

## Add cmake target dependencies of the library
## as an example, code may need to be generated before libraries
## either from message generation or dynamic reconfigure
 add_dependencies(${PROJECT_NAME}
     ${${PROJECT_NAME}_EXPORTED_TARGETS}
     ${catkin_EXPORTED_TARGETS}
     fastdb
     )

## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
 add_executable(fastDBTest
     test/fdbDaoTest.cpp
     src/fdbDao.cpp
     src/RUDC.cpp
     src/GUDC.cpp
     )

 add_executable(sqliteDaoTest
     test/sqliteDaoTest.cpp
     src/sqliteDao.cpp
     )

 add_executable(storageNodeTest
     src/StorageNode.cpp
     src/sqliteDao.cpp
     src/storage.cpp
     src/RUDC.cpp
     src/RingBuffer.cpp
     src/fdbDao.cpp
     src/GUDC.cpp
     )
 add_executable(UnifiedDataPub
     test/UnifiedDataPub.cpp
     )
 add_executable(storageTest
     test/storageTest.cpp
     src/sqliteDao.cpp
     src/storage.cpp
     src/RUDC.cpp
     src/RingBuffer.cpp
     src/fdbDao.cpp
     src/GUDC.cpp
     )

 add_executable(sqlite3Test
     test/sqlite3test.cpp
     )
## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use
## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")

## Add cmake target dependencies of the executable
## same as for the library above
 
 add_dependencies(sqlite3Test
     ${${PROJECT_NAME}_EXPORTED_TARGETS}
     ${catkin_EXPORTED_TARGETS}
     )


## Specify libraries to link a library or executable target against
target_link_libraries(sqlite3Test
  ${catkin_LIBRARIES}
  sqlite3
  spatialite
  #json
)

 

 

数据库sqlite3 中型数据库(分布式超大型) ———— mysql(百万级)轻型数据库(嵌入式设备) ———— sqlite(万级)。大型数据库(大型机) —————- Oracle(亿级).schema 查看表的结构。的、零配置的、事务性的 SQL 数据库引擎。 阅读详情

相关推荐

SQLite与C语言集成开发实战指南

SQLite作为轻量级嵌入式数据库,以其零配置、单文件存储和ACID事务支持等特性,成为物联网、移动应用等场景下的首选数据存储方案。其基于B-tree的存储引擎可实现O(logN)的查询效率,配合回滚日志机制确保数据一致性。在C语言集成方面,SQLite提供了简洁的API接口,支持预处理语句、事务控制和内存数据库等高级特性。通过合理使用批量插入、WAL模式等优化手段,开发者可以在嵌入式设备上实现高效的数据持久化方案,满足智能家居、工业传感器等场景下的实时数据处理需求。

weixin_36474001的博客 271

sqlite3数据库 json库

欢迎来到TheBlob 博客!这里是sqlite3 数据库和json库基操。文中举了一些简单例子和常用函数用法。希望能帮助大家!

TheBlob的博客 1627

不写代码,Cursor 10分钟开发1个APP!保姆级教程喂饭来了

做出第一个能运行的app,那种成就感真的很棒。虽然过程可能有点折腾,但只要耐心一点,问题都能解决。记住,遇到问题不要慌,现在有AI帮忙,大部分问题都能快速解决。重要的是迈出第一步,开始动手实践。你的第一个app可能很简单,但这是一个很好的开始。随着经验积累,你能做出的东西会越来越酷。现在就开始行动吧,说不定下个月你就能向朋友炫耀你自己做的app了!

chenhong007的博客 1548

sqlite3 and json

数据库sqlite3 与 json在Linux的安装与使用。

weixin_54069165的博客 1259

新系统申请软件著作权详细操作说明

今年八月底版权中心系统升级,新系统相对好用一些,至少不用再拿IE访问了,但是多了一项实名认证。下面介绍新系统的操作流程。 目录注册、登录和实名认证注册登录实名认证软件登记申请申请表填写鉴别材料身份证明文件权利归属证明文件其他材料提交材料变更登记 注册、登录和实名认证 首先访问版权中心系统:https://register.ccopyright.com.cn/login.html,如果老系统有账号直接登录即可,没有的话需要注册。 注册 点击注册按钮进入注册。 根据实际情况选择个人或单位,每个个人或单位只能在

Programming Talk 1万+

第十五章数据管理成熟度评估【6’】(DAMA-CDGA 2022年以后历年模拟题真题汇总,基本包含所有考点。)

第十五章数据管理成熟度评估【6’】(DAMA-CDGA 2022年以后历年模拟题真题汇总,基本包含所有考点。)

JasonH2021的博客 399

Sqlite3命令行工具的使用

目录 一、Sqlite3简介 二、Sqlite3命令行工具的使用 1、测试是否安装成功打开一个控制台窗口 2、Sqlite命令行基本操作 一、Sqlite3简介 SQLite 是一个软件库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是在世界上最广泛部署的 SQL 数据库引擎。 SQLite是一款轻量级的、基于文件的嵌入式数据库,实现自包容、零配置、支持事务的SQL数据库引擎。与其他数据库管理系统不同,SQLite 的安装和运行非常简...

kupePoem的专栏 3664

建设银行核心系统建设历程全网最详细记录

中国建设银行核心系统数字化转型之路 摘要:中国建设银行自1954年成立以来,其核心系统经历了从分散到集中、再到分布式架构的演进历程。2002-2005年完成的数据大集中工程(DCC)实现了全行业务统一管理,2010年启动的"新一代核心系统"构建了企业级架构,率先实现"一次研发,全行共享"。2020年起全面推进主机下移战略,通过分布式架构改造,攻克八大关键技术难题,于2024年7月完成境内外全量核心业务下移,日均同步数据8亿条,实现金融核心系统完全自主可控。这一转型不仅

银行信息系统应用架构详解 4870

sqlite 存放json数据

在SQLite中存放和查询JSON数据,你可以使用SQLite内置的JSON支持(从SQLite版本3.9.0开始引入的JSON1扩展,以及在后续版本中增强的功能如JSON函数和操作符)。实际上,如果你要遍历的是一个JSON数组,并且想要获取数组中的每个元素,你应该使用json_each_array()函数而不是json_each()。SQLite的JSON1扩展提供了一些函数,如json_extract(),json_each(),json_array_length()等,用于查询JSON数据。

weixin_42095178的博客 4746

Spring Boot入门(03): 从零开始学习配置文件:掌握YAML和Properties,轻松应对多环境配置管理

在Spring Boot开发中,配置文件是非常重要的。本文将带领你从零开始学习配置文件,掌握YAML和Properties的语法,轻松应对多环境配置管理。无论是开发、测试还是生产环境,你都可以轻松切换不同的配置文件,并且能够灵活修改配置信息。

**My Coding Family** 4万+

C++ Qt6 QtQuick/QML入门进阶与项目实战视频教程

C++ Qt这些年在PC客户端、嵌入式、汽车座舱仪表等领域应用很广泛,例如剪映专业版、微信4.0、亿图脑图、Steam、美图秀秀、腾讯会议、钉钉(部分模块)等都是使用C++ QWidget/QML开发。特别是QML这种声明式UI开发更加快捷,QML的界面开发效率相对于QWidget更快速,界面效果更好,QtQuick/QML在Qt6版本也逐渐完善了,使用QML进行客户端开发是个不错的选择。

琅嬛福地 4481

安装和卸载sqlite3 + 使用C语言API将json文件写入数据库

from:https://blog.youkuaiyun.com/jinking01/article/details/100152038 from:https://blog.youkuaiyun.com/hkyshl/article/details/88046537 一、在Linux环境下安装SQLite 1、去官网下载安装包 2、解压文件 tar -zxvf sqlite-autoconf-3220000.tar.gz...

qq_40674996的博客 1885

【PX4学习笔记】3. PX4 固件烧写(1 探索过程)

飞控型号:cube orange【PX4官方用户指南中关于cube orange的描述】 飞控载板型号:Mini Carrier Board【迷你载板说明文档】 固件安装参考:The Cube User Manual V1.0

【人工智障 | 计算鸡视觉 | 机器孩】 7675

NodeJS中使用SQLite3

NodeJS中使用SQLite3 SQLite简介 sqlite是一款轻量级的数据库,sqlite的第一个版本是2000年就发布了的,经过十多年的历练,显然sqlite目前已经相当成熟。sqlite最大的特点就是没有任何数据库服务器,无论是C、java、node.js,只需要相应的驱动,就可以直接对数据库进行读写,速度是相当的快。相比之下,其他的sql数据库必须启动一个服务,而且还要安装...

YunWisdom 2万+

openharmony之启动恢复子系统详解

需求: 添加一个名为my_service的自定义服务步骤1: 创建服务配置],],"env": [步骤2: 添加到主配置],"jobs": ["cmds": [步骤3: 验证配置# ✅ 检查配置格式 jq . /system/etc/init/my_service.cfg # 🔄 重新加载配置 begetctl reload # 📊 验证服务状态 begetctl dump_service my_serviceOpenHarmony init进程的完整生命周期。🔄 三阶段启动模型⚙️ 配置体系。

m0_67505153的博客 597

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

在VSCode中使用C语言连接sqlite3,实现数据库创建

最近在学习sqlite3,记录一下如何通过VSCode使用sqlite3的C语言API来创建数据库等操作。

qq_45899177的博客 1730

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Qt 自带的QSqlDatabase 模块中使用的 SQLite 和 SQLite 官方提供的 C 语言版本(sqlite.org)对比

Qt 自带的模块中使用的 SQLite 和 SQLite 官方提供的 C 语言版本(sqlite.org)在核心功能上是相同的,但它们在集成方式、API 封装、功能支持以及版本更新上存在一些区别。

u014094704的博客 1177

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

深入解析go-sqlite3:Go语言SQLite3驱动全面指南

深入解析go-sqlite3:Go语言SQLite3驱动全面指南 go-sqlite3是一个纯Go语言实现的SQLite3数据库驱动,完全兼容Go标准库的database/sql接口,由日本开发者Yasuhiro Matsumoto创建并维护。该项目采用CGO技术桥接Go语言与SQLite的C语言库,既保持了SQLite原生库的高性能,又提供了Go语言友好的API接口。文章将深入解析其架构设计、核...

gitblog_00056的博客 1222

SQLite 用C语言开发的原因有哪些?

SQLite是一个开源的关系型数据库管理系统,它以轻量级、嵌入式、零配置、可移植性和高性能等特点而著称。SQLite 是一种轻量级的关系型数据库管理系统 (RDBMS),它拥有许多优点,如易于使用、可嵌入、跨平台等。SQLite 拥有轻量级、可嵌入、易于维护等特点,与传统的关系型数据库相比,SQLite 更适合于小型项目和嵌入式应用程序。SQLite未来的发展趋势主要集中在性能、可靠性、安全性和功能方面的不断提升,以满足不同场景下的需求,并且扩大应用范围。c语言具有性能高、跨平台支持、应用广泛等优势。

Lion_Long的博客 1157

SQLite 3.43.0 发布,又有啥新功能?

SQLite 开发团队于 2023 年 08 月 24 日发布了 SQLite 3.43.0 版本。本文给大家分析一下该版本的更新。

Tony.Dong的专栏 7029

go-sqlite3 使用指南:基于 database/sql 的 Go 语言 SQLite 驱动完整解读

> **导读**:go-sqlite3(`github.com/mattn/go-sqlite3`)是一个严格遵循 Go 标准库 `database/sql` 接口的 SQLite3 驱动,它通过 cgo 将 SQLite 的 C 语言合并源文件(amalgamation)直接编译进 Go 程序。本文以本仓库 vendor 目录中携带的 v1.14 版本文档为骨架,系统讲解其 DSN 连接串的全部

gitblog_00025的博客 436

sqlite3数据库

常用数据库1.关系型数据库:将复杂的数据结构简化为二维表格形式(大型:Oracle、DB2中型:MySql、SQLServer小型:Sqlite)2.非关系型数据库:以键值对存储,且结构不固定 (JSON、Redis、MongoDB)优势:1.开源免费, c语言开发2.代码量少,1万行左右,总大小10M以内3.文件型数据库,可以移动4.数据容量最大2T。

2301_78040391的博客 3118

SQLite 3.53.0版本发布,重要更新

SQLite 官方团队于 2026 年 4 月 9 日 发布了版本。本次更新在稳定性修复的基础上,引入了多项 SQL 语言能力增强、CLI 工具革新以及新的 C API 接口,整体属于强烈推荐升级的重要版本。

Tony.Dong的专栏 720

深入解析 go-sqlite3:Go 语言的 SQLite 数据库驱动完整使用指南

go-sqlite3(`github.com/mattn/go-sqlite3`)是一个基于 cgo 的 SQLite3 数据库驱动,完全遵循 Go 标准库 `database/sql` 接口规范,在 Go 生态中承担着"以标准接口访问 SQLite"的桥梁角色。在 buildah 项目中,它作为间接依赖被引入(见 [go.mod](https://link.gitcode.com/i/7a8e7

gitblog_00758的博客 338

Linux C语言操作SQLite数据库

1. SQLite数据库特点 (1)SQLite数据库是开源的嵌入式数据库,无需独立的数据库引擎,直接嵌入到应用程序进程中,因此,通过API,应用程序可以直接操作它。 (2)事务的处理是原子的,一致的,独立的,可持久化的(ACID),即使在系统崩溃和掉电后。 (3)SQLite数据库通过独占性与共享锁来实现事务的独立处理。 (4)一个单独的跨平台的磁盘文件就能够存储一个数据库。 (5)能支持2TB级的数据。 (6)自包含,无外部依赖性。 (7)支持NULL,INTEGER,NUMERIC,RE

5078

SQLite3(六):扩展机制——自定义函数、聚合、排序与虚拟表

SQLite3 最强大的能力之一是其高度可扩展的架构。通过和接口,开发者可以在 C++ 中实现自定义标量函数、聚合函数、排序规则和完整的虚拟表模块。这些机制使得 SQLite3 可以适配任意特定领域的数据处理需求。本文将通过完整的代码实现,深入解析每种扩展机制的原理和最佳实践。自定义标量函数接收 0 个或多个参数,返回单个值。// 自定义标量函数:简化版的 JSON 验证函数// 检查字符串是否是有效的 JSON// 参数检查if (argc!// 获取输入。

weixin_42388661的博客 172
上一篇: sqlite3的json1扩展的函数
下一篇: boost::thread的六种使用方法总结
土豆西瓜大芝麻
博客等级 码龄18年 1189粉丝 238原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值