热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android数据库(1)、SQLite数据库介绍

一、关系性数据库 关系型数据库主要有以下三个特征,尤为明显,如果没有这个三个特征约束,当多个客户端使用数据的时候就会出现各种各样的错误,所以关系型数据库定义这些约束,让客户端程序只

一、关系性数据库

  关系型数据库主要有以下三个特征,尤为明显,如果没有这个三个特征约束,当多个客户端使用数据的时候就会出现各种各样的错误,所以关系型数据库定义这些约束,让客户端程序只要遵守这个规则便可以规避很多的错误。   这三个特征主要是:

  • 强类型
  • 引用完整性
  • 事物

 

1、强类型:

      大多数的数据库都是强类型的,要求数据库引擎严格执行,引擎通常定义一些原生的数据类型,它描述可以存进数据库当中数据的具体类型,这些类型通常是各种长度的浮点数,字符串,整数等,特定的实现,这个类型不能让用户自己特定的去扩展,当引擎定义了关系,数据库当中将无法企图把错误的数据类型的数据存入列当中,   例如:尝试插入一个包含一个字符串作为第三个特性的元组到一个指定第三特性应该是一个浮点数的关系当中,通常引擎会报错,将插入失败。  

2、引用完整性

      在关系型数据库当中,原生类型可以通过声明一个关系中的列到另一个关系的一个引用进行扩展,也就是我们常说的主外建关系,数据库架构师可以声明一个关系中一些列的内容是其他关系中类似类型列的一个引用,下图进行外建的演示:
上述就是最简单的主外建关系,通过表A当中的外建和表B进行连接,从而如果可以在表A当中获取到数据就可以在表B当中进行查询,   想要实现上述的要求,必须遵循数据库引擎提供的引用完整性,因为数据库引擎将会强制的去执行引用完整性约束,该约束主要分为以下的两种类型,   2.1 强制会去执行表B的主键约束,就如上述表B当中的主键。要保证在表B当中主键列当中主键的唯一性,也就是不可以重复,例如当表B当中的主键有A,B,C三个值,现在插入一行数据的主键列为A或B或C将会失败,因为破坏了主键约束的唯一性。   2.2、强调表A的引用完整性,所谓什么是引用完整性呢,就是表A当中的外键要么是null,要么该指就一定在表B的主键当中存在,下面有两种情况会破环引用的完整性,

  • 如果给表A当中插入一行数据,该数据的外键值在表B当中没有,那么该操作则失败。
  • 如果删除表B当中的一条数据,并且该条数据被表A当中的外键所引用,那么该操作失败

  上述两种情况也是我们开发当中常常会用到情况,所以我们的解决方式便是,  

  • 先插入表B当中的数据,然后插入表A当中的数据
  • 先将表A当中引用表B的外键值置为null,然后删除表B当中数据

 

3、数据库事务

      事务:对数据的一组操作当作为一个单位去执行,要么全部失败,要么全部成功。事物有以下几个特点,常常被开发者侃侃而谈,便是

  • 原子性:全部成功,全部失败,操作被视为一个单位,不能将操作分离
  • 一致性:事务开启之前,数据库处于有效状态,那么事务开启之后,数据库仍然处于有效状态,不能因为事物导致数据约束被破坏
  • 隔离性:执行完事物以后,数据库的状态可以通过依次执行事物中的命令达到同样的状态
  • 持久性:事物一旦完毕,就不能丢失,比如电源故障等,物理环境都不能撼动。

 

二、SQL语言

  什么是SQL语言呢,就是操作数据库以及数据库当中的数据的命令。称之为SQL语言,SQL语言是由数据库引擎解释并且执行的,SQL语言大多数开发者都或多或少的已经掌握,所以该部分内容为回顾内容,笔者并不打算详细讲解。如有不同,可以自行Google,Baidu。   SQL语言主要分为六大类,分别是DDL(date definition Language)数据定义语言、DML(Data Manipulation Language)数据操作语言、DQL(Data Query Language)数据查询语言,TPL事物处理语言,DCL数据控制语言、CCL指针控制语言。   其中最为常用的便是上述当中的前三类语言,而后面的三类用的不是很多,所以对前三类语言做详细介绍,而后面的三类简单了解就可以了。  

1、DDL(数据定义语言)

  主要描述的是数据库当中所包含的数据结构,最常见的DDL语言就是用来定义一张表,包含列数、列类型、还有删除一张表,下面为创建一个User表的SQL语言描述。    

1 #删除表结构
2 DROP TABLE users; 3 4 #创建一个新的表结构 5 CREATE TABLE users{ 6 _id INTEGER PRIMARY KEY AUTOINCREMENT, 7 name_raw_user_id INTEGER REFERENCES raw_users(_id), 8 photo_id INTEGER REFERENCES data(_id), 9 photo_file_id INTEGER REFERENCES photo_files(_id), 10 custom_ringtone TEXT, 11 send_to_voicemail INTEGER NOT NULL DEFAULT 0, 12 time_contacted INTEGER NOT NULL DEFAULT 0, 13 last_time_contacted INTEGER, 14 starred INTEGER NOT NULL DEFAULT 0, 15 has_phone_number INTEGER NOT NULL DEFAULT 0, 16 lookup TEXT, 17 status_update_id INTEGER REFERENCES data(_id) 18 19 };

 

这里需要注意的是:在定义一张表的时候,所有数据库语法的关键字大写,并且列名称是唯一的,这里不允许列名称之间相互重复。并且表的名称在同一个数据库当中也不能重复,通常使用的是一个复数名词   除了创建表以外,SQL的DDL允许创建其他标准的RDBMS的数据结构,而RDBMS当中常见的标准的数据结构除了相应的表以外,还有相应的视图(View)、触发器(trigger)、索引(index)。这里把定义一个给定数据库当中所有对象的DDL语句集合叫做这个数据库的模式(schema),其他的数据结构在什么场景下会用到呢?它们分别扮演着什么样子的角色呢,  

  • 视图(View):
  • 触发器(trigger):
  • 索引(index):

   

2、DML(数据库操作语言)

  这类型语句主要操作的是数据库当中数据的变化,有三个类型,分别是插入语句(insert),删除语句(delete),修改语句(update)。下面我们对上述定义的表结构进行数据上面的操作  

1 #插入语句
2 INSERT INTO users( 3 name_raw_contact_id,photo_id,photo_file_id, 4 last_time_contacted,status_update_id) 5 VALUES(null,null,null,18944658190,null); 6 7 #更新语句 8 UPDATE users SET starred=1, has_phone_number=1 WHERE _id=3; 9 10 #删除语句 11 DELETE FROM users WHERE _id=2;

  注意:插入数据的时候,一般要主要强类型的问题,而也要关注主键为NULL以及主键重复的问题(自增长可以解决),还有就是如果字段通过NOT NULL修饰的时候,一般会在定义表结构的时候会给出相应的默认值。  

3、DQL(数据库查询语句)

  查询语句是最难的,也是使用最为平凡的语句,在关系术语当中,查询创建一个新的关系(通过一个虚拟表),即就是一个或者多个表的叉积的投影约束,具体的查询语句该怎么写请各位看客自行Google,或者baidu,如下所示一个查询示例,  

1 #查询语句
2 SELECT rc.display_name, u.starred 3 FROM users u INNER JOIN raw_users ru 4 ON u.name_raw_contact_id=rc._id 5 WHERE NOT ru.display_name IS NULL 6 ORDER BY ru.display_name ASC;

  连接是两个表的叉积的重要凭证。两个表的一个完整叉积把1个表的每一行于第二个表中每一行进行合拼,在上述的语句当中,users表于raw_contacts表进行连接。叉积的结果将有C(users)*C(raw_contacts)行。   完整的叉积有时候不是非常有用,在查询中 ON字句限制只有name_raw_contacts_id列的值和raw_contacts表中_id列的值相等的时候进行叉积,连接所产生的新的关系包含users表当中的行加上raw_contacts表当中的相应信息。这就非常有用了,下面有一个关于叉积理解的图,相信大家会理解什么是叉积的概念  
  根据上述的这个小示例,我们很快就会明白多表查询的原理是什么,主要就是通过条件去约束叉积,然后拿到我们想要的数据。到了这里,基本的SQL语言也就差不多了,剩下三种语言类型。  

三、SQLite入门

  Android端使用的数据库就是开源数据库SQLite,它是一个小型的无服务器的数据库,由于这种数据库的种种特性,让它成为了在手机端极具吸引力的数据库之一,大体说一下都有什么好处,让该数据库这么火热,   该数据库是2000年开发的,当初开发的初衷就是轻量级方式管理结构话数据,所以非常的轻便,具体的优点有以下几点  

  • 存储在里面的数据持久化的跨进程和电源存在。
  • 跨越系统软件升级和重新安装
  • 处理多种异常情况,非常优雅,比如:低内存环境、磁盘错误、电池电量不足、都不足矣破坏已经持久化的数据

  当然缺点同时也是存在,关系数据库的几个重要特征部分丢失,SQLite当中没有强类型的支持,虽然有引用完整性的支持,但是默认是关闭的,唯独事务默认情况是开启的。   SQLite数据库其实就是一个文件。在Android设备当中大多数应用程序把数据库存储在文件系统沙箱当中,位于名为datebase的子目录当中,例如对于包是com.suansuan.application的应用程序,其数据库极有可能位于目录/data/data/com.suansuan.application/datebases中。   在以前人们想象能否将数据库放入到SD卡下,让其自己应用程序的数据库被多个程序所共享,但是相比于这么做Android提供了更好的解决思路。  

1、SQLite语法

  命令行当中是用sqlite3的时候,首先要记住每条命令必须以分号结束,就和我们写代码的时候一样。   当然还有一些命令,我们称之为元命令,这些命令不属于数据库所有,而是SQLite3去解释与执行,这些命令都是以,开头的命令,其中最常用的就是.help和.exit .schema命令   其余的就是常用的SQL命令了,当然也可以叫做SQL语句  

2、支持的数据类型

  前文已经说过SQLite数据库当中没有强引用的支持,实际上列的类型仅仅只是注释,列的类型仅仅只是提示而已,以帮助SQL引擎为此刻存储在该列的数据选择高效的表示。SQL引擎使用一些简单的规则来调节“类型相似性”,从而决定内部存储类型。这些规则几乎不可见,我们开发能感觉到的是给定数据集占用的磁盘数量而已。   实际开发当中,Google开发人员限制自己只使用SQLite的4种基本类型,(integer、real、text、blob)并且显式的使用文本来表示时间戳,使用integer来表示boolean值。   我们通过一个例子,来了解SQLite当中的“类型弱化”  

1 sqlite> create table test(
2 ...> c1 biginteger, c2 smalldatetime, c3 float(9,3)); 3 sqlite> insert into test values("la","la","la"); 4 sqlite> select * from test; 5 la|la|la

3、关于约束

  3.1、主键约束 我们可以将列的约束定义在表结构当中,比如我们常常用来修饰主键的 PRIMARY KEY的约束,唯一,表示这一行。同时SQLite支持非整数主键、支持多列复合主键,这里需要注意一下,关于非整数主键,除了“唯一”约束以外,应该还存在“非空”约束。但是由于SQLite早期版本的疏忽,SQLite允许Null作为非整数主键。所以会出现很多行主键为NULL的情况(此NULL非彼NULL),从而我们需要使用代码给插入数据的主键做非空判断,要不然我们数据库当中就会出现无法通过其主键都无法区分的数据,笔者这里把这些数据叫做“脏数据”   通过上述的问题,很多开发人员都使用integer来做为主键列,同时将主键设置为自增长,PRIMARY KEY AUTOINCREMENT。并且SQL引擎为了解决上述问题,会默认的在表当中加入一个隐式的id,    关于自增长,我们可以通过下面示例来了解  

1 sqlite> create table test(
2 ...> key integer primary key, 3 ...> val text); 4 sqlite> insert into test(val) values("something"); 5 sqlite> insert into test(val) values("liusuansuan"); 6 sqlite> select * from test; 7 1|something 8 2|liusuansuan 9 sqlite>

 

  自增长非常好用,可以唯一表示我们的数据,并且我们都不用去关心,但是正是因为我们的不关心将导致大量丑陋且愚蠢的代码存在,比如我们添加一个新行,并且需要将新行的id存储在SP当中,以便下次快速访问,这种情况下,各位看客想想该如何实现呢。其实笨办法确实有,并且笔者只想到了一种,如果看客有好的想法可以下方留言,那就是再查一遍,   3.2、外键约束 上文提到过外键约束,SQLite不强制执行外键约束,其实和SQLite列类型类似相似本质上都是注释,但是可以通过修改相应的属性来让SQLite强制执行外键约束

  •  pragma FOREIGN_KEYS=true 

通过上述指令开启外键的引用完整性。   下面我们来看一下关于外键注释:  

1 sqlite> creaet table people(
2 ...> name text, address integer references addresses(id)); 3 Error: near "creaet": syntax error 4 sqlite> create table people( 5 ...> name text, address integer references addresses(id)); 6 sqlite> create table addresses( 7 ...> id integer primary key, street text); 8 sqlite> insert into people values("liupengcheng",99); 9 sqlite> insert into addresses(street) values("shahe"); 10 sqlite> select * from people; 11 liupengcheng|99 12 sqlite> select * from addresses; 13 1|shahe 14 sqlite> select * from people, addresses where address=id; 15 sqlite>

 

上述语句,如果是在支持引用完整性的数据库当中,第一个insert将失败,并且第一个create table people也将失败,因为找不到addresses这个外键表,很显然上述我们的试验都成功了,也就意味这SQLite数据库不会去强制执行外键约束。   但是SQLite的优点就是灵活方便,如果我们需要设计一个复杂类型的、并且多个表通过外键所连接,像这种时候,易于修改和高效的数据存储反而成为了SQLite的闪光点,Google官方文档中描述,鼓励开发人员使用标准范式,然后让开发这自己编写代码的时候自己规划引用完整约束,而不是依赖数据库去实现。   下面我们来模拟一个简单的连接    

1 sqlite> create table people(
2 ...> name text, address integer references addresses(id)); 3 sqlite> create table addresses(id integer primary key, street text); 4 sqlite> insert into addresses(street) values("北京"); 5 sqlite> insert into addresses(street) values("上海"); 6 sqlite> insert into people values("张飞“,1); 7 sqlite> insert into people values("张飞",1); 8 sqlite> insert into people values("关羽",2); 9 sqlite> insert into people values("刘备",2); 10 sqlite> select name,street from people,addresses where address=id; 11 张飞|北京 12 关羽|上海 13 刘备|上海

  SQLite中还支持一些其他的约束,比如:   unique:该约束表示SQLite将拒绝任何试图在表中添加将导致该列出现重复值的一行。 not null:该约束表述SQLite将拒绝任何试图将表中数据置为NULL的所有操纵。 check(expression):当次约束修饰列时,每当一个新行添加到表中时,或当修改现有的行时,都会对表达式求值,如果求值的结果转化整数为0时,该操作将失败,操作将取消。如果表达式的计算结果为NULL或者任何其他非零值,则操作成功   下面展示一个列约束:  

1 sqlite> create table test(
2 ...> c1 text unique, c2 text not null, c3 text check(c3 in ("OK","Dandy"))); 3 sqlite> insert into test values("dandy","dandy","dandy"); 4 Error: CHECK constraint failed: test 5 sqlite> insert into test values("dandy","dandy","Dandy"); 6 sqlite> insert into test values("dandy","dandy","Dandy"); 7 Error: UNIQUE constraint failed: test.c1 8 sqlite> insert into test values("dandy",null,"Dandy"); 9 Error: NOT NULL constraint failed: test.c2

4、SQLite数据库示例

  在开始我们的程序示例之前,我们需要对我们数据库当中的数据进行一些格式化,好方便我们之后的查看数据。使用SQLite的元命令来进行数据库数据展示的格式化。  

1 sqlite>.header on
2 sqlite>.mode column
3 sqlite>.timer on

具体详细内容,可以参考SQLite元命令
http://www.runoob.com/sqlite/sqlite-commands.html   我们来尝试去创建一个完整的User的数据库。   1、创建User表

1 sqlite> create table users(
2 ...> _id integer primary key autoincrement, 3 ...> name text not null); 4 sqlite>

 

我们需要一个字段是用来记录这条记录是什么时候被修改的,好方便我们以后对数据的修改

1 sqlite> alter table users add last_modified_time text;
2 Run Time: real 0.003 user 0.000000 sys 0.000000

  2、创建触发器   我们让刚刚我们定义完的字段,可以根据我们插入数据,或者是添加数据跟随我们插入数据和更新数据取当前最新的时间。这里定义两个触发器,一个是跟随insert所进行触发,一个根据update进行触发。  

1 sqlite> create trigger t_users_audit_i
2 ...> after insert
3 ...> on users 4 ...> begin 5 ...> update users set last_modified_time=datetime('now','utc') 6 ...> where rowid=new.rowid; end; 7 Run Time: real 0.003 user 0.000000 sys 0.000000 8 9 sqlite> create trigger t_users_audit_u 10 ...> after update 11 ...> on users 12 ...> begin 13 ...> update users set last_modified=datetime('now','utc') 14 ...> where rowid=new.rowid; 15 ...> end; 16 17 Run Time: real 0.003 user 0.000000 sys 0.000000

 

上述触发器创建的时候用到了datetime数据库内置和日期相关的函数。具体内容可以查看http://www.runoob.com/sqlite/sqlite-date-time.html

  现在我们插入一条数据来验证我们刚刚创建的结构是否正确。  

1 sqlite> insert into users(name) values("liupengcheng");
2
3 Run Time: real 0.003 user 0.000000 sys 0.004000
4
5 sqlite> select * from users; 6 7 _id name last_modified_time 8 ---------- ------------ ------------------- 9 2 liupengcheng 2018-03-09 09:50:40 10 11 Run Time: real 0.000 user 0.000000 sys 0.000000

 

我们的User可能需要地址,比如客户的收货地址,所以我们创建一个地址表,

1 sqlite> create table addresses(
2 ...> _id integer primary key autoincrement, 3 ...> number integer not null, 4 ...> unit text, 5 ...> street text not null, 6 ...> city integer references cities); 7 8 Run Time: real 0.004 user 0.000000 sys 0.000000

  如果我们引用完整性的支持已经开启的话,这个表的定义肯定会导致一个错误,因为这里cities这张表是不存在的。不过在SQLite数据库的默认配置当中,是没有问题的,我们可以稍后去定义cities这张表。   现在我们的用户存在了,地址表也存在了,这里分析得到,一个用户可以有多个收货地址,一个收货地址可以被多个人多共有,所以这里的关系是多对多,一般的主外键支持一对多,如果是多对多的关系的话,我们就需要建立第三张表专门的让上述两张表进行对应了。  

1 sqlite> create table users_addresses(
2 ...> users integer references users, 3 ...> address integer references addresses); 4 5 Run Time: real 0.004 user 0.000000 sys 0.004000

  现在我们来我们创建的数据库添加数据

1 insert into users(name) values("wangyiqi"); 2 insert into users(name) values("wwangpeng"); 3 insert into users(name) values("liuna"); 4 insert into users(name) values("yangqiqi"); 5 sqlite> select * from users; 6 7 _id name last_modified_time 8 ---------- ------------ ------------------- 9 2 liupengcheng 2018-03-09 09:50:40 10 3 wangyiqi 2018-03-09 10:18:42 11 4 wwangpeng 2018-03-09 10:18:42 12 5 liuna 2018-03-09 10:18:42 13 6 yangqiqi 2018-03-09 10:19:01 14 Run Time: real 0.003 user 0.000000 sys 0.000000 15 16 17 insert into addresses(number,street) values(651, "北京昌平"); 18 insert into addresses(number,street) values(1600, "上海浦东"); 19 insert into addresses(number,street) values(259, "哈尔滨江北"); 20 insert into addresses(number,street) values(693, "甘肃天水"); 21 insert into addresses(number,street) values(1658, "北京朝阳"); 22 sqlite> select * from addresses; 23 24 _id number unit street city 25 ---------- ---------- ---------- ------------ ---------- 26 1 651 北京昌平 27 2 1600 上海浦东 28 3 259 哈尔滨江 29 4 693 甘肃天水 30 5 1658 北京朝阳 31 Run Time: real 0.000 user 0.000000 sys 0.000000 32 33 34 insert into users_addresses(users,address) values(2,1); 35 insert into users_addresses(users,address) values(3,2); 36 insert into users_addresses(users,address) values(4,3); 37 insert into users_addresses(users,address) values(5,4); 38 insert into users_addresses(users,address) values(6,5); 39 sqlite> select * from users_addresses; 40 41 users address 42 ---------- ---------- 43 2 1 44 3 2 45 4 3 46 5 4 47 6 5 48 Run Time: real 0.000 user 0.000000 sys 0.000000

现在数据也有了,关系也键全了,现在可以使用关联关系进行查看我们之前所编辑的数据实体了。

 

1 sqlite> select name,street,number from users,addresses,users_addresses where users._id = users_addresses.users and addresses._id = users_addresses.address;
2
3 name street number
4 ------------ ------------ ----------
5 liupengcheng 北京昌平 651
6 wangyiqi 上海浦东 1600
7 wwangpeng 哈尔滨江 259
8 liuna 甘肃天水 693
9 yangqiqi 北京朝阳 1658
10
11 Run Time: real 0.000 user 0.000000 sys 0.000000

如果我们想确定一个地址下面有多少用户,我们可以使用count函数和group by字句来实现。

 

1 select count(name),number,street
2 from users,addresses,users_addresses 3 where users._id=users_addresses.users 4 and addresses._id=users_addresses.address 5 group by number,street; 6 7 count(name) number street 8 ----------- ---------- --------------- 9 1 259 哈尔滨江北 10 1 651 北京昌平 11 1 693 甘肃天水 12 1 1600 上海浦东 13 1 1658 北京朝阳 14 15 Run Time: real 0.000 user 0.000000 sys 0.000000

 


推荐阅读
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • 基于PgpoolII的PostgreSQL集群安装与配置教程
    本文介绍了基于PgpoolII的PostgreSQL集群的安装与配置教程。Pgpool-II是一个位于PostgreSQL服务器和PostgreSQL数据库客户端之间的中间件,提供了连接池、复制、负载均衡、缓存、看门狗、限制链接等功能,可以用于搭建高可用的PostgreSQL集群。文章详细介绍了通过yum安装Pgpool-II的步骤,并提供了相关的官方参考地址。 ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • “你永远都不知道明天和‘公司的意外’哪个先来。”疫情期间,这是我们最战战兢兢的心情。但是显然,有些人体会不了。这份行业数据,让笔者“柠檬” ... [详细]
author-avatar
桃花救赎
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有