欢迎来真孝善网,为您提供真孝善正能量书籍故事!

深入浅出:iOS SQLite3 常用操作指南

时间:10-29 现代故事 提交错误

sqlite3_open()

sqlite3_prepare()

sqlite3_step()

sqlite3_column()

sqlite3_finalize()

sqlite3_close()

1.sqlite3_open()

打开数据库。在操作数据库之前,必须先打开数据库。该函数打开一个到sqlite 数据库文件的连接并返回一个数据库连接对象。该操作是程序中调用的第一个SQLite函数,也是其他SQLite API的先决条件。许多SQLite 接口函数需要一个指向数据库连接对象的指针作为其第一个参数。

相关函数

SQLITE_APIintsqlite3_open(

const char*filename, /* 数据库文件名(UTF-8) */

sqlite3**ppDb /* OUT: SQLite 数据库句柄*/

);

SQLITE_APIintsqlite3_open16(

const void*filename, /* 数据库文件名(UTF-16) */

sqlite3**ppDb /* OUT: SQLite 数据库句柄*/

);

SQLITE_APIintsqlite3_open_v2(

const char*filename, /* 数据库文件名(UTF-8) */

sqlite3**ppDb, /* OUT: SQLite 数据库句柄*/

intflags, /* 标志*/

const char*zVfs /* 要使用的VFS 模块的名称*/

);

注意:如果要打开的数据文件不存在,则会创建一个同名的数据库文件。如果使用sqlite3_open和sqlite3_open_v2,数据库将使用UTF-8编码,而sqlite3_open16将使用UTF-16编码。

返回值:如果sqlite数据库成功打开(或创建),则返回SQLITE_OK,否则返回错误码。 sqlite3_errmsg()或sqlite3_errmsg16可用于获取数据库打开错误代码的英文描述。这两个函数定义为:

const char *sqlite3_errmsg(sqlite3*);

const void *sqlite3_errmsg16(sqlite3*);

无论数据库是否成功打开,都应该使用sqlite3_close()关闭数据库连接。

参数说明:

filename:需要打开的数据库文件的文件名。在sqlite3_open和sqlite3_open_v2中,该参数使用UTF-8编码,而在sqlite3_open16中,它使用UTF-16编码。

ppDb:即使发生错误,也会将数据库连接句柄返回给此参数。唯一的例外是,如果SQLite 无法分配内存来存储SQLite 对象,则ppDb 将返回NULL 值。

flags:作为数据库连接的附加控制参数,可以是SQLITE_OPEN_READONLY、SQLITE_OPEN_READWRITE 和SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE 之一。用于控制数据库的打开方式。它可以与SQLITE_OPEN_NOMUTEX、SQLITE_OPEN_FULLMUTEX、SQLITE_OPEN_SHAREDCACHE 和SQLITE_OPEN_PRIVATECACHE 结合使用。具体细节情况可以查看文档。

2.Sqlite3_prepare()

此函数将SQL 文本转换为准备好的语句对象并返回指向该对象的指针。该接口需要一个数据库连接指针和一个包含要准备的SQL语句的文本。它实际上并不执行(评估)SQL 语句,它只是准备执行SQL 语句。

函数定义

SQLITE_API

int sqlite3_prepare(

sqlite3 *db, /* 数据库句柄*//* 数据库句柄成功打开*/

const char *zSql, /* SQL 语句,UTF-8 编码*//* UTF8 编码的SQL 语句*/

int nByte, /* zSql 的最大长度(以字节为单位)。 *//* 参数sql的字节数,包括"" */

sqlite3_stmt **ppStmt, /* OUT: 语句句柄*//* 输出: 预编译语句句柄*/

const char **pzTail /* OUT: 指向zSql 未使用部分的指针*//* 输出: 指向sql 语句未使用部分*/

);

SQLITE_API int sqlite3_prepare_v2(

sqlite3 *db, /* 数据库句柄*/

const char *zSql, /* SQL语句,UTF-8编码*/

int nByte, /* zSql 的最大长度(以字节为单位)。 */

sqlite3_stmt **ppStmt, /* OUT: 语句句柄*/

const char **pzTail /* OUT: 指向zSql 未使用部分的指针*/

);

SQLITE_API int sqlite3_prepare16(

sqlite3 *db, /* 数据库句柄*/

const void *zSql, /* SQL 语句,UTF-16 编码*/

int nByte, /* zSql 的最大长度(以字节为单位)。 */

sqlite3_stmt **ppStmt, /* OUT: 语句句柄*/

const void **pzTail /* OUT: 指向zSql 未使用部分的指针*/

);

SQLITE_API int sqlite3_prepare16_v2(

sqlite3 *db, /* 数据库句柄*/

const void *zSql, /* SQL 语句,UTF-16 编码*/

int nByte, /* zSql 的最大长度(以字节为单位)。 */

sqlite3_stmt **ppStmt, /* OUT: 语句句柄*/

const void **pzTail /* OUT: 指向zSql 未使用部分的指针*/

);

这里我们只介绍sqlite3_prepare的参数:

db:数据指针。

zSql:sql语句,使用UTF-8编码。

nByte:如果nByte小于0,则函数取出zSql中从开头到第一个0终止符的内容;如果nByte不为负,则它是该函数可以从zSql读取的最大字节数。如果nBytes 为非负数,则zSql 在第一次遇到"/000/或"u000" 时终止。如果用户知道传入的sql 语句以"" 结尾,那么更好的做法是: 将nbytes 值设置为字符串的长度(包括"")。这可以防止SQLite 复制字符串并提高程序效率。

pzTail:如上所述,zSql在遇到终止符或达到设定的nByte后结束。如果zSql有剩余内容,则剩余内容存储在pZTail中,不包括终止符。如果pszTail不为NULL,则*pszTail指向sql中第一个传递的SQL语句的末尾。该函数只编译sql的第一条语句,因此*pszTail指向的内容不会被编译。

ppStmt:指向可使用sqlite3_step() 执行的已编译准备语句的指针。如果发生错误,则将其设置为NULL,例如如果输入文本不包含sql 语句。调用进程必须负责在使用完编译后的sql语句后使用sqlite3_finalize()删除它。

注意:如果执行成功,则返回SQLITE_OK,否则返回错误码。建议在任何当前程序中使用sqlite3_prepare_v2 函数。 sqlite3_prepare 仅用于向前兼容。

准备好的语句(prepared statements) object typedef struct sqlite3_stmt sqlite3_stmt;准备好的语句(prepared statements)对象代表一个简单的SQL语句对象的实例。这个对象通常被称为“准备好的语句”或“编译的SQL语句”或简称为“语句”。

Statement对象的生命周期经历这样的过程:

1.使用sqlite3_prepare_v2或相关函数创建该对象。

2.使用sqlite3_bind_*()将值绑定到主机参数。

3. 通过调用sqlite3_step 一次或多次来执行此sql。

4. 使用sqlite3——reset() 重置该语句,然后返回步骤2。执行此过程0 次或多次。

5.使用sqlite3_finalize()来销毁它

sqlite3_stmt结构体的具体内容在sqlite.h中没有定义。它只是一个抽象类型,一般在使用过程中对其指针进行操作。 sqlite3_stmt类型的指针实际上是指向Vdbe结构体的指针。

3.sqlite3_step()

此进程用于执行先前由sqlite3_prepare 创建的准备语句。执行该语句直到第一行结果可用。要继续查看第二行结果,只需再次调用sqlite3_setp() 即可。继续调用sqlite3_setp(),直到该语句完成。对于不返回结果的语句(例如INSERT、UPDATE 或DELETE),sqlite3_step() 仅执行一次并返回。

函数定义:int sqlite3_step(sqlite3_stmt*);

返回值:函数的返回值基于用于创建sqlite3_stmt参数的函数。如果使用旧版本的接口sqlite3_prepare() 和sqlite3_prepare16(),则返回值将为SQLITE_BUSY、SQLITE_DONE、SQLITE_ROW、SQLITE_ERROR 或SQLITE_MISUSE,而v2 版本的接口将为sqlite3_prepare_v2() 和sqlite3_prepare16_v2() 将返回两者这些结果代码和扩展结果代码。

对于所有V3.6.23.1及其之前的所有版本,需要在sqlite3_step()之后、后续sqlite3_step之前调用sqlite3_reset()。如果调用sqlite3_reset重置prepared语句失败,sqlite3_step将返回SQLITE_MISUSE,但在V3之后。 6.23.1,sqlite3_step()会自动调用sqlite3_reset。

描述:

当sqlite3_prepare()或其相关函数准备一条语句时,必须调用sqlite3_step()一次或多次来评估准备好的语句。

该函数的详细行为取决于sqlite3_prepare() (或其相关函数)生成哪种类型的准备好的语句。

该函数将返回以下结果之一来标识其执行结果:

SQLITE_BUSY: 忙。数据库引擎无法锁定数据以完成其工作。但可以尝试多次。

SQLITE_DONE: 已完成。 sql语句已成功执行。在调用sqlite_reset() 之前,不应由sqlite3_step() 再次调用当前预编译语句。

SQLITE_ROW: 查询生成结果。这时可以通过相关的‘列访问函数’来获取数据。再次调用sqlite3_step() 将获得下一个查询结果。

SQLITE_ERROR: 发生错误。此时可以通过sqlite3_ermmsg()获取相关错误信息。 sqlite3_step() 无法再次调用。

SQLITE_MISUSE: 库使用不正确。该功能使用不当。

4.int sqlite3_reset(sqlite3_stmt *pStmt)

sqlite3_reset 用于将准备好的语句对象重置为其初始状态,然后准备重新执行。所有SQL 语句变量都使用sqlite3_bind* 来绑定值,并使用sqlite3_clear_bindings 来重置这些绑定。 Sqlite3_reset 接口将准备好的语句重置为其代码的开头。 sqlite3_reset不会改变prepared语句上的任何绑定值,所以这里的猜测是语句执行过程中可能发生了其他变化,然后这条语句将其重置为绑定值被绑定时的状态。

它的返回值比较特殊。返回SQLITE_BUSY表示操作暂时无法执行,SQLITE_DONE表示操作完成,SQLITE_ROW表示执行完成有返回(执行select语句时)。当返回值为SQLITE_ROW时,我们需要对查询结果进行处理。 SQLITE3提供了sqlite3_column_*系列函数。

const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);

参数iCol为列号,从0开始。如果返回值有多行,可以再次调用sqlite3_step函数,然后从sqlite3_column_*函数中获取返回值。利用以上函数,基本可以完成对SQLITE3数据库的操作(但这里只说明文本数据类型)。

5. sqlite3_column()

此过程从执行sqlite3_step() 获得的结果集的当前行返回一列,以执行准备好的语句。 sqlite3_step每次获取结果集中的一列并停止时,可以多次调用该过程来查询该行中每一列的值。列操作的函数有多个,均以sqlite3_column 为前缀

const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);

int sqlite3_column_bytes(sqlite3_stmt*, int iCol);

int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);

双sqlite3_column_double(sqlite3_stmt*, int iCol);

int sqlite3_column_int(sqlite3_stmt*, int iCol);

sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);

const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);

const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);

int sqlite3_column_type(sqlite3_stmt*, int iCol);

int sqlite3_column_numeric_type(sqlite3_stmt*, int iCol);

sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);

阐明

第一个参数是指向从sqlite3_prepare 返回的准备好的语句对象的指针,第二个参数指定要返回的该行中的列的索引。最左边一列的索引号为0,可以使用sqlite3_colum_count()获得该行的列数。

(1) 得到数据行中某个列的数据

sqlite3_column_xxx(sqlite3_stmt*, int iCol);

sqlite3_step返回SQLITE_ROW后,用它来获取iCol列的数据。

其中,xxx代表:

blob:指向存储数据的内存的指针。

bytes, bytes16: 获取blob类型数据的大小,或者从文本转换为UTF8/UTF16的字符串长度。

double、int、int64:数值。

text、text16:字符串指针。

type: 该列的数据类型(SQLITE_INTEGER、SQLITE_FLOAT、SQLITE_TEXT、SQLITE_BLOB、SQLITE_NULL)

注意:如果该列使用与该列本身类型不同的数据读取方式,则获取的值为转换后的结果。

(2)得到数据行中某个列的数据的类型

int sqlite3_column_type(sqlite3_stmt*, int iCol);

返回值:SQLITE_INTEGER、SQLITE_FLOAT、SQLITE_TEXT、SQLITE_BLOB、SQLITE_NULL。

使用的方法与sqlite3_column_xxx()函数类似。

(3)

int sqlite3_column_count(sqlite3_stmt *pStmt);函数: 获取列数。如果进程没有返回值,比如update,就会返回0。

const char *sqlite3_column_name(sqlite3_stmt*,int);函数:获取列名。

const char *sqlite3_column_decltype(sqlite3_stmt *, int i);函数: 返回列数据类型。

获取当前行包含的数据条数int sqlite3_data_count(sqlite3_stmt *pStmt);如果sqlite3_step返回SQLITE_ROW,则可以获得列数,否则为零。

6.sqlite3_finalize

int sqlite3_finalize(sqlite3_stmt *pStmt);此过程会破坏先前由sqlite3_prepare 创建的准备好的语句。必须使用此函数销毁每个准备好的语句,以防止内存泄漏。在空指针上调用此函数没有任何效果,并且可以在准备好的语句的生命周期中的任何时间调用此函数:在执行语句之前,在一次或多次调用sqlite_reset 之后,或者在任何sqlite3_step 调用之后判断语句是否完成。实施。

示例:

sqlite3_finalize(pStmt);

pStmt=NULL;

7.sqlite3_close

此进程关闭先前使用sqlite3_open 打开的数据库连接。在调用此关闭函数之前,必须释放与此连接相关的任何准备好的语句。

int sqlite3_close(

sqlite3* pDB /* 由sqlite3_open 或基础相关函数打开的SQLite 对象句柄*/

);

描述:

该函数用于破坏sqlite3对象。返回SQLITE_OK表明该对象被成功销毁并且所有相关资源被成功回收。应用程序必须在关闭之前“最终确定”所有“准备好的语句”,并关闭所有“二进制句柄绑定(BLOB 句柄)”。如果关闭时有未完成的准备好的语句或二进制句柄,则该函数返回SQLITE_BUSY(5)。

示例:

如果(pDB!=NULL)

{

sqlite3_close(pDB);

pDB=空;

}

8.int sqlite3_exec

int sqlite3_exe(

sqlite3* pDB, /* sqlite3 句柄*/

const char* sql, /* 要执行的SQL语句*/

int (*callback)(void*,int,char**,char**), /* 执行/查询回调函数*/

void* pvoid, /* 传递给回调函数的第一个参数*/

char**errmsg /* 错误输出信息*/

);

描述:

该函数用于执行多条SQL语句。

该函数包装了之前版本的sqlite3_prepare()、sqlte3_step()和sqlite3_finalize()函数,以便用户可以通过简单的代码来执行多个SQL语句。

sqlite3_exec()接口执行多个由“;”分隔的SQL语句。如果回调函数不为NULL,则会对每一行查询结果调用该回调函数。如果没有指定回调函数,sqlite3_exec() 只会忽略查询结果。

当执行SQL语句时发生错误时,执行将被中断,并且所有后续语句将被忽略。如果errmsg参数不为空,任何错误信息都会写入sqlite3_malloc()获得的内存空间,即errmsg指向的内存。为了避免内存泄漏,应用程序应在不再需要错误消息后立即调用sqlite3_free() 来释放内存空间。如果errmsg 参数不为NULL,并且没有发生错误,则errmsg 将设置为NULL。

如果回调函数返回非零,sqlite3_exec()立即中断查询,不再执行后续的SQL语句或调用回调函数。 sqlite3_exec() 将返回SQLITE_ABORT 以结束执行。

示例:

sqlite3_exec(pDB, to_utf8("从id=123 的表名中删除;"), NULL, NULL, NULL);

sqlite3_exec(pDB, to_utf8("如果创建表

not exists tablename (id integer primary key,name text);"), NULL, NULL, NULL); sqlite3_exec(pDB, to_utf8("insert into tablename (name) values ("女孩不哭");"), NULL, NULL, NULL); if(sqlite3_exec(pDB, to_utf8("select * from tablename;"), sqlite_callback, NULL, &pszErrMsg) != SQLITE_OK) {     ...     sqlite3_free(pszErrMsg);     pszErrMsg = NULL; } 参阅:在 sqlite3 中使用回调函数(http://www.cnblogs.com/nbsofer/archive/2012/05/29/2523807.html)

9.int sqlite3_errcode

int sqlite3_errcode(     sqlite3* pDB    /* SQLite3 数据库句柄 */ ); 说明: 该函数返回最近一次调用 sqlite3_ API时产生的错误码. 示例: int errcode = sqlite3_errcode(pDB);

10.const char *sqlite3_errmsg

const char *sqlite3_errmsg(     sqlite3* pDB    /* SQLite3 数据库句柄 */ ); 说明:

该函数返回与pDB数据库指针相关的错误信息, 由英语书写. 用户不必考虑内存的释放, 其由SQLite内部管理, 它也将会在下产次调用函数时被覆盖. 示例: printf("%sn", sqlite3_errmsg(pDB));

11.int sqlite3_key

int sqlite3_key(     sqlite3 *db,                   /* Database to be rekeyed */         const void *pKey, int nKey     /* The key */ ); 功能:为加密的数据库指定密码,改函数在sqlite3_open之后调用

12.int sqlite3_rekey

int sqlite3_rekey(     sqlite3 *db,                   /* Database to be rekeyed */     const void *pKey, int nKey     /* The new key */ ); 功能:重设数据库密码,如果pKey = 0 或者 nKey = 0,这数据库不加密

13.int sqlite3_get_table

int sqlite3_get_table(     sqlite3*,               /* An open database */     const char *sql,       /* SQL to be executed */     char ***resultp,       /* Result written to a char *[]  that this points to */     int *nrow,             /* Number of result rows written here */     int *ncolumn,          /* Number of result columns written here */     char **errmsg          /* Error msg written here */ ); 功能:查询表. 参数1(IN):数据库句柄. 参数2(IN):sql语句,以结尾. 参数3(OUT):查询结果. 参数4(OUT):返回行数(多少条数据). 参数5(OUT):返回列数(多少字段). 参数6(OUT):返回错误信息. 返回值:SQLITE_OK成功,房子失败见错误信息.

14.void sqlite3_free_table(char **result);

void sqlite3_free_table(char **result); 功能:释放通过sqlite3_get_table查询保存的结果数据. 参数1(IN):要释放的数据指针.

15.int sqlite3_create_function

int sqlite3_create_function(     sqlite3 *,     const char *zFunctionName,     int nArg,     int eTextRep,     void*,     void (*xFunc)(sqlite3_context*,int,sqlite3_value**),     void (*xStep)(sqlite3_context*,int,sqlite3_value**),     void (*xFinal)(sqlite3_context*) ); 功能: const void *sqlite3_value_blob(sqlite3_value*); int sqlite3_value_bytes(sqlite3_value*); int sqlite3_value_bytes16(sqlite3_value*); double sqlite3_value_double(sqlite3_value*); int sqlite3_value_int(sqlite3_value*); sqlite_int64 sqlite3_value_int64(sqlite3_value*); const unsigned char *sqlite3_value_text(sqlite3_value*); const void *sqlite3_value_text16(sqlite3_value*); const void *sqlite3_value_text16le(sqlite3_value*); const void *sqlite3_value_text16be(sqlite3_value*); int sqlite3_value_type(sqlite3_value*); int sqlite3_value_numeric_type(sqlite3_value*); 功能:类似sqlite3_column_*函数 其他: const char *sqlite3_libversion(void); int sqlite3_libversion_number(void); 功能:获取版本号 sqlite_int64 sqlite3_last_insert_rowid(sqlite3*); 功能:获取最后插入的行标示. int sqlite3_changes(sqlite3*); 功能:获取最近执行的sqlite3_exec影响的行数. int sqlite3_total_changes(sqlite3*); 功能:获取自从数据库打开后有改动的函数 void sqlite3_interrupt(sqlite3*); 功能:打断或停止数据库当前操作. int sqlite3_complete(const char *sql); 功能:判断语句是否以分号(;)结尾 int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); 功能:设置查询忙碌时的回调处理 说明:缺省的回调函数为空,如果回调函数为空,表锁定后sqlite3_exec()执行会直接返回SQLITE_BUSY int sqlite3_busy_timeout(sqlite3*, int ms); 功能:设置查询超时时间(毫秒) char *sqlite3_mprintf(const char*,...); char *sqlite3_vmprintf(const char*, va_list); char *sqlite3_snprintf(int,char*,const char*, ...); 功能:格式化字符,需要用%q来代替%s.(主要是不用对分号"进行转义) void *sqlite3_malloc(int); void *sqlite3_realloc(void*, int); void sqlite3_free(void*); 功能:内存函数 int sqlite3_set_authorizer(     sqlite3*,     int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),     void *pUserData ); 功能:设置数据库授权 void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); void *sqlite3_profile(sqlite3*, void(*xProfile)(void*,const char*,sqlite_uint64), void*); void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); 功能:设置执行回调函数,sqlite3_exec(),sqlite3_step() ,sqlite3_get_table()时会调用 void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); 功能:设置事务回调函数 int sqlite3_errcode(sqlite3 *db); const char *sqlite3_errmsg(sqlite3*); 功能:获取错误码和错误消息 int sqlite3_bind_parameter_count(sqlite3_stmt*); 功能:返回需要绑定的参数数目(sql语句中问号?数量) const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); 功能:获取绑定参数名字,?参数返回NULL int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); 功能:获取绑定参数索引 int sqlite3_clear_bindings(sqlite3_stmt*);

用户评论

水波映月

终于找到这篇文章了!一直想学习 SQLite 但不太懂怎么操作

    有20位网友表示赞同!

逃避

感觉 iOS 开发还是离不开数据库的。

    有6位网友表示赞同!

烟花巷陌

这个标题一看就是针对我的,我最近在做 iOS 开发项目遇到一些数据管理的问题

    有18位网友表示赞同!

龙卷风卷走爱情

希望这些常用命令能解释清楚,方便实际操作

    有10位网友表示赞同!

男神大妈

感谢作者分享这份宝贵的信息,学习效率能提高很多

    有13位网友表示赞同!

汐颜兮梦ヘ

iOS 的 SQLite 是入门不错的选择,现在越来越多人使用它了

    有17位网友表示赞同!

你与清晨阳光

平时开发里遇到数据问题的时候真希望能快速查找到解决方法

    有19位网友表示赞同!

我怕疼别碰我伤口

看来学习 SQLite3 还是很有必要的,以后多用用感觉会很有帮助

    有18位网友表示赞同!

迁心

分享的文章质量很重要,期待作者能够讲解深入浅出

    有12位网友表示赞同!

单身i

之前总是看别人的代码不明白怎么做数据库操作,这篇文章应该能解决我的疑惑

    有6位网友表示赞同!

﹎℡默默的爱

学习 SQLite3 用途很多,这个标题很吸引人

    有20位网友表示赞同!

你很爱吃凉皮

iOS 开发中遇到数据问题的时候真希望能够快速找到解决方案

    有17位网友表示赞同!

柠栀

这个文章主题很重要,我希望可以包含详细的操作步骤

    有14位网友表示赞同!

孤独症

之前尝试过使用 SQLite3 但操作一直不太顺畅,期待学习更深层次的知识

    有7位网友表示赞同!

夏以乔木

相信很多 iOS 开发者都需要掌握 SQLite3 常用命令,这篇文章能够帮助我提升技能

    有20位网友表示赞同!

■□丶一切都无所谓

文章标题很明确,内容也一定很实用,期待作者能够讲清楚每一个命令的使用方法

    有10位网友表示赞同!

像从了良

学习完这些常用命令后,我相信可以更好地完成 iOS 项目中的数据操作

    有7位网友表示赞同!

【深入浅出:iOS SQLite3 常用操作指南】相关文章:

1.蛤蟆讨媳妇【哈尼族民间故事】

2.米颠拜石

3.王羲之临池学书

4.清代敢于创新的“浓墨宰相”——刘墉

5.“巧取豪夺”的由来--米芾逸事

6.荒唐洁癖 惜砚如身(米芾逸事)

7.拜石为兄--米芾逸事

8.郑板桥轶事十则

9.王献之被公主抢亲后的悲惨人生

10.史上真实张三丰:在棺材中竟神奇复活