[sqlite3]_[初级]_[使用正则表达式REGEXP查询]

场景

1.在一些数据库db文件中,随着版本更新可能会有不同的表名, 但是这些表名一般都符合某种规则, 所以适配不同版本的数据库表时, 最好的办法是动态获取表名.

2.或者在查询Text数据里需要匹配某个email,某个数值, 都可以用正则表达式.

说明

1.REGEXP 操作符是sqlite3的一个调用regexp()函数的特殊语法. 默认情况下没有定义这个regexp()用户函数, 所以在使用REGEXP操作符时会返回一个错误信息, SQLITE_ERROR = 1. 如果在运行时定义了一个regexp函数的话, 那么使用语法 X REGEXP Y 操作语句会以这样的形式调用 regexp(Y,X). regexp(zPattern, zString)

2.用户定义的regexp(Y,X)函数使用 sqlite3_create_function 创建.

int sqlite3_create_function(
  sqlite3 *db,
  const char *zFunctionName,
  int nArg,
  int eTextRep,
  void *pApp,
  void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
  void (*xStep)(sqlite3_context*,int,sqlite3_value**),
  void (*xFinal)(sqlite3_context*)
);

3.因为我们的regexp(Y,X)只有2个参数,所以nArg的值是2. 如果 xFunc,xStep,XFinal 三个都为NULL,会删除这个用户自定义函数.

db: sqlite3指针.
zFunctionName: "regexp"
nArg: 2
eTextRep: 指定regexp参数的文本编码,一般是 SQLITE_UTF8 | SQLITE_DETERMINISTIC, 
         SQLITE_DETERMINISTIC的意思确定性,当给同样的输入时,输出是一样的. 但是有些函数却不一样, 比如random()就不是确定性的.
pApp:用户自定义userdata, 通过 ``` void *sqlite3_user_data(sqlite3_context*) ``` 获取.
xFunc: 用户自定义的regexp函数指针.
xStep: NULL
xFinal: NULL

4.void (*xFunc)(sqlite3_context*,int,sqlite3_value**) 函数定义里通过调用 void sqlite3_result_int(sqlite3_context*, int) 来实现返回值. 这里我们返回非0 为true, 0为false.

例子


// test-sqlite3-regex.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include <Windows.h>
#include <memory>
#include <string>
#include <algorithm>
#include <regex>
#include <iostream>
#include <assert.h>

#include "sqlite3.h"

void Sqlite3Regexp(sqlite3_context* context, int argc, sqlite3_value** values) {

    std::cout << (const char*)sqlite3_user_data(context) << std::endl;

    int ret;
    std::string reg = (char*)sqlite3_value_text(values[0]);
    std::string text = (char*)sqlite3_value_text(values[1]);
    std::transform(text.begin(),text.end(),text.begin(),::toupper);
    std::transform(reg.begin(),reg.end(),reg.begin(),::toupper);

    if ( argc != 2 || reg.size() == 0 || text.size() == 0) {
        sqlite3_result_error(context, "SQL function regexp() called with invalid arguments.\n", -1);
        return;
    }
    std::regex pattern(reg);
    std::smatch color_match;
    sqlite3_result_int(context, std::regex_search(text, color_match, pattern));
}

bool TestSqlite3Regexp(){
    sqlite3* db = NULL;
    sqlite3_stmt* query = NULL;
    int ret = 0;

    // 创建DB文件
    // 如果不需要创建db文件,使用sqlite3_open即可
    ret = sqlite3_open_v2("test.db",&db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
    if (SQLITE_OK != ret)
        return false;

    std::shared_ptr<sqlite3> sp_db(db,[](sqlite3* db){ 
        sqlite3_close(db);
    });

    // 创建表
    std::string create = "CREATE TABLE IF NOT EXISTS X_12PHOTO (userid INTEGER PRIMARY KEY, ipaddr"
    " TEXT,username TEXT,useradd TEXT,userphone INTEGER,age INTEGER, "
                                                    "time TEXT NOT NULL DEFAULT" 
                                                                             " (NOW()));";
    // 注意,如果使用了sqlite3_stmt不关闭的话调用sqlite3_close是返回 SQLITE_BUSY 失败的.
    sqlite3_stmt *stmt = NULL;
    ret = sqlite3_prepare(db, create.c_str(), create.size(), &stmt, NULL);
    if(SQLITE_OK != ret)
        return false;

    if (sqlite3_step(stmt) != SQLITE_DONE){
        sqlite3_finalize(stmt); 
        return false;
    }
    sqlite3_finalize(stmt);

    // 获取数据库匹配的表
    static const char* sql = "SELECT name FROM sqlite_master WHERE type=\"table\" AND name REGEXP 'X_[0-9]+PHOTO'";
    sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8 | SQLITE_DETERMINISTIC,(void*)sql, &Sqlite3Regexp,NULL,NULL);
    ret = sqlite3_prepare(db, sql, strlen(sql), &stmt, NULL);
    if(SQLITE_OK != ret){
        return false;
    }

    int flag = 0;
    while(sqlite3_step(stmt) == SQLITE_ROW ){
        auto table_sql = (const char*)sqlite3_column_text(stmt,0);
        std::cout << table_sql << std::endl;
    }
    sqlite3_finalize(stmt);

    sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8 | SQLITE_DETERMINISTIC,0, NULL,NULL,NULL);
    ::DeleteFile(L"test.db");

    return true;
}


int _tmain(int argc, _TCHAR* argv[])
{
    assert(TestSqlite3Regexp());
    system("pause");
    return 0;
}


输出:

SELECT name FROM sqlite_master WHERE type="table" AND name REGEXP 'X_[0-9]+PHOTO'
X_12PHOTO   

参考

1.lang_expr
2.create_function
3.sqlite-in-c-and-supporting-regexp
4.icu.c

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Peter(阿斯拉达)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值