SQLite 知识整理

news/发布时间2024/5/18 14:33:56

写在前面:

本文章旨在总结备份、方便以后查询,由于是个人总结,如有不对,欢迎指正;另外,内容大部分来自网络、书籍、和各类手册,如若侵权请告知,马上删帖致歉。

目录

  • SQLite 类型
  • 数据表查询
  • C / C++ 接口函数
    • Errors 码
    • API 函数
      • sqlite3_open
      • sqlite3_close
      • sqlite3_exec
      • sqlite3_get_table
      • sqlite3_free_table
      • sqlite3_prepare_v2
      • sqlite3_bind_xxx
      • sqlite3_step
      • sqlite3_column_xxx
      • sqlite3_reset
    • 操作流程
  • 常用命令
  • 参考


首发及后期更新将于 https://arachnid.cc/sqlite-summarize/,此处仅作二次备份。

SQLite 类型

1、存储类

SQLite 存储类属性划分为以下几种类型:

类型描述
NULL表示该值为 NULL 值。
INTEGER无符号整型值,根据值的大小存储在 1、2、3、4、6 或 8 字节中。
REAL浮点值,存储为 8 字节的 IEEE 浮点数字。
TEXT文本字符串,使用 UTF-8、UTF-16BE 或 UTF-16LE 编码方式存储。
BLOB存储 Blob 数据,该类型数据和输入数据完全相同。

2、数据类型

  • 布尔数据类型:
    SQLite 并没有提供专门的布尔存储类型,取而代之的是存储整型 1 表示 true,0 表示 false。

  • 日期和时间数据类型:
    和布尔类型一样,SQLite 也同样没有提供专门的日期时间存储类型,而是以 TEXT、REAL 和 INTEGER 类型分别不同的格式表示该类型,如:
    TEXT : “YYYY-MM-DD HH:MM:SS.SSS”。
    REAL :以 Julian 日期格式存储。
    INTEGER :以 Unix 时间形式保存数据值,即从 1970-01-01 00:00:00 到当前时间所流经的秒数。

3、类型亲缘性(Type Affinity)

为了最大限度地提高 SQLite 和其他数据库引擎之间的兼容性,SQLite 支持 “类型亲缘性” 的概念。使其它 SQL 数据库引擎能在 SQLite 上运行;在表字段被声明之后,SQLite 都会根据该字段声明时的类型为其选择一种亲缘类型,当数据插入时,该字段的数据将会优先采用亲缘类型作为该值的存储方式,除非亲缘类型不匹配或无法转换当前数据到该亲缘类型,这样 SQLite 才会考虑其它更适合该值的类型存储该值。

SQLite 3 数据库中支持分配的类型关联:

  • TEXT
  • NUMERIC
  • INTEGER
  • REAL
  • BLOB

决定规则:

  1. 如果声明的类型包含字符串 “INT”,则它分配为 INTEGER
  2. 如果声明的类型包含任意字符串 “CHAR”、“CLOB” 或 “TEXT” 的关键字,则被分配为 TEXT 。请注意,VARCHAR 类型包含字符串 “CHAR”,因此被分配为 TEXT
  3. 如果声明的类型包含字符串 “BLOB”,或者如果未指定类型,则被分配为 BLOB
  4. 如果声明的类型包含任意字符串 “REAL”、“FLOA” 或 “DOUB” 的关键字,则被分配为 REAL
  5. 其余情况下,归类为 NUMERIC

note:请注意,确定类型亲缘性的规则顺序很重要。声明类型为 “CHARINT” 的字段将同时匹配规则 1 和 2,但第一条规则采用优先权,所以会被分配为 INTEGER

示例:

声明的类型类型亲缘性规则优先级
INT
INTEGER
TINYINT
SMALLINT
MEDIUMINT
BIGINT
UNSIGNED
BIG
INT
INT2
INT8
INTEGER1
CHARACTER(20)
VARCHAR(255)
VARYING
CHARACTER(255)
NCHAR(55)
NATIVE
CHARACTER(70)
NVARCHAR(100)
TEXT
CLOB
TEXT2
BLOB
no datatype specified
BLOB3
REAL
DOUBLE
DOUBLE
PRECISION
FLOAT
REAL4
NUMERIC
DECIMAL(10,5)
BOOLEAN
DATE
DATETIME
NUMERIC5

数据表查询

1、查看所有表名

SELECT * FROM sqlite_master WHERE type='table' ORDER BY name;

sqlite_master 是一个特殊表, 属于系统表;存放在根页中,每一个数据库的 .db 文件都有一个 sqlite_master 表。该表存放了 .db 中所有表的相关信息,并只有只读权限,写操作由系统自动执行,使用者没有写的执行权限;其结构如下:

CREATE TABLE sqlite_master (type TEXT, // 记录项目的类型,如:表(table), 索引(index), 视图(view), 触发器(trigger)name TEXT, // 记录项目的名称,如表名、索引名等tbl_name TEXT, // 记录所从属的表名,如索引所在的表名。对于表来说,该列就是表名本身rootpage INTEGER, // 记录项目在数据库页中存储的编号。对于视图和触发器,该列值为 0 或者 NULLsql TEXT // 记录创建该项目的 SQL 语句
);

2、查看表的字段

PRAGMA table_info(table_name);

其中 [table_name] 为待查数据表名。

3、查看整表数据

SELECT * FROM table_name;

其中 [table_name] 为待查数据表名。

note:参数传入,字符串用单引号包括。


C / C++ 接口函数

Errors 码

#define SQLITE_OK           0   /* 成功 */
/* 错误码 */
#define SQLITE_ERROR        1   /* sql错误或丢失的数据库,SQL error or missing database */
#define SQLITE_INTERNAL     2   /* sqlite内部逻辑错误,Internal logic error in SQLite */
#define SQLITE_PERM         3   /* 拒绝访问,Access permission denied */
#define SQLITE_ABORT        4   /* 回调函数请求取消操作,Callback routine requested an abort */
#define SQLITE_BUSY         5   /* 数据库文件被锁定,The database file is locked */
#define SQLITE_LOCKED       6   /* 数据库的一个表被锁定,A table in the database is locked */
#define SQLITE_NOMEM        7   /* 某次malloc函数调用失败,A malloc() failed */
#define SQLITE_READONLY     8   /* 尝试写入一个只读数据库,Attempt to write a readonly database */
#define SQLITE_INTERRUPT    9   /* 操作sqlite3_interrupt函数被中断,Operation terminated by sqlite3_interrupt()*/
#define SQLITE_IOERR       10   /* 发生磁盘I/O错误,Some kind of disk I/O error occurred */
#define SQLITE_CORRUPT     11   /* 数据库磁盘映像不正确,The database disk image is malformed */
#define SQLITE_NOTFOUND    12   /* 找不到表或记录,NOT USED. Table or record not found */
#define SQLITE_FULL        13   /* 数据库满而插入失败,Insertion failed because database is full */
#define SQLITE_CANTOPEN    14   /* 无法打开数据库,Unable to open the database file */
#define SQLITE_PROTOCOL    15   /* 数据库锁定协议错误,NOT USED. Database lock protocol error */
#define SQLITE_EMPTY       16   /* 数据库为空,Database is empty */
#define SQLITE_SCHEMA      17   /* 数据库结构发生改变,The database schema changed */
#define SQLITE_TOOBIG      18   /* 数据大小超限,String or BLOB exceeds size limit */
#define SQLITE_CONSTRAINT  19   /* 约束违反,Abort due to constraint violation */
#define SQLITE_MISMATCH    20   /* 数据类型不匹配,Data type mismatch */
#define SQLITE_MISUSE      21   /* 库使用不正确,Library used incorrectly */
#define SQLITE_NOLFS       22   /* 使用了操作系统不支持的功能,Uses OS features not supported on host */
#define SQLITE_AUTH        23   /* 授权失败,Authorization denied */
#define SQLITE_FORMAT      24   /* 附加数据库格式错误,Auxiliary database format error */
#define SQLITE_RANGE       25   /* sqlite3_bind的第2给参数超出范围,2nd parameter to sqlite3_bind out of range */
#define SQLITE_NOTADB      26   /* 不是数据库文件,File opened that is not a database file */
#define SQLITE_NOTICE      27   /* Notifications from sqlite3_log() */
#define SQLITE_WARNING     28   /* Warnings from sqlite3_log() */
#define SQLITE_ROW         100  /* sqlite3_step产生一个就绪行,sqlite3_step() has another row ready */
#define SQLITE_DONE        101  /* sqlite3_step执行完成,sqlite3_step() has finished executing */

API 函数

以下只列举嵌入式环境下常用的 API:

sqlite3_open

SQLITE_API int sqlite3_open(const char *filename,   /* Database filename (UTF-8) */sqlite3 **ppDb          /* OUT: SQLite db handle */
);

该函数用于打开由 filename 参数指定的 SQLite 数据库文件,并返回一个 *ppDb 数据库连接句柄,即使发生错误;filename 为 UTF-8 编码,如果 SQLite 无法分配内存来保存 sqlite3 对象,则会在 *ppDb 中写入一个 NULL,而不是指向 sqlite3 对象的指针。如果数据库成功打开,则返回 SQLITE_OK。否则返回错误代码。sqlite3_errmsg() 可用于获取任何 sqlite3_open() 执行失败后错误的英文描述。

如果 filename 参数是 ':memory:' ,那么 sqlite3_open() 将会在 RAM 中创建一个内存数据库,这只会在数据库连接关闭前持续。

如果 filename 参数是 '' (空字符串),则将创建一个专用的临时磁盘数据库;一旦数据库连接关闭,此专用数据库将被自动删除。

sqlite3_close

SQLITE_API int sqlite3_close(sqlite3*);

该函数与 sqlite3_open 函数相对应,用于关闭之前调用 sqlite3_open() 打开的数据库连接,此时所有与连接相关的语句都应在连接关闭之前完成。

如果还有查询没有完成,sqlite3_close() 将返回 SQLITE_BUSY 禁止关闭的错误消息;当成功执行,将销毁 sqlite3 对象并释放所有关联资源时返回 SQLITE_OK。

sqlite3_exec

SQLITE_API int sqlite3_exec(sqlite3*,                                  /* An open database */const char *sql,                           /* SQL to be evaluated */int (*callback)(void*,int,char**,char**),  /* Callback function */void *,                                    /* 1st argument to callback */char **errmsg                              /* Error msg written here */
);

sqlite3_exec() 提供了一个执行 SQL 命令的快捷方式,SQL 命令由 *sql 参数提供;它是 sqlite3_prepare_v2() 、sqlite3_step() 和 sqlite3_finalize() 的包装函数,允许应用程序运行多个 SQL 语句,而无需编写大量 C 代码。

sqlite3_exec() 程序解析并执行由 *sql 参数所给的每个命令,直到字符串结束或者遇到错误为止。此参数等同于使用 shell 实现所有的 sqlite 功能命令,所以这个 *sql 就是对应 sqlite 功能命令的 “字符串”。

callback 是执行 *sql 对应的功能命令后,所调取的函数,即回调函数;用于将执行结果进行分析处理。其原型如下:

typedef int (*sqlite3_callback)(void *data, int argc, char **argv, char **azColName);

sqlite3_callback 参数:

  • data:由 sqlite3_exec 传入的参数 void* ,或者说是指针参数。
  • argc:查询到的这一条记录由多少个字段(多少列)。
  • argv:该参数是双指针,查询出来的数据都保存在这里,它是一个一维数组,每一个元素都是一个 char* ,是一个字段内容,所以这个参数就可以不是单字节,而是可以为字符串等不定长度的数值,用字符串表示,以 '\0' 结尾。
  • azColName:该参数是双指针,与 argv 是对应的,表示这个字段的字段名称。

note:除 data 传入参数外,回调函数的其它参数一定是 SQL 命令执行结果的进一步处理;此外,需要特别注意的是:回调函数多数时候不是执行 1 次,而是会循环执行 n 次,例如当我们执行 SELECT 命令时,往往输出的结果会是多行,假设有 n 行,那么就会执行 n 次回调函数。

实例:

#include <stdio.h>
#include <sqlite3.h>static int callback(void *NotUsed, int argc, char **argv, char **azColName){int i;for(i=0; i<argc; i++){printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");}printf("\n");return 0;
}int main(int argc, char **argv){sqlite3 *db;char *zErrMsg = 0;int rc;if( argc!=3 ){fprintf(stderr, "Usage: %s DATABASE SQL-STATEMENT\n", argv[0]);return(1);}rc = sqlite3_open(argv[1], &db);if( rc ){fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));sqlite3_close(db);return(1);}rc = sqlite3_exec(db, argv[2], callback, NULL, &zErrMsg);if( rc!=SQLITE_OK ){fprintf(stderr, "SQL error: %s\n", zErrMsg);sqlite3_free(zErrMsg);}sqlite3_close(db);return 0;
}

sqlite3_get_table

SQLITE_API int sqlite3_get_table(sqlite3 *db,          /* An open database */const char *zSql,     /* SQL to be evaluated */char ***pazResult,    /* Results of the query */int *pnRow,           /* Number of result rows written here */int *pnColumn,        /* Number of result columns written here */char **pzErrmsg       /* Error msg written here */
);

在最新的文档中,表明这该函数是一个传统的 API,保留该 API 是为了向后兼容;因此,不建议使用此接口。

输入参数:

  • db:打开数据库文件后返回的句柄。

  • zSql:需要执行的 SQL 命令字符串。

  • pazResult:对字符串数组的引用。使用此引用传回查询结果。传回的值必须通过调用 sqlite3_free_table()

  • pnRow:查询返回的行数,不包括列名。

  • pnColumn:查询返回的列数。

  • pzErrmsg:对字符串的可选引用。如果发生错误,引用将被设置为一条错误消息。该应用程序负责 释放的消息 sqlite3_free() 。如果没有错误发生,引用将被设置为 NULL。引用可能为 NULL。

和 sqlite3_exec() 这种使用回调函数的方式不同,sqlite3_get_table() 的功能要显得更加简便。它通过控制语句的传入,直接将参数赋值给指针传出。

note:虽然 sqlite3_get_table() 的使用较于 sqlite3_exec() 更为简便,但官方不推荐使用的,在实际当中它更趋于用作测试 API,并且根据官方建议,推荐使用 sqlite3_prepare_v2()、sqlite3_column_xxx() 这些 API 组合。

sqlite3_free_table

SQLITE_API void sqlite3_free_table(char **result);

该函数与 sqlite3_get_table 函数相对应,在应用程序完成 sqlite3_get_table 的结果使用后,它必须将查询结果的指针 pazResult 传递给 sqlite3_free_table() 以释放分配的内存。

sqlite3_prepare_v2

SQLITE_API int sqlite3_prepare_v2(sqlite3 *db,            /* Database handle */const char *zSql,       /* SQL statement, UTF-8 encoded */int nByte,              /* Maximum length of zSql in bytes. */sqlite3_stmt **ppStmt,  /* OUT: Statement handle */const char **pzTail     /* OUT: Pointer to unused portion of zSql */
);

输入参数:

  • db:从先前成功调用 sqlite3_open()、sqlite3_open v2()或sqlite3_open16()获得的 SQLite 数据库。
  • zSql:要执行的 SQL 语句(可以包含未赋值的变量)
  • nByte:如果 nByte 参数为负,则 zSql 被读取到第一个空结束终止符。如果 nByte 为正,则它是从 zSql 读取的字节数。
  • ppStmt:解析编译出的 SQL 语句实例。
  • pzTail:如果 pzTail 不为空,那么 *pzTail 将指向 zSql 中第一个 SQL 语句结束后的第一个字节。

sqlite3_bind_xxx

SQLITE_API int sqlite3_bind_blob(      sqlite3_stmt* stmt, int pidx, const void*          val, int            bytes, mem_callback);
SQLITE_API int sqlite3_bind_blob64(    sqlite3_stmt* stmt, int pidx, const void*          val, sqlite3_uint64 bytes, mem_callback);
SQLITE_API int sqlite3_bind_double(    sqlite3_stmt* stmt, int pidx, double               val);
SQLITE_API int sqlite3_bind_int(       sqlite3_stmt* stmt, int pidx, int                  val);
SQLITE_API int sqlite3_bind_int64(     sqlite3_stmt* stmt, int pidx, sqlite3_int64        val);
SQLITE_API int sqlite3_bind_null(      sqlite3_stmt* stmt, int pidx);
SQLITE_API int sqlite3_bind_text(      sqlite3_stmt* stmt, int pidx, const char*          val, int            bytes, mem_callback);
SQLITE_API int sqlite3_bind_text16(    sqlite3_stmt* stmt, int pidx, const void*          val, int            bytes, mem_callback);
SQLITE_API int sqlite3_bind_text64(    sqlite3_stmt* stmt, int pidx, const char*          val, sqlite3_uint64 bytes, mem_callback, unsigned char encoding);
SQLITE_API int sqlite3_bind_value(     sqlite3_stmt* stmt, int pidx, const sqlite3_value* val);
// SQLITE_API int sqlite3_bind_pointer(   sqlite3_stmt*, int, void*, const char*,void(*)(void*));
SQLITE_API int sqlite3_bind_zeroblob(  sqlite3_stmt* stmt, int pidx,                           int            bytes);
SQLITE_API int sqlite3_bind_zeroblob64(sqlite3_stmt* stmt, int pidx,                           sqlite3_uint64 bytes);void mem_callback( void* ptr );

用于绑定任何参数值。

  • stmt:指向一个被 sqlite3_prepare_v2() 等接口编译的语句句柄,它可被 sqlite3_step() 执行。最后用 sqlite3_finalize() 来释放它。
  • pidx:SQL 参数(每列元素)的索引值,参数索引值从 1 开始。
  • val:要绑定的数据值。
  • bytes:数据值的大小,以字节(不是字符)为单位。通常,长度不包括任何空结束符。如果 val 是一个以空结束的字符串,把该值设为为负值(-1),则会自动计算长度。
  • mem_callback:一个指向内存释放函数的函数指针。此函数用于在 SQLite 处理完BLOB 或 string 之后对其进行处理,主要用来释放 val 的内存缓冲区;如果缓冲区是用 sqlite3_malloc() 分配的,则可以直接传递对 sqlite3_free() 的引用。也可以使用特殊标志 SQLITE_STATICSQLITE_TRANSIENTSQLITE_STATIC 说明数据值为常量,位于静态的非托管空间中,不需要释放,而 SQLITE_TRANSIENT 会使得对 val 数据做一份拷贝。

sqlite3_step

SQLITE_API int sqlite3_step(sqlite3_stmt*);

在调用 sqlite3_prepare_v2() 等接口编译的语句句柄后,必须调用此函数一次或多次以计算语句。

返回值:

  • SQLITE_BUSY:忙碌,数据库引擎无法锁定数据去完成其工作。可以重试该语句。

  • SQLITE_DONE:意味着 SQL 语句执行完成且成功。一旦执行成功后,sqlite3_step() 就不应该被再次调用执行,除非我们使用 sqlite3_reset() 重置 sqlite3_stmt 数据。

  • SQLITE_ROW:当返回的行数据较多时会出现,代表获得了一条有效数据行,此时可以通过 sqlite3_column_xxx 函数来取得数据;再次调用 sqlite3_step() 可取得下一条查询结果,直至返回 SQLITE_DONE

  • SQLITE_ERROR:表示发生了运行时错误(例如约束冲突),此时可以通过 sqlite3_errmmsg() 取得相关的错误信息,并且不应再次调用 sqlite3_step() 。

  • SQLITE_MISUSE:意味着这个例程被不适当地调用。可能是在已完成的准备好的语句上调用的,也可能是在以前返回 SQLITE_ERRORSQLITE_DONE 的语句上调用的。或者可能是同一数据库连接同时被两个或多个线程使用。

sqlite3_column_xxx

SQLITE_API const void*          sqlite3_column_blob(  sqlite3_stmt* stmt, int cidx);
SQLITE_API double               sqlite3_column_double( sqlite3_stmt* stmt, int cidx);
SQLITE_API int                  sqlite3_column_int(    sqlite3_stmt* stmt, int cidx);
SQLITE_API sqlite3_int64        sqlite3_column_int64(  sqlite3_stmt* stmt, int cidx);
SQLITE_API const unsigned char* sqlite3_column_text(  sqlite3_stmt* stmt, int cidx);
SQLITE_API const void*          sqlite3_column_text16(sqlite3_stmt* stmt, int cidx);
SQLITE_API sqlite3_value*       sqlite3_column_value( sqlite3_stmt* stmt, int cidx);
SQLITE_API int                  sqlite3_column_bytes(  sqlite3_stmt* stmt, int cidx);
SQLITE_API int                  sqlite3_column_bytes16(sqlite3_stmt* stmt, int cidx);
SQLITE_API int                  sqlite3_column_type(   sqlite3_stmt* stmt, int cidx);

用于从当前结果行中提取列值。

  • stmt:指向一个被 sqlite3_prepare_v2() 等接口编译的语句句柄,它可被 sqlite3_step() 执行。最后用 sqlite3_finalize() 来释放它。
  • cidx:SQL 参数(每列元素)的索引值,参数索引值从 0 开始。

返回结果:

API 函数结果值
sqlite3_column_blobBLOB
sqlite3_column_doubleREAL
sqlite3_column_int32 位 INTEGER
sqlite3_column_int6464 位 INTEGER
sqlite3_column_textUTF-8 TEXT
sqlite3_column_text16UTF-16 TEXT
sqlite3_column_value作为 未受保护的 sqlite3_value 对象
sqlite3_column_bytesBLOB 或 UTF-8 TEXT 的字节大小
sqlite3_column_bytes16UTF-16 TEXT 的字节大小
sqlite3_column_type默认数据的类型

sqlite3_reset

SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);

用于重置 sqlite3_stmt 数据,然后准备被重新执行。任何使用 sqlite3_bind_xxx 函数将值绑定到它们的 SQL 语句变量都将保留它们的值。使用 sqlite3_clear_bindings() 重置绑定。

返回值:

  • SQLITE_BUSY
  • SQLITE_DONE
  • SQLITE_ROW

操作流程

使用 SQLite 数据库,最典型的函数操作流程(伪代码):

/* create a statement from an SQL string */
sqlite3_stmt *stmt = NULL;if ( sqlite3_prepare_v2( db, sql_str, sql_str_len, &stmt, NULL ) == SQLITE_OK )
{/* use the statement as many times as required */while( ... ){/* bind any parameter values */sqlite3_bind_xxx( stmt, param_idx, param_value... );.../* execute statement and step over each row of the result set */while ( sqlite3_step( stmt ) == SQLITE_ROW ){/* extract column values from the current result row */col_val = sqlite3_column_xxx( stmt, col_index );...}/* reset the statement so it may be used again */sqlite3_reset( stmt );sqlite3_clear_bindings( stmt );  /* optional */}
}/* destroy and release the statement */
sqlite3_finalize( stmt );

a、sqlite3_prepare 创建一个预处理对象。

b、sqlite3_bind_xxx 绑定参数。

c、循环执行 sqlite3_step 获取数据。

d、sqlite3_column 从数据中取出每一段。

e、释放 sqlite3_finalize 。

1、插入

sqlite3_open -> sqlite3_prepare_v2 -> sqlite3_bind_xxx -> sqlite3_step -> sqlite3_reset -> sqlite3_finalize -> sqlite3_close

2、查询

sqlite3_open -> sqlite3_prepare_v2 -> sqlite3_step -> sqlite3_column_xxx -> sqlite3_finalize -> sqlite3_close

3、例子

略略略


常用命令

If you use an auto-increment field, you can easily write this to delete the oldest 100 records:

DELETE FROM mytable WHERE id IN (SELECT id FROM mytable ORDER BY id ASC LIMIT 100)

Or, if no such field is present, use ROWID :

DELETE FROM mytable WHERE ROWID IN (SELECT ROWID FROM mytable ORDER BY ROWID ASC LIMIT 100)

Or, to leave only the latest 1000 records:

DELETE FROM mytable WHERE ROWID IN (SELECT ROWID FROM mytable ORDER BY ROWID DESC LIMIT -1 OFFSET 1000)

参考

An Introduction To The SQLite C/C++ Interface

C-language Interface Specification for SQLite

Datatypes In SQLite

Using sqlite3_bind_xxx()

Using sqlite3_column_xxx()

Write Programs That Use SQLite

SQLite常用API©

Delete oldest records from database

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.bcls.cn/csOR/4085.shtml

如若内容造成侵权/违法违规/事实不符,请联系编程老四网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

Spring 容器、核心容器总结

目录 创建容器获取 bean容器类层次结构图核心容器总结容器相关bean 相关依赖注入相关 创建容器 方式一&#xff1a; 类路径加载配置文件 ApplicationContext ctx new ClassPathXmlApplicationContext("applicationContext.xml");方式二&#xff1a; 文件路径加载配…

TCP Keepalive 和 HTTP Keep-Alive

HTTP 的Keep-Alive 在 HTTP 1.0 中默认是关闭的&#xff0c;如果浏览器要开启 Keep-Alive&#xff0c;它必须在请求的包头中添加&#xff1a; Connection: Keep-Alive然后当服务器收到请求&#xff0c;作出回应的时候&#xff0c;它也添加一个头在响应中&#xff1a; Connec…

基于java+springboot+vue实现的美食信息推荐系统(文末源码+Lw)23-170

1 摘 要 使用旧方法对美食信息推荐系统的信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在美食信息推荐系统的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不能及时纠正等问题。这次开发…

Elasticsearch:创建自定义 ES Rally tracks 的分步指南

作者&#xff1a;Alejandro Snchez 按照这个综合教程学习如何制作个性化的 Rally tracks ES Rally 是什么&#xff1f;它的用途是什么&#xff1f; ES Rally 是一个用于在 Elasticsearch 上测试性能的工具&#xff0c;允许你运行和记录比较测试。 做出决策可能很困难&#x…

【kubernetes】二进制部署k8s集群之master节点和etcd数据库集群(上)

目录 前言&#xff1a;关于整个k8s集群的主机规划以及本文部署架构 步骤一&#xff1a;完成操作系统初始化配置 步骤二&#xff1a;完成etcd集群部署 关于etcd集群 ①准备签发证书环境 ②先完成单独一个节点的部署 ③通过部署好的etcd01节点 完成另外两个节点的部署 拓展…

如何在CentOS安装SQL Server数据库并实现无公网ip环境远程连接

文章目录 前言1. 安装sql server2. 局域网测试连接3. 安装cpolar内网穿透4. 将sqlserver映射到公网5. 公网远程连接6.固定连接公网地址7.使用固定公网地址连接 前言 简单几步实现在Linux centos环境下安装部署sql server数据库&#xff0c;并结合cpolar内网穿透工具&#xff0…

使用IntelliJ IDEA查看接口的全部实现方法

在大型Java项目中&#xff0c;经常会使用接口和抽象类进行代码设计。为了更好地了解代码结构和功能&#xff0c;我们需要快速查看一个接口的所有实现类。IntelliJ IDEA提供了一些方便的方法来实现这一目标。 1. 点击查看接口的实现子类 在IDEA中&#xff0c;你可以轻松地查看…

南邮概率统计与随机过程练习册答案

**南京邮电大学** **概率统计与随机过程练习册答案简介** 本文档是一份精心整理的南京邮电大学概率统计与随机过程课程的练习册答案集。它旨在为学习该课程的学生提供一个详尽的解题参考,帮助他们更好地理解和掌握概率论与统计学的基本概念和方法。 **内容概览:** - **章节…

发布订阅模式:观察者模式的一种变体

发布-订阅模型&#xff08;Publish-Subscribe Model&#xff09;的底层机制通常基于观察者模式。 发布-订阅模型是观察者模式的一种变体。 在观察者模式中&#xff0c;主题&#xff08;或被观察者&#xff09;维护了一组观察者&#xff0c;当主题的状态发生变化时&#xff0c…

【day02】每天三道 java后端面试题:Java、C++和Go的区别 | Redis的特点和应用场景 | 计算机网络七层模型

文章目录 1. Java、C和 Go 语言的区别&#xff0c;各自的优缺点&#xff1f;2. 什么是Redis&#xff1f;Redis 有哪些特点&#xff1f; Redis有哪些常见的应用场景&#xff1f;3. 简述计算机网络七层模型和各自的作用&#xff1f; 1. Java、C和 Go 语言的区别&#xff0c;各自的…

2.1_4 进程通信

文章目录 2.1_4 进程通信&#xff08;一&#xff09;什么是进程间通信&#xff08;二&#xff09;为什么进程通信需要操作系统支持&#xff08;三&#xff09;共享存储&#xff08;四&#xff09;消息传递&#xff08;1&#xff09;直接通信方式&#xff08;2&#xff09;间接通…

Mybatis-Plus为数据表字段自动填充创建时间和更新

遇到的问题 练习项目时遇到create_time和update_time数据表字段需要填充时想到每次都要手写代码有点繁琐而且直觉告诉我肯定有办法自动填充。通过查阅相关资料&#xff0c;最终也是成功达成目标。 解决步骤 1.创建自定义类DateAutoFillHandler实现MetaObjectHandler接口 Co…

(十六)devops持续集成开发——jenkins流水线构建之邮件通知

前言 本节内容主要介绍jenkins在流水线任务构建完成后的通知操作&#xff0c;使用jenkins的邮件通知插件完成构建任务结束的通知。一般项目发布都会通知相关的责任人&#xff0c;这样项目发布在出现问题时能够及时的处理。 正文 ①在插件中心安装Email Extension邮件通知插件…

第九天-自动化办公

1.基础-普通文件操作 1. shutil文件操作模块 文件的复制 复制文件 from shutil import copy copy("复制文件路径","目标位置") 文件内容的复制 from shutil import copyfile copyfile(来源文件&#xff0c;目标文件) 文件的剪切 可用于文件和文件夹 fr…

【Spring MVC】处理器映射器:AbstractHandlerMethodMapping源码分析

目录 一、继承体系 二、HandlerMapping 三、AbstractHandlerMapping 四、AbstractHandlerMethodMapping 4.1 成员属性 4.1.1 MappingRegistry内部类 4.2 AbstractHandlerMethodMapping的初始化 4.3 getHandlerInternal()方法&#xff1a;根据当前的请求url&#xff0c;…

CSS高级技巧

一&#xff0c;精灵图&#xff08;sprites&#xff09; 1.1why 当网页中的图像过多时&#xff0c;服务器就会频繁地接收和发送请求图片&#xff0c;造成请求压力过大进而降低页面的加载速度。为了有效减少服务器请求和接收次数&#xff0c;提高页面的加载速度&#xff0c;出现…

向导式堆栈管理器Dockge

经过申诉&#xff0c;目前博客的几个域名都恢复了&#xff0c;时间也延长到了 2033 年&#xff0c;后面还会不会出问题&#xff0c;老苏就不知道了 什么是 Dockge ? Dockge 是一款时髦的、易于使用的、响应式的、自托管的 docker-compose.yaml 向导式堆栈管理器&#xff0c;可…

前端项目如何准确预估个人工时

补充 看来很多小伙伴对这个问题感兴趣&#xff0c;大家不要忽视了压工时这个事。 领导为什么会压工时&#xff1f; 使他的KPI更好看不清楚做这个东西实际要多长时间因为第2点的原因&#xff0c;他也无法去争取合理时间部分人看着下属加班&#xff0c;有种大权在握&#xff0…

Open CASCADE学习|为什么由Edge生成Wire不成功?

Wire 是一种复合形状&#xff0c;不是由几何形状构建的&#xff0c;而是由边缘的装配构建的。BRepBuilderAPI_MakeWire类可以从一个或多个Edge构建Wire&#xff0c;或将新Edge连接到现有Wire。 BRepBuilderAPI_MakeWire 类将Edge连接到Wire。添加新Edge时&#xff0c;如果其顶点…

k8s(4)

目录 负载均衡部署 做初始化操作&#xff1a; 每台主机添加域名 从 master01 节点上拷贝证书文件、各master组件的配置文件和服务管理文件到 master02 节点: 修改02配置文件kube-apiserver&#xff0c;kube-controller-manager&#xff0c;kube-scheduler中的IP&#xff1…
推荐文章