sqlite

推荐列表 站点导航

当前位置:首页 > 数据库 > sqlite >

Android数据存储(三) SQLite数据库存储

来源:网络整理  作者:网友投稿  发布时间:2020-12-29 07:29
SQLite是Android系统内置的数据库,是一种轻量级的关系型数据库,它运算速度快,占用资源少,非常适合在移动设备上...

SQLite是Android系统内置的数据库,是一种轻量级的关系型数据库,它运算速度快,占用资源少,非常适合在移动设备上使用。同时,它不仅支持标准的SQL语法,还遵循了数据库的ACID事务。

一、创建数据库

Android为了让我们方便地管理数据库,提供了一个SQLiteOpenHelper帮助类,借助于这个类可以非常简单地对数据库进行创建和升级。

1 . SQLiteOpenHelper类介绍

该类是一个抽象类,其中包含两个抽象方法,分别是onCreate()和onUpgrade()我们必须在自己的类中重写这两个方法,分别在两个方法中实现创建、升级数据库的逻辑。

SQLiteOPenHelper中还有两个重要的实例方法,getReadableDatabase()和getWritableDatabase()这两个方法都可以创建或打开一个现有的数据库(如果数据库存在则直接打开,否则创建一个新的数据库),并返回一个可对数据库进行读写操作的对象。不同的是,当数据库不可写入的时候(比如磁盘空间已满),getReadableDatabase()返回的对象将以只读方式打开数据库,而getWritableDatabase()方法将抛出异常

SQLiteOpenHelper中有两个构造方法可供重写,一般使用参数少一点的那个构造方法。该构造方法接收四个参数,第一个参数是Context,第二个参数是数据库名,第三个参数允许我们在查询数据的时候返回一个自定义的Cursor,一般传入null,第四个参数表示当前数据库的版本号,可用于对数据库进行升级操作。构建出SQLiteOPenHelper的实例之后,再调用它的getReadableDatabase()或getWritableDatabase()方法就能够创建数据库了。此时,重写的onCreate()方法也会得到执行,所以通常会在这里处理一些创建表的逻辑。

2 . SQLite的数据类型

integer —————— 整型 real ————————浮点型 text ————————文本类型 blob ————————二进制类型

3 . 代码示例

1 . 首先创建一个Book表,建表语句如下:

create table Book( id integer primary key autoincrement, author text, price real, pages integer, name text )

2 . 新建类继承自SQLiteOpenHelper,重写其中的构造方法和抽象方法。

public class MyDatabaseHelper extends SQLiteOpenHelper{ //创建Book表的语句 public static final String CREATE_BOOK = 'create table Book(' + 'id integer primary key autoincrement, ' + 'author text, ' + 'price real, ' + 'pages integer, ' + 'name text)'; private Context mContext; //参数较少的构造方法 public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { super(context, name, factory, version); mContext = context; } @Override public void onCreate(SQLiteDatabase sqLiteDatabase) { //执行建表语句 sqLiteDatabase.execSQL(CREATE_BOOK); Toast.makeText(mContext, '数据表创建成功', Toast.LENGTH_SHORT).show(); } @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) { } }

3 . 在Activity中通过点击按钮触发创建数据库操作。

public class SqliteActivity extends AppCompatActivity { private MyDatabaseHelper myDatabaseHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sqlite); //创建数据库为BookStore.db,不返回自定义的Cursor,数据库版本为1 myDatabaseHelper = new MyDatabaseHelper(this, 'BookStore.db', null, 1); Button btnCreateDb = (Button) findViewById(R.id.create_db); btnCreateDb.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //点击按钮创建数据库,同时执行onCreate()中的建表语句 myDatabaseHelper.getWritableDatabase(); } }); } }

先使用构造函数获得SQLiteOpenHelper实例,然后在点击按钮时触发getWritableDatabase()方法,执行了数据库创建,然后默认调用onCreate()方法在数据库BookStore.db里面创建数据表Book。

这个时候运行程序,数据库BookStore.db和数据表应Book应该就创建好了。接下来我们要查看创建好的数据库。

二、查看数据库

这里我们采用adb和sqlite3来查看创建的数据库和数据表。

adb是Android SDK中自带的一个调试工具,它可以通过命令行对连接在电脑上的真机或者模拟器进行调试。它存放在SDK的platform-tools目录下 。你可以把该路径加到环境变量里面,以便在任意目录下可以通过命令行使用adb工具。

由于我使用的是Genymotion 模拟器,并且使用的是Genymotion默认的自带的adb工具,所以需要在Genymotion安装目录的tools目录下找到adb工具。

1 . 打开命令行,输入 adb shell打开adb交互命令行。

2 . 通过 cd 命令切换到指定目录, cd /data/data/packagename/databases/,此处的packagename是指你项目的包名,通过输入 ls 命令 查看该目录下的文件。会发现有刚才创建的BookStore.db数据库文件。

3 . 通过sqlite3来查看数据库结构。继续输入 sqlite3 BookStore.db打开数据库。输入.table就可以看见刚刚创建的Book表,输入.schema就可以看见看见建表语句。

如下图:

这里写图片描述

说明:
1 . 在 databases目录下还会有一个BookStore.db-journal文件是为了让数据库能够支持事务而产生的临时文件。
2 . 输入.table 之后还有一张表 android_metadata是每个数据库都会自动生成的表。

三、升级数据库
如果我们已经创建好了数据表Book,现在想再创建另一张数据表,我们是不能简单在onCreate()方法里面再添加

sqLiteDatabase.execSQL(CREATE_BOOK)

这句的,由于Book表已经存在,我们的onCreate()方法不会再执行,这样就不能再创建数据表了。

解决方法有两种:

卸载程序,此时数据库也会被删除,重新安装程序运行,就会执行onCreate()方法,就会创建两张数据表。 借助于onUpgrade()方法。要想让onUpgrade()方法执行,我们只需要在new SQLiteOpenHelper时将数据库的版本 改为大于2,这样就会执行该方法,代码如下。 myDatabaseHelper = new MyDatabaseHelper(this, 'BookStore.db', null, 2);

同时修改onUpgrade()中的代码:

public class MyDatabaseHelper extends SQLiteOpenHelper{ //创建Book1表的语句 public static final String CREATE_BOOK1 = 'create table Book1(' + 'id integer primary key autoincrement, ' + 'author text, ' + 'price real, ' + 'pages integer, ' + 'name text)'; //创建Book2表的语句 public static final String CREATE_BOOK2 = 'create table Book2(' + 'id integer primary key autoincrement, ' + 'author text, ' + 'price real, ' + 'pages integer, ' + 'name text)'; private Context mContext; //参数较少的构造方法 public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { super(context, name, factory, version); mContext = context; } @Override public void onCreate(SQLiteDatabase sqLiteDatabase) { //执行建表语句 sqLiteDatabase.execSQL(CREATE_BOOK1); sqLiteDatabase.execSQL(CREATE_BOOK2); Toast.makeText(mContext, '数据表创建成功', Toast.LENGTH_SHORT).show(); } @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) { sqLiteDatabase.execSQL('drop table if exists Book1'); sqLiteDatabase.execSQL('drop table if exists Book2'); onCreate(sqLiteDatabase); } }

先看要新建的表是否存在,如果存在先删除,然后在onUpgrade()方法中调用onCreate()方法创建数据表。

四、插入数据

上面我们在使用getReadableDatabase()创建和升级数据库,其实它还会返回一个SQLiteDatabase对象,借助于这个对象我们对数据库进行操作。

插入数据使用insert()方法,该方法接受三个参数,第一个参数是要插入数据的表名,第二个参数在未指定添加数据的情况下给某些可为空的列自动赋值NULL,一般直接传入null即可,第三个参数是ContentValues对象,它提供一系列的put()方法以键值对的方式给每个列名传入对应的数据。

//向数据库中添加数据 private void addData() { db = myDatabaseHelper.getWritableDatabase(); ContentValues contentValues1 = new ContentValues(); contentValues1.put('name', 'bingjian'); contentValues1.put('author', '冰鉴'); contentValues1.put('pages', 453); contentValues1.put('price', 16.0); //插入第一组数据 db.insert('Book1', null, contentValues1); contentValues1.clear(); contentValues1.put('name', 'bingjian2'); contentValues1.put('author', '冰鉴2'); contentValues1.put('pages', 455); contentValues1.put('price', 12.0); //插入第二组数据 db.insert('Book1', null, contentValues1); }

接下来按照上面的方式使用adb和sqlite3打开BooStore数据库,输入select * from Book1;就可以查看的刚才插入的数据。如下图:

这里写图片描述

五、更新数据

更新数据使用update()方法,该方法有四个参数,第一个参数是表名,第二个参数是ContentValues对象,在这里面组装穴ky"http://www.it165.net/qq/" target="_blank">qq4/NDCtcTK/b7do6y12sj9tdrLxLj2ss7K/dPD09rUvMr4uPzQwsSz0rvQ0LvyxLO8uNDQ1tC1xMr9vt2ho7K71ri2qL7NysfErMjPuPzQwsv509DQ0KGjPC9wPgo8L2Jsb2NrcXVvdGU+CjxwcmUgY2xhc3M9"brush:java;"> private void updateData() { ContentValues contentValues = new ContentValues(); contentValues.put('price', 10.99); db.update('Book1', contentValues, 'name = ?', new String[]{'bingjian'}); }

上面的update()函数第三个参数对应的SQL语句的where部分,表示去更新所有name等于?的行,而?是一个占位符,可以通过第四个参数的字符串替换占位符。

六、删除数据

更新数据使用delete()方法,该方法有三个参数,第一个参数是表名,第二、第三个参数是用于约束删除某一行或某几行中的数据。不指定就是默认删除所有行。

//删除数据库中的数据 private void deleteData() { db.delete('Book1', 'pages > ?', new String[]{'400'}); }

上面的代码会删除Book1表中的pages大于400的数据。也是使用了占位符来指定约束条件。

七、查询数据

对sqlite数据库的查询使用query()方法,哎方法有很多不同的重载方式,其中参数最少的一种也需要以下七个参数,下表给出了每个参数的含义。

query() 方法参数 对应SQL部分 描述
table   from table_name   指定查询的表名  
columns   select column1, column2   指定查询的列名  
selection   where column = value   指定where的约束条件  
selectionsArgs   -   为where中的占位符提供具体的值  
groupBy   group by column   指定需要group by 的列  
having   having column = value   对group by 后的结果进一步约束  
orderBy   order by column1, column2   指定查询结果的排序方式  

一般我们传入query的几个参数就可以获取到要查询的数据,该方法返回一个Cursor对象,查询到的所有数据都将从这个对象中取出。

//从数据库中查询数据 private String queryData() { Cursor cursor = db.query('Book1', null, null, null, null, null, null); String content = ''; if (cursor.moveToFirst()){ do{ //遍历Cursor对象,取出数据(注意字段的类型) String name = cursor.getString(cursor.getColumnIndex('name')); String author = cursor.getString(cursor.getColumnIndex('author')); int pages = cursor.getInt(cursor.getColumnIndex('pages')); double price = cursor.getDouble(cursor.getColumnIndex('price')); content = content + name; content = content + author; content = content + String.valueOf(pages); content = content + String.valueOf(price); }while (cursor.moveToNext()); } cursor.close(); return content; }

上面通过循环遍历从cursor中取出了查询结果。我们可以给query指定更多参数来获取我们想要的数据。

七、使用SQL语操作数据库

Android中可以直接通过函数执行SQL语句来操作数据库。下面是是简单的增删改查的例子。

//添加数据 db.execSQL('insert into Book1(name, author, pages, price) values(?, ?, ?, ?)', new String[] {'mybook', 'my', '123', '15.5'}); //删除数据 db.execSQL('delete from Book1 where pages > ?', new String[] {'120'}); //更新数据 db.execSQL('update Book1 set price = ? where name = ?', new String[]{}); //查询数据 db.rawQuery('select * from Book1', null);

以上就是sqlite的一些基础知识。

相关热词:

本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供用于网络技术学习参考,学习中请遵循相关法律法规!

本文地址: https://v30.fanwenzhu.com/sql/sqlite/10589.shtml

Copyright © www.juheyunku.com      关于 | 合作 | 声明 | 联系 | 更新 | 地图 | Tags

Android数据存储(三) SQLite数据库存储

2020-12-29 编辑:网友投稿

SQLite是Android系统内置的数据库,是一种轻量级的关系型数据库,它运算速度快,占用资源少,非常适合在移动设备上使用。同时,它不仅支持标准的SQL语法,还遵循了数据库的ACID事务。

一、创建数据库

Android为了让我们方便地管理数据库,提供了一个SQLiteOpenHelper帮助类,借助于这个类可以非常简单地对数据库进行创建和升级。

1 . SQLiteOpenHelper类介绍

该类是一个抽象类,其中包含两个抽象方法,分别是onCreate()和onUpgrade()我们必须在自己的类中重写这两个方法,分别在两个方法中实现创建、升级数据库的逻辑。

SQLiteOPenHelper中还有两个重要的实例方法,getReadableDatabase()和getWritableDatabase()这两个方法都可以创建或打开一个现有的数据库(如果数据库存在则直接打开,否则创建一个新的数据库),并返回一个可对数据库进行读写操作的对象。不同的是,当数据库不可写入的时候(比如磁盘空间已满),getReadableDatabase()返回的对象将以只读方式打开数据库,而getWritableDatabase()方法将抛出异常

SQLiteOpenHelper中有两个构造方法可供重写,一般使用参数少一点的那个构造方法。该构造方法接收四个参数,第一个参数是Context,第二个参数是数据库名,第三个参数允许我们在查询数据的时候返回一个自定义的Cursor,一般传入null,第四个参数表示当前数据库的版本号,可用于对数据库进行升级操作。构建出SQLiteOPenHelper的实例之后,再调用它的getReadableDatabase()或getWritableDatabase()方法就能够创建数据库了。此时,重写的onCreate()方法也会得到执行,所以通常会在这里处理一些创建表的逻辑。

2 . SQLite的数据类型

integer —————— 整型 real ————————浮点型 text ————————文本类型 blob ————————二进制类型

3 . 代码示例

1 . 首先创建一个Book表,建表语句如下:

create table Book( id integer primary key autoincrement, author text, price real, pages integer, name text )

2 . 新建类继承自SQLiteOpenHelper,重写其中的构造方法和抽象方法。

public class MyDatabaseHelper extends SQLiteOpenHelper{ //创建Book表的语句 public static final String CREATE_BOOK = 'create table Book(' + 'id integer primary key autoincrement, ' + 'author text, ' + 'price real, ' + 'pages integer, ' + 'name text)'; private Context mContext; //参数较少的构造方法 public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { super(context, name, factory, version); mContext = context; } @Override public void onCreate(SQLiteDatabase sqLiteDatabase) { //执行建表语句 sqLiteDatabase.execSQL(CREATE_BOOK); Toast.makeText(mContext, '数据表创建成功', Toast.LENGTH_SHORT).show(); } @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) { } }

3 . 在Activity中通过点击按钮触发创建数据库操作。

public class SqliteActivity extends AppCompatActivity { private MyDatabaseHelper myDatabaseHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sqlite); //创建数据库为BookStore.db,不返回自定义的Cursor,数据库版本为1 myDatabaseHelper = new MyDatabaseHelper(this, 'BookStore.db', null, 1); Button btnCreateDb = (Button) findViewById(R.id.create_db); btnCreateDb.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //点击按钮创建数据库,同时执行onCreate()中的建表语句 myDatabaseHelper.getWritableDatabase(); } }); } }

先使用构造函数获得SQLiteOpenHelper实例,然后在点击按钮时触发getWritableDatabase()方法,执行了数据库创建,然后默认调用onCreate()方法在数据库BookStore.db里面创建数据表Book。

这个时候运行程序,数据库BookStore.db和数据表应Book应该就创建好了。接下来我们要查看创建好的数据库。

二、查看数据库

这里我们采用adb和sqlite3来查看创建的数据库和数据表。

adb是Android SDK中自带的一个调试工具,它可以通过命令行对连接在电脑上的真机或者模拟器进行调试。它存放在SDK的platform-tools目录下 。你可以把该路径加到环境变量里面,以便在任意目录下可以通过命令行使用adb工具。

由于我使用的是Genymotion 模拟器,并且使用的是Genymotion默认的自带的adb工具,所以需要在Genymotion安装目录的tools目录下找到adb工具。

1 . 打开命令行,输入 adb shell打开adb交互命令行。

2 . 通过 cd 命令切换到指定目录, cd /data/data/packagename/databases/,此处的packagename是指你项目的包名,通过输入 ls 命令 查看该目录下的文件。会发现有刚才创建的BookStore.db数据库文件。

3 . 通过sqlite3来查看数据库结构。继续输入 sqlite3 BookStore.db打开数据库。输入.table就可以看见刚刚创建的Book表,输入.schema就可以看见看见建表语句。

如下图:

这里写图片描述

说明:
1 . 在 databases目录下还会有一个BookStore.db-journal文件是为了让数据库能够支持事务而产生的临时文件。
2 . 输入.table 之后还有一张表 android_metadata是每个数据库都会自动生成的表。

三、升级数据库
如果我们已经创建好了数据表Book,现在想再创建另一张数据表,我们是不能简单在onCreate()方法里面再添加

sqLiteDatabase.execSQL(CREATE_BOOK)

这句的,由于Book表已经存在,我们的onCreate()方法不会再执行,这样就不能再创建数据表了。

解决方法有两种:

卸载程序,此时数据库也会被删除,重新安装程序运行,就会执行onCreate()方法,就会创建两张数据表。 借助于onUpgrade()方法。要想让onUpgrade()方法执行,我们只需要在new SQLiteOpenHelper时将数据库的版本 改为大于2,这样就会执行该方法,代码如下。 myDatabaseHelper = new MyDatabaseHelper(this, 'BookStore.db', null, 2);

同时修改onUpgrade()中的代码:

public class MyDatabaseHelper extends SQLiteOpenHelper{ //创建Book1表的语句 public static final String CREATE_BOOK1 = 'create table Book1(' + 'id integer primary key autoincrement, ' + 'author text, ' + 'price real, ' + 'pages integer, ' + 'name text)'; //创建Book2表的语句 public static final String CREATE_BOOK2 = 'create table Book2(' + 'id integer primary key autoincrement, ' + 'author text, ' + 'price real, ' + 'pages integer, ' + 'name text)'; private Context mContext; //参数较少的构造方法 public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { super(context, name, factory, version); mContext = context; } @Override public void onCreate(SQLiteDatabase sqLiteDatabase) { //执行建表语句 sqLiteDatabase.execSQL(CREATE_BOOK1); sqLiteDatabase.execSQL(CREATE_BOOK2); Toast.makeText(mContext, '数据表创建成功', Toast.LENGTH_SHORT).show(); } @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) { sqLiteDatabase.execSQL('drop table if exists Book1'); sqLiteDatabase.execSQL('drop table if exists Book2'); onCreate(sqLiteDatabase); } }

先看要新建的表是否存在,如果存在先删除,然后在onUpgrade()方法中调用onCreate()方法创建数据表。

四、插入数据

上面我们在使用getReadableDatabase()创建和升级数据库,其实它还会返回一个SQLiteDatabase对象,借助于这个对象我们对数据库进行操作。

插入数据使用insert()方法,该方法接受三个参数,第一个参数是要插入数据的表名,第二个参数在未指定添加数据的情况下给某些可为空的列自动赋值NULL,一般直接传入null即可,第三个参数是ContentValues对象,它提供一系列的put()方法以键值对的方式给每个列名传入对应的数据。

//向数据库中添加数据 private void addData() { db = myDatabaseHelper.getWritableDatabase(); ContentValues contentValues1 = new ContentValues(); contentValues1.put('name', 'bingjian'); contentValues1.put('author', '冰鉴'); contentValues1.put('pages', 453); contentValues1.put('price', 16.0); //插入第一组数据 db.insert('Book1', null, contentValues1); contentValues1.clear(); contentValues1.put('name', 'bingjian2'); contentValues1.put('author', '冰鉴2'); contentValues1.put('pages', 455); contentValues1.put('price', 12.0); //插入第二组数据 db.insert('Book1', null, contentValues1); }

接下来按照上面的方式使用adb和sqlite3打开BooStore数据库,输入select * from Book1;就可以查看的刚才插入的数据。如下图:

这里写图片描述

五、更新数据

更新数据使用update()方法,该方法有四个参数,第一个参数是表名,第二个参数是ContentValues对象,在这里面组装穴ky"http://www.it165.net/qq/" target="_blank">qq4/NDCtcTK/b7do6y12sj9tdrLxLj2ss7K/dPD09rUvMr4uPzQwsSz0rvQ0LvyxLO8uNDQ1tC1xMr9vt2ho7K71ri2qL7NysfErMjPuPzQwsv509DQ0KGjPC9wPgo8L2Jsb2NrcXVvdGU+CjxwcmUgY2xhc3M9"brush:java;"> private void updateData() { ContentValues contentValues = new ContentValues(); contentValues.put('price', 10.99); db.update('Book1', contentValues, 'name = ?', new String[]{'bingjian'}); }

上面的update()函数第三个参数对应的SQL语句的where部分,表示去更新所有name等于?的行,而?是一个占位符,可以通过第四个参数的字符串替换占位符。

六、删除数据

更新数据使用delete()方法,该方法有三个参数,第一个参数是表名,第二、第三个参数是用于约束删除某一行或某几行中的数据。不指定就是默认删除所有行。

//删除数据库中的数据 private void deleteData() { db.delete('Book1', 'pages > ?', new String[]{'400'}); }

上面的代码会删除Book1表中的pages大于400的数据。也是使用了占位符来指定约束条件。

七、查询数据

对sqlite数据库的查询使用query()方法,哎方法有很多不同的重载方式,其中参数最少的一种也需要以下七个参数,下表给出了每个参数的含义。

query() 方法参数 对应SQL部分 描述
table   from table_name   指定查询的表名  
columns   select column1, column2   指定查询的列名  
selection   where column = value   指定where的约束条件  
selectionsArgs   -   为where中的占位符提供具体的值  
groupBy   group by column   指定需要group by 的列  
having   having column = value   对group by 后的结果进一步约束  
orderBy   order by column1, column2   指定查询结果的排序方式  

一般我们传入query的几个参数就可以获取到要查询的数据,该方法返回一个Cursor对象,查询到的所有数据都将从这个对象中取出。

//从数据库中查询数据 private String queryData() { Cursor cursor = db.query('Book1', null, null, null, null, null, null); String content = ''; if (cursor.moveToFirst()){ do{ //遍历Cursor对象,取出数据(注意字段的类型) String name = cursor.getString(cursor.getColumnIndex('name')); String author = cursor.getString(cursor.getColumnIndex('author')); int pages = cursor.getInt(cursor.getColumnIndex('pages')); double price = cursor.getDouble(cursor.getColumnIndex('price')); content = content + name; content = content + author; content = content + String.valueOf(pages); content = content + String.valueOf(price); }while (cursor.moveToNext()); } cursor.close(); return content; }

上面通过循环遍历从cursor中取出了查询结果。我们可以给query指定更多参数来获取我们想要的数据。

七、使用SQL语操作数据库

Android中可以直接通过函数执行SQL语句来操作数据库。下面是是简单的增删改查的例子。

//添加数据 db.execSQL('insert into Book1(name, author, pages, price) values(?, ?, ?, ?)', new String[] {'mybook', 'my', '123', '15.5'}); //删除数据 db.execSQL('delete from Book1 where pages > ?', new String[] {'120'}); //更新数据 db.execSQL('update Book1 set price = ? where name = ?', new String[]{}); //查询数据 db.rawQuery('select * from Book1', null);

以上就是sqlite的一些基础知识。

本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供学习参考!
本文地址为 https://v30.fanwenzhu.com/sql/sqlite/10589.shtml

相关文章

风云图片

推荐阅读

返回sqlite频道首页