精华内容
下载资源
问答
  • To与For目的”的用法

    千次阅读 2011-12-19 09:54:02
    To+动词eg:check the attachment for details  to do sth  for doing sth的用法在OG里边是unidiomatic的。 参见:http://wenku.baidu.com/view/b08c974d2b160b4e767fcfd6.html 参见:http://forum.cha

    一句话:

    For+名词
    To+动词
    eg:check the attachment for details

             to do sth

             for doing sth的用法在OG里边是unidiomatic的。

    参见:http://wenku.baidu.com/view/b08c974d2b160b4e767fcfd6.html

    参见:http://forum.chasedream.com/GMAT_SC/thread-181642-1-1.html

    展开全文
  • 【数据库学习】数据库总结

    万次阅读 多人点赞 2018-07-26 13:26:41
    自我理解是:中所有的数据元素不但要能唯一地被主键所标识,而且他们之间必须相互独立,不存在其他的函数关系。 ④BCNF(修正第三范式、扩充第三范式 消除主属性对键的传递依赖) 所有非主属性对每一个码都是...

    1,概念

    1)数据库

    数据库是长期存储在计算机内、有组织的、可共享的大量数据的集合。
    数据库中存储的是数据及数据之间的关系。

    正常情况读写文件系统比数据库快一到两个数据级;
    数据库的查询,大量并发的时候可能最浪费时间的是connect和close。
    数据库的优势是体现的大量数据的查询、统计以及并发读写,不是在速度上。

    2)数据库数据特点

    永久存储、有组织、可共享。
    (数据的最小存取单位是数据项)

    3)数据库系统的特点

    ①数据结构化

    ②数据的共享性,冗余度,易扩充

    ③数据独立性高

    数据独立性包括:物理独立性和逻辑独立性
    a)物理独立性(外模式\模式映像):
    用户程序不需要了解,应用程序要处理的只是数据的逻辑结构,这样当数据的物理存储改变了,应用程序不用改变。
    b)逻辑独立性(模式\内模式映像):
    逻辑独立性是指用户的应用程序与数据库的逻辑结构是相互独立的,即,当数据的逻辑结构改变时,用户程序也可以不变。
    逻辑数据独立性(logical data independence)是指概念模式改变,外模式和应用程序不变。在逻辑数据独立性里,数据的逻辑结构发生改变或存储关系的选择发生改变时用户不会受到影响。改变概念模式,例如增加和删除实体、增加和删除属性、增加和删除联系,不需要改变现有的外模式或重写应用程序。在DBMS中只需要修改视图的定义和映像来支持逻辑数据独立性。对用户来说,不再关心所做的修改是非常重要的。换句话说,模式经过逻辑重构之后,根据外模式构建的应用程序还是和从前一样工作。

    4)概念模型(E-R模型)

    ①概念

    概念模型的一种表示方法:实体联系方法,用E-R方法(E-R模型)来描述。
    概念模型是用于信息世界的建模,是一种信息模型,与具体的DBMS无关。且能满足用户对数据的处理要求,易于修改。
    概念模型与具体数据模型无关且容易向数据库模型转化。

    实体:举行表示
    属性:椭圆表示,并用直线与实体连接
    联系:菱形表示,用直线与实体连接,同时在边上标上联系的类型(1:1,1:n,m:n)。
    

    一个联系转化为一个关系模式,与该联系相连的各实体的码以及联系的属性转化为关系的属性,该关系的码则有三种情况:
    若联系为1:1,则每个实体的码均是该关系的后选码。
    若联系为1:n,则关系的码为n端实体的码。
    若联系为m:n,则关系的码为诸实体码的组合。

    数据库模式定义语言DDL(Data Definition Language):是用于描述数据库中要存储的现实世界实体的语言。一个数据库模式包含该数据库中所有实体的描述定义。这些定义包括结构定义、操作方法定义等。

    数据库逻辑设计: 将概念设计所得到的概念模型转换为某一具体的数据模型(层次、网状、关系、面向对象).

    5)关系完整性

    在关系模型中,关系完整性主要是指以下三方面:

    实体完整性

    所谓的实体完整性就是指关系(所谓的关系就是表)的主码不能取空值;
    比如学生表的主码通常是取学号为主码

    参照完整性

    是指参照关系中每个元素的外码要么为空(NULL),要么等于被参照关系中某个元素的主码;
    参照关系也称为外键表,被参照关系也称为主键表。

    用户定义的完整性

    指对关系中每个属性的取值作一个限制(或称为约束)的具体定义。比如 性别属性只能取”男“或”女“,再就是年龄的取值范围,可以取值0-130 ,但不能取负数,因为年龄不可能是负数。

    6)关系数据库规范化

    目地:使结构更合理,消除存储异常,使数据冗余尽量小,便于插入、删除和更新。
    原则:遵从概念单一化“一事一地”原则,即一个关系模式描述一个实体或实体间的一种联系。
    规范的实质:概念的单一化。
    规范化的方法:将关系模式投影分解成两个或两个以上的关系模式。

    2,依赖和范式

    1)依赖

    ①部分函数依赖

    设X,Y是关系R的两个属性集合,存在X→Y,若X’是X的真子集,存在X’→Y,则称Y部分函数依赖于X。

        举个例子:通过AB能得出C,通过A也能得出C,通过B也能得出C,那么说C部分依赖于AB。
    

    ②完全函数依赖

    设X,Y是关系R的两个属性集合,X’是X的真子集,存在X→Y,但对每一个X’都有X’!→Y,则称Y完全函数依赖于X。

        举个例子:通过AB能得出C,但是AB单独得不出C,那么说C完全依赖于AB.
    

    ③传递函数依赖

    设X,Y,Z是关系R中互不相同的属性集合,存在X→Y(Y !→X),Y→Z,则称Z传递函数依赖于X。

        举个例子:通过A得到B,通过B得到C,但是C得不到B,B得不到A,那么成C传递依赖于A
    

    ④多值依赖

    设R(U)是属性集U上的一个关系模式。X,Y,Z是U的子集,并且Z=U-X-Y。关系模式R(U)中多值依赖X→→Y成立,当且仅当对R(U)的任一关系r,给定的一对(x,z)值有一组Y的值,这组值仅仅决定于x值而与z值无关。

    举例:
    有这样一个关系 <仓库管理员,仓库号,库存产品号> ,假设一个产品只能放到一个仓库中,但是一个仓库可以有若干管理员,那么对应于一个 <仓库管理员,库存产品号>有一个仓库号,而实际上,这个仓库号只与库存产品号有关,与管理员无关,就说这是多值依赖。

    2)范式

    各个范式联系:
    5NF⊂4NF⊂BCNF⊂3NF⊂2NF⊂1NF

    ①1NF(满足最低要求的范式:字段不可再分,原子性)

    如果一个关系模式R的所有属性都是不可分的基本数据项,则R∈1NF。
    自我理解1NF就是无重复的列。
    如:(X1,X2)→X3,X2→X3 其中x3对x2部分依赖
    如:(X1,X2)→X3,X2→X4 其中有非主属性X4部分依赖于候选键{X1,X2},所以这个关系模式不为第二范式;又因为范式之间的关系满足1NF⊇2NF⊇3NF ⊇ BCNF,所以是第一范式。

    ②2NF(消除部分子函数依赖:一个表只能说明一个事物)

    若R∈1NF,且每一个非主属性完全函数依赖于码,则R∈2NF。
    即要求数据库表中的每个实例或行必须可以被唯一地区分。

    ③3NF(消除传递依赖,即消除非主属性对键的传递依赖:每列都与主键有直接关系,不存在传递依赖。任何非主属性不依赖于其它非主属性。)

    若R∈3NF,则每一个非主属性既不部分依赖于码,也不传递依赖于码。
    自我理解是:表中所有的数据元素不但要能唯一地被主键所标识,而且他们之间还必须相互独立,不存在其他的函数关系。

    ④BCNF(修正第三范式、扩充第三范式 消除主属性对键的传递依赖)

    所有非主属性对每一个码都是完全函数依赖;
    所有主属性对每一个不包含它的码,也是完全函数依赖;
    没有任何属性完全函数依赖于非码的任何一组属性。

    ⑤4NF

    关系模式R<U,F>∈1NF,如果对于R的每个非平凡多值依赖X->->Y(Y∉X),X都含有码,则称R<U,F>∈4NF

    3,数据库平台

    数据库管理系统(DBMS):是系统软件,是数据库系统的核心。
    常见数据库管理系统有:Access、mysql、sql server

    4,数据库语句

    SQL 语言是非过程化的语言,易学习。
    SQL语言具有两种使用方式:一种是在终端交互方式下使用,称为交互式SQL; 另一种是嵌入在高级语言的程序中使用,称为嵌入式SQL,而这些高级语言可以是C、PASCAL、COBOL等,称为宿主语言。

    1)基本对象

    关系数据库系统支持 三级模式结构,其概念模式、外模式和内模式中的基本对象有表、视图和索引。
    三级模式结构有效地组织、管理数据,提高了数据库的逻辑独立性和物理独立性。使数据库达到了数据独立性。

    ①模式(schema,逻辑模式)

    A.概念

    是数据库中全体数据的逻辑结构和特征的描述,是所有用户的公共数据视图。是数据库系统模式结构的中间层,即不涉及数据的物理存储细节和硬件环境,也与具体的应用程序、开发工具及高级设计语言无关。
    模式是数据库数据在逻辑级上的视图,一个数据库只有一个模式。

    也用于区分一个 大项目中的各个小项目,这样若有相同名字的表的话, 不同模式不会发生冲突。相当于编程时的命名空间。
    如:
    一个公司的系统,分2个子系统,分别为财务系统和人力资源系统.
    这2个子系统, 共用一个数据库。
    那么 财务系统的表, 可以放在财务的模式(schema).
    人力资源系统的表,放在人力资源系统的模式里面。
    这2个子系统,能够互相访问对方的表。
    但是又不因为 表重名 的问题,影响对方。

    B.访问

    访问具体的一个表,可以由 4个部分组成
    分别为 服务器名, 数据库名,模式名,表名。

    对于访问本地的数据库:
    不指定模式名的话, 数据库默认使用dbo模式。
    (DBO是每个数据库的默认用户,具有所有者权限,即DbOwner )
    pg不指定模式的话默认使用public模式。

    C.操作

    --创建
    CREATE SCHEMA schema_name;
    

    ②外模式(子模式,用户模式)

    是数据库用户能够看见和使用的局部数据的逻辑结构和特征的描述,是数据库用户的数据视图,是与某一应用有关的数据的逻辑表示。
    外模式通常是模式的子集,一个数据库可以有多个外模式,但一个应用程序只能有一个外模式。
    外模式是保证数据库安全性的一个有力措施:用户只能访问外模式的数据,其余数据不可见。

    ③内模式(存储模式)

    一个数据库只有一个内模式。
    内模式是数据物理结构和存储方式的描述,是数据在数据库内部的表示方式。

    数据库管理系统在三级模式之间提供了两层映像:
    外模式/模式映像(保证数据的逻辑独立性)
    模式/内模式映像(保证了物理独立性)

    ④表

    表分为临时表和永久表。

    临时表

    临时表存储在tempdb中(如下),当不再使用时会自动删除。

    IF OBJECT_ID('tempdb..#ownerAnnouce') IS NOT NULL
    

    根据进程独立,只有进程的拥有者有表的访问权限,其它用户不能访问该表;
    不同的用户进程,创建的临时表虽然“名字”相同,但是这些表之间相互并不存在任何关系;在SQLSERVER中,通过特别的命名机制保证临时表的进程独立性。

    临时表有两种类型:本地和全局。

    A.本地临时表

    名称以单个数字符号 (#) 打头;它们仅对当前的用户连接是可见的;当用户从 SQL Server 实例断开连接时被删除。

    B.全局临时表

    名称以两个数字符号 (##) 打头,创建后对任何用户都是可见的,当所有引用该表的用户从 SQL Server 断开连接时被删除。

    临时表优点

    真正的临时表利用了数据库临时表空间,由数据库系统自动进行维护,因此节省了表空间。并且由于临时表空间一般利用虚拟内存,大大减少了硬盘的I/O次数,因此也提高了系统效率。

    临时表的创建

    A. create table #临时表名
    B.select * into #临时表名 from 表名(永久表或临时表)

    ⑤视图

    A.概念

    视图是一张虚拟表,视图的字段是自定义的,视图只支持查询,查询数据来源于实体表。

    一般视图是只读的,在pg中通过添加规则可以进行视图的更新。从pg9.1开始,用户可以通过INSTEAD OF的触发器来实现视图更新。

    B.优缺点

    • 优点
      视图可以将多个复杂关联表提取信息,方便查询,但不能优化查询速度(调用视图查询时才进行动态检索数据)。
      即,如果你认为一个sql查询非常慢,为了优化它的速度把它建立成视图,这是不可取的,视图是每次调用的时候生成,并不是数据源变化就刷新数据,并不能提高检索效率。
    • 缺点
      视图就是临时表,即调即用,如果数据源没有任何变化,在反复调用中,临时表会缓存到内存中(SHOW STATUS LIKE ‘Qcache%’;),视图中不能创建索引,但视图可以基于索引生成 。

    C.场景

    1. 重用SQL语句;
    2. 简化复杂SQL操作(生成视图),重用查询且不需要知道基本查询细节。
    3. 保护数据。用户有表的部分权限。
    4. 更改数据格式和表示。视图可返回与底层表不同的表示和格式。

    D.操作

    --创建视图
    CREATE OR REPLACE VIEW view_name(studentName, studentAge)  --(studentName, studentAge) 可以去掉,加上是重命名列名
    AS 
    SELECT user_info.name, user_info.age from user_info;
    
    --删除视图
    DROP VIEW view_name;
    

    ⑥实体视图

    相对于普通的视图来说,实体化视图的不同之处在于实体化视图管理存储数据,占据数据库的物理空间。

    实体化视图的结果会保存在一个普通的数据表中,在对实体化视图进行查询的时候不再会对创建实体化视图的基表进行查询,而是直接查询实体化视图对应的结果表,然后通过定期的刷新机制来更新实体化视图表中的数据。

    demo

    -- 创建物化视图
    CREATE MATERIALIZED VIEW MAX_ID_MVIEW 
    AS
      SELECT PART_ID, MAX(ID)  MAX_ID
      FROM PART_DETAIL GROUP BY PART_ID;
      
    -- 如果刷新时不带CONCURRENTLY则无需创建唯一索引
    CREATE UNIQUE INDEX IDX_MAX_ID ON MAX_ID_MVIEW(PART_ID);
    
    -- 利用watch命令每120s刷新一次物化视图
    REFRESH MATERIALIZED VIEW CONCURRENTLY MAX_ID_MVIEW; \watch 120
    

    作用

    1. 减轻网络负担:通过实体化视图将数据从一个数据库分发到多个不同的数据库上,通过对多个数据库访问来减轻对单个数据库的网络负担。
    2. 搭建分发环境:通过从一个中央数据库将数据分发到多个节点数据库,达到分发数据的目的。
    3. 复制数据子集:实体化视图可以进行行级/列级的筛选,这样可以复制需要的那一部分数据。
    4. 实体化视图是用于汇总,预计算,复制或分发数据的对象, 在大型的数据库中使用它可以提高涉及到的SUM,COUNT,AVG,MIN,MAX等的表的查询的速度。
    5. 物化视图的快速刷新采用了增量的机制,在刷新时,只针对基表上发生变化的数据进行刷新。因此快速刷新是物化视图刷新方式的首选。

    ⑦索引

    为了改变数据库的性能和可访问性所增加的一组辅助性数据。
    详细介绍见下文。

    2)数据结构创建及修改

    1>数据库操作

    --查看数据库
    show databases;
    --建库
    create database children;
    --删库
    drop database children;
    --调用数据库
    use children;
    

    2>表操作

    --pg建表
    CREATE TABLE if not exists public.stu_info(   --创建public模式下的表
        FOREIGN KEY (ID) REFERENCES people_info (ID),  --单个外键,一般情况下不建议增加这种强约束
        id int8 PRIMARY KEY,    --系统会自动为主键创建一个隐含的索引  primary key(Sno,Cno)组合主键
        address VARCHAR (255) UNIQUE NOT NULL,
        birthday TIMESTAMP NOT NULL,  
        age int default 15,  --默认值,影响后续插入值。但对旧数据没有影响。
       CONSTRAINT student2_pkey PRIMARY KEY (id),
       CONSTRAINT ck_age CHECK(age<18), --检查约束,约束某些字段需要满足的要求。NULL被认为满足条件。
       CONSTRAINT uk_tbl_unique_a_b unique(id ,address) --唯一约束。唯一键中可以写入任意多个NULL!即可以存在多组 1,null  
    )
    WITH (
      OIDS=FALSE
    );
    ALTER TABLE myschema.tb_test
      OWNER TO postgres;
    
    --重命名表
    alter table tableName RENAME TO newName;--pg
    

    i>指定默认值

    一般用于数据预置或create_time、update_time的自动录入。各个DBMS获得系统日期如下:

    DBMS函数/变量
    AccessNOW()
    DB2CURRENT_DATE
    MySQLCURRENT_DATE()
    OracleSYSDATE
    PostgreSQLCURRENT_DATE
    SQL ServerGETDATE()
    SQLitedate(‘now’)
    --修改默认值
    alter table tableName alter column age set DEFAULT 15;--pg
    --删除默认值
    alter table tableName alter column age drop DEFAULT 15;--pg
    

    ii>表约束

    表约束有:主键、外键、检查约束、唯一约束、非NULL约束。

    --添加主键(有些DBMS不允许在建表之后修改主键)
    ALTER TABLE tableName ADD PRIMARY KEY(fieldName) ; --fieldName在库中不能有重复数据
    --增加约束
    alter table tableName add check (age<16);--pg 增加检查约束,约束名为:tableName_age_check
    alter table tableName add constraint uk_tbl_unique_a_b unique (a,b);--pg 增加唯一约束
    alter table tableName alter column fieldName set NOT NULL;--pg 增加非空约束
    --删除约束
    alter table tableName drop constraint constraintName;--pg 根据约束名删除检查约束、唯一约束
    alter table tableName alter column fieldName drop NOT NULL;--pg 删除非空约束(非空约束没有约束名)
    

    iii>修改表字段

    --增加列\添加一个字段
    alter table tableName add column columnName varchar(30) default 'a' not null; --column 可加可不加
    --删除列(会连同字段上的约束一并删除)
    alter table tableName drop column columnName; --column 可加可不加
    --修改列名:
    alter table tableName rename column fieldName TO fieldNameNew;--pg、oracle中
    exec sp_rename '[表名].[列名]‘,’[表名].[新列名]'--在sqlserver
    ALTER TABLE 表名 CHANGE 列名 新列名 列类型--mysql
    
    --修改字段类型或长度:
    alter table tableName modify column 字段名 类型;
    alter table tableName alter column fieldName TYPE text;--pg修改字段数据类型。仅在当前数据都可以隐式转换为新类型时才可以执行成功
    --将NAME最大列宽增加到10个字符
    ALTER TABLE CARD ALTER COLUMN NAME varchar(10) 
    
    

    3)数据查询

    数据库处理一个查询的步骤:
    客户端连接->查询缓存->解析器->预处理器->查询优化器->查询执行引擎->数据

    1. 客户端发送一条查询给服务器;
    2. 服务器先会检查查询缓存query cache,如果命中了缓存,则立即返回存储在缓存中的结果。否则进入下一阶段;
    3. 服务器端进行SQL解析parsing、预处理transition,再由优化器optimization生成对应的执行计划;
    4. 根据优化器生成的执行计划,调用存储引擎的API来执行分布distribution查询;
    5. 将结果返回给客户端。
    

    1>简单查询

    select * from student;
    select 1+2; #当表达式与表列无关时,在pg和mysql中不适用“from tableName”
    

    拼接查询:
    Access和 SQL Server使用 + 号。DB2、Oracle、PostgreSQL、SQLite和Open Office Base 使用 ||。

    select label || '_' || id from user_info;  --结果:abc_1
    

    2>条件查询

    功能表达举例备注
    等于=
    不等于<>!=
    空值is null,is not nullselect * from student where class is not null;
    确定集合,ininnot inselect * from student where age not in(21,23);在sql标准中仅支持100个以内的占位符作为查询参数。根据数据库不同,对in的参数和长度有不同的限制,否则会直接报错。
    确定范围between and , not between and
    模糊查询like ,not likeselect * from student where name like '%丽%';’ %代表任意长度(可为0)的字符串;_(下划线):代表任意单个字符。(汉字代表2个字符,所以一个汉字用两个下划线);\为转义字符

    select出的别名是否可以作为where查询条件?不能,因为执行计划中where在selectz之前。如:select label a from asset_field where a = '分类'

    3>排序查询

    非排序查询的数据顺序:pg默认返回数据的顺序是插入表的数据顺序。

    # 单个排序:
    select name,age from student order by age desc; # 默认为asc:升序排列。desc:降序排序。
    
    #多重排序:
    order by 字段5,字段6 asc  //先按字段5排序,再按字段6排序
    

    4>case when then查询

    --简单case函数
    case sex
      when '1' then '男'
      when '2' then '女’
      else '其他' end
    --case搜索函数
    case when sex = '1' then ''
         when sex = '2' then ''
         else '其他' end  
    

    应用:

    select (case sex
    		  when '1' then '男'
    		  when '2' then '女’
    		  else '其他' end)sex from student where class = 11;
    

    5>where、group by、having

    大部分的where都可以背having代替,不同的是where过滤行,而having过滤分组,用在group by之后。(where在分组前过滤,having在分组后过滤)

    select class,avg(age) as age from student 
    group by class 
    having avg(age)>23 /*要求平均年龄大于23*/
    

    where肯定在group by 之前
    where后的条件表达式里不允许使用聚合函数,而having可以。

    6> 函数

    聚合函数

    avg平均数,同min(age)、max(age)、sum(age)

    select avg(age)  as age from student group by class order by age desc; 
    

    count

    select count(class)from student;
    /*数量 因为使用了92标准,所以null不计入count*/
    count(*) 跟count(1) 的结果一样,返回记录的总行数,都包括对NULL 的统计,
    count(column) 是不包括NULL 的统计。
    

    distinct

    select distinct(class)from student;/*去重复,出现所有不同的内容*/
    select count(distinct(class)) from student;
    

    其它

    LEFT(“123456789”,LEN(“数据库”))/*分两步运算,第一步是运算LEN函数,结果是3。第二步针对123456789这个字符从左边开始连续取三个数*/
    
    select top 100 * from student where no=11;/*显示前100行*/
    select isnull(name,'无') as name,age,class from student;/*isnull之后就无列名了 用as给列重命名*/
    select name,age,class,'the name is' + name as introduce from student;/*用加号形成一个自定义列*/
    

    7>SQL-92 规则

    是数据库的一个标准。以下代码 写在存储过程前面,表示遵从SQL-92 规则。
    SQL-92 标准要求在对空值进行等于 (=) 或不等于 (<) 比较时取值为 FALSE。

    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    

    SET ANSI_NULLS ON
    即使 column_name 中包含空值,使用 WHERE column_name = NULL 的 SELECT 语句仍返回零行。
    即使 column_name 中包含非空值,使用 WHERE column_name < NULL 的 SELECT 语句仍会返回零行。

    SET QUOTED_IDENTIFIER ON
    为ON:标识符可以由双引号分隔,而文字必须由单引号分隔。
    为OFF:标识符不可加引号。

    8>多层查询 EXISTS

    如果内层查询语句查询到符合条件的记录,就返回一个真值(true),否则,将返回
    一个假值(false)。

    SELECT * FROM employee
    WHERE EXISTS
    (SELECT d_name FROM department WHERE d_id=1003);
    

    同理还有:NOT EXISTS。

    9>关联查询、联结(JOIN)表

    关系数据库设计中表的设计是把信息分解成多个表,一类数据一个表,各表通过某些共同的值相互关联。
    一般情况下我们不建议建立外键这种强关联的关联信息。

    可伸缩(scale)
    能够适应不断增加的工作量而不失败。关系数据库的可伸缩性远远优于非关系数据库。

    注意:

    1. 联结的表越多效率越低。
    2. SQL本身不限制联结表的数目,但DBMS有最大数目限制。
    3. 一般情况下,联结查询比子查询快,实际应用中应该尝试两种方法看哪种快。
    JSON类型说明备注
    JOIN如果表中有至少一个匹配,则返回行INNER已省略。外联结比内联结返回的行数多(还包括没有关联的行)
    LEFT JOIN即使右表中没有匹配,也从左表返回所有的行OUTER已省略
    RIGHT JOIN即使左表中没有匹配,也从右表返回所有的行OUTER已省略
    FULL JOIN只要其中一个表中存在匹配,就返回行OUTER已省略

    luo_persons表:

    id_plast_namefirst_nameaddresscity

    luo_orders表:

    id_oorder_noid_p

    要求输出:谁订购了产品,并且他们订购了什么产品?

    ①联表查询(等值联结,equijoin)

    SELECT
    	a.last_name, a.first_name, b.order_no
    FROM
    	luo_persons a,
    	luo_orders b 
    WHERE
    	a.id_p = b.id_p	
    

    ②join查询(内联结,inner join, 推荐)

    /*(推荐)等值联结明确指定联结类型可转换为inner join

    SELECT
    	last_name,
    	first_name,
    	order_no 
    FROM
    	luo_persons
    	INNER JOIN luo_orders ON luo_persons.id_p = luo_orders.id_p
    

    ③union查询(复合查询、并查询)

    UNION 操作符用于合并两个或多个 SELECT 语句的结果集。

    注意:

    1. UNION 内部的 SELECT 语句必须拥有相同数量的列、表达式或聚集函数。列也必须拥有相似的数据类型(可以不完全相同,但是可以互相转换)。同时,每条 SELECT 语句中的列的顺序必须相同。
    2. 默认地,UNION 操作符选取不同的值。如果允许重复的值,请使用 UNION ALL。
    3. UNION能组合的最大语句数目限制需要查询具体的DBMS文档。
    	select id_p from luo_persons 
    	union 
    	SELECT id_p from luo_orders
    

    某些DBMS中还支持其它类型的UNION:

    1. EXCEPT(或MINUS):检索在第一个表中存在而在第二个表中不存在的行;
    2. INTERSECT:检索两个表中都存在的行。

    4)数据更新

    ①数据插入

    i> insert

    insert into tableName(no,name) values'1','kate');
    --按表中列的顺序,但如果表结构发生了变化那么对应 sql也要改。不推荐
    insert into product values('001','001','N','N');
    

    有自增长主键(id)的插入:
    i>可以把id的值设置为null或者0,这样mysql会自己做处理
    ii>手动指定需要插入的列,不插入这一个字段的数据!

    ii> insert select

    将select结果插入表中,一般用于可重复执行的sql。
    注:
    1.insert select语句中,如果select返回多行,那么会insert多行数据。

    INSERT INTO "public"."vendors"("vend_name", "vend_id") select 'vend_name1', 1 
    WHERE NOT EXISTS (select 1  FROM "public"."vendors" WHERE vend_id = 1);
    

    iii> select into

    1. SELECT INTO 语句从一个表中选取数据,然后把数据插入另一个表中。
    2. SELECT INTO 语句常用于创建表的备份复件或者用于对记录进行存档。
    3. select into 可以从多个表中检索数据,但只能插入到一个表中。

    函数里面,把一个查询出来的值存入临时变量:

    SELECT LastName,FirstName
    INTO _lName,_fName  FROM Persons
    

    也可以存入临时表中:

    SELECT *
    INTO Persons_backup
    FROM Persons
    

    ②数据修改

    update tableName set name = 'Tom' where name='kate';
    update tableName set age = age + 1;
    

    5)数据删除

    删除表中几行:

    DELETE FROM Person WHERE LastName = 'Wilson' 
    

    删除表中所有行,保留表、不释放空间。所删除的每行记录都会进日志,可以回滚。

    DELETE FROM table_name
    

    删除表:删除内容和定义,释放空间

    drop table user;    
    DROP TABLE IF EXISTS "public"."role_relation"; 可重复执行sql
    

    删除表中所有数据,保留表、同时释放空间(速度比delete快,但是无法撤回,日志里面只记录页释放):

    truncate table book;
    

    truncate是DDL语句(Data Definition,数据定义语句),相当于用重新定义一个新表的方法把原表的内容直接丢弃了,所以执行起来很快。delete语句是DML语句(Data Manipulation,数据操作语句),把数据一条一条的删除,所以删除多行数据执行较慢。

    6)其他注意

    ①加中括号

    列名、表名、存储过程名、函数名等都可以按需要加中括号。防止某些关键字在应用中引起歧义。

    select [select] from 表名;
    

    7)数据库授权

    ①授权GRANT

        GRANT <权限>
        ON <对象类型>  <对象名>
        TO <用户>
        [WITH GRANT OPTION]  // 如果指定了WITH GRANT OPTION子句,则获得某种权限的用户还可以把这种权限再授予其他用户,允许用户传递权限,但是不允许循环授权。
    

    举例:

    例1:把查询Student表的权限授给用户U1
    GRANT SELECT
    ON TABLE Student
    TO U1;
    
    例2:把全部操作权限授予用户U2和U3
    GRANT ALL PRIVILEGES
    ON TABLE Student,Course
    TO U2,U3;
    
    例3:把查询权限授予所有用户
    GRANT SELECT
    ON TABLE SC
    TO PUBLIC;
    

    ③权限的收回 REVOKE

    REVOKE <权限>
    ON <对象类型>  <对象名>
    FROM <用户>
    

    举例:

    例6:收回所有用户对表sc的查询权限
    REVOKE SELECT
    ON TABLE SC
    FROM PUBLIC;
    

    ③对用户模式的授权

    由DBA(数据库管理员,Database Administrator,简称DBA)在创建用户时实现。

    CREATE USER <username>
    [WITH] [DBA|RESOURCE|CONNECT]
    

    只有系统的超级用户才有权创建一个新的数据库用户
    新创建的用户有三种权限:DB,|RESOURCE,CONNECT

    ④数据库角色创建及授权

    CREATE ROLE <角色名>
    

    给角色授权:

    GRANT <权限>
    ON <对象类型>  对象名
    TO <角色>
    

    将一个角色授予其他的角色或用户

    GRANT <角色1>
    TO <角色3>
    [WITH ADMIN OPTION]//如果指定了WITH ADMIN OPTION 子句,则获得某种权限的角色或用户还可以把这种权限再授予其他角色
    

    角色权限的收回

    REVOKE <权限>
    ON <对象类型>  <对象名>
    FROM <角色>
    

    ⑤DENY 拒绝账户访问

    在安全系统中创建一项,以拒绝给当前数据库内的安全帐户授予权限并防止安全帐户通过其组或角色成员资格继承权限。

    DENY { ALL | statement [ ,...n ] }
    TO security_account [ ,...n ]
    

    和授权区别:
    不授权是没有权限,但是如果这个用户属于某个角色,这个角色有了权限,那么这个用户可以从角色继承这个权限。如果选择了deny,即使这个用户属于某个具有权限的角色,他也没有权限。

    8)数据类型

    ①uniqueidentifier

    可存储16字节的二进制值,其作用与全局唯一标记符(GUID)一样。GUID是唯一的二进制数:世界上的任何两台计算机都不会生成重复的GUID值。GUID主要用于在用于多个节点,多台计算机的网络中,分配必须具有唯一性的标识符。

    9)函数

    ①OBJECT_ID

    A. 返回指定对象的对象 ID

    USE master;
    GO
    SELECT OBJECT_ID(N'AdventureWorks.Production.WorkOrder') AS 'Object ID';
    GO
    

    B. 验证对象是否存在

    USE AdventureWorks;
    GO
    IF OBJECT_ID (N'dbo.AWBuildVersion', N'U') IS NOT NULL
    DROP TABLE dbo.AWBuildVersion;
    GO
    

    N是显式的将非unicode字符转成unicode字符,它来自 SQL-92 标准中的 National(Unicode)数据类型,用于扩展和标准化,在这里可以不用,写作object_id(PerPersonData)。

    10)SQL中的借书经典案例

    ①问题描述

    本题用到下面三个关系表:
    CARD 借书卡。 CNO 卡号,NAME 姓名,CLASS 班级
    BOOKS 图书。 BNO 书号,BNAME 书名, AUTHOR 作者,PRICE 单价,QUANTITY 库存册数
    BORROW 借书记录。 CNO 借书卡号,BNO 书号,RDATE 还书日期

    备注:限定每人每种书只能借一本;库存册数随借书、还书而改变。

    要求1. 写出建立BORROW表的SQL语句,要求定义主码完整性约束和引用完整性约束。

    CREATE TABLE BORROW(
        CNO int FOREIGN KEY REFERENCES CARD(CNO),
        BNO int FOREIGN KEY REFERENCES BOOKS(BNO),
        RDATE datetime,
        PRIMARY KEY(CNO,BNO)) 
    

    要求2. 找出借书超过5本的读者,输出借书卡号及所借图书册数。

    SELECT CNO,借图书册数=COUNT(*)
    FROM BORROW
    GROUP BY CNO
    HAVING COUNT(*)>5
    

    要求3. 查询借阅了"水浒"一书的读者,输出姓名及班级

    CARD 借书卡。 CNO 卡号,NAME 姓名,CLASS 班级
    BOOKS 图书。 BNO 书号,BNAME 书名, AUTHOR 作者,PRICE 单价,QUANTITY 库存册数
    BORROW 借书记录。 CNO 借书卡号,BNO 书号,RDATE 还书日期

    SELECT * FROM CARD c
    WHERE EXISTS(
        SELECT * FROM BORROW a,BOOKS b 
        WHERE a.BNO=b.BNO
            AND b.BNAME=N'水浒'
            AND a.CNO=c.CNO) 
    

    要求4. 查询过期未还图书,输出借阅者(卡号)、书号及还书日期。

    SELECT * FROM BORROW 
    WHERE RDATE<GETDATE() 
    

    要求5. 查询书名包括"网络"关键词的图书,输出书号、书名、作者。

    SELECT BNO,BNAME,AUTHOR FROM BOOKS
    WHERE BNAME LIKE N'%网络%' 
    

    N’string’ 表示string是个Unicode字符串

    要求6. 查询现有图书中价格最高的图书,输出书名及作者。

    SELECT BNO,BNAME,AUTHOR FROM BOOKS
    WHERE PRICE=(
        SELECT MAX(PRICE) FROM BOOKS) 
    

    要求7. 查询当前借了"计算方法"但没有借"计算方法习题集"的读者,输出其借书卡号,并按卡号降序排序输出。

    SELECT a.CNO
    FROM BORROW a,BOOKS b
    WHERE a.BNO=b.BNO AND b.BNAME=N'计算方法'
        AND NOT EXISTS(
            SELECT * FROM BORROW aa,BOOKS bb
            WHERE aa.BNO=bb.BNO
                AND bb.BNAME=N'计算方法习题集'
                AND aa.CNO=a.CNO)
    ORDER BY a.CNO DESC 
    

    要求8. 将"C01"班同学所借图书的还期都延长一周。

    UPDATE b SET RDATE=DATEADD(Day,7,b.RDATE)
    FROM CARD a,BORROW b
    WHERE a.CNO=b.CNO
        AND a.CLASS=N'C01' 
    
    DATEADD(datepart,number,date)  
    date 参数是合法的日期表达式。number 是您希望添加的间隔数;对于未来的时间,此数是正数,对于过去的时间,此数是负数。
    

    要求9. 从BOOKS表中删除当前无人借阅的图书记录。

    DELETE FROM BOOKS a
    WHERE NOT EXISTS(
        SELECT * FROM BORROW
        WHERE BNO=a.BNO) 
    

    要求11.在BORROW表上建立一个触发器,完成如下功能:如果读者借阅的书名是"数据库技术及应用",就将该读者的借阅记录保存在BORROW_SAVE表中(注ORROW_SAVE表结构同BORROW表)。

    CREATE TRIGGER TR_SAVE ON BORROW
    FOR INSERT,UPDATE
    AS
    IF @@ROWCOUNT>0
    INSERT BORROW_SAVE SELECT i.*
    FROM INSERTED i,BOOKS b
    WHERE i.BNO=b.BNO
        AND b.BNAME=N'数据库技术及应用' 
    

    要求13.查询当前同时借有"计算方法"和"组合数学"两本书的读者,输出其借书卡号,并按卡号升序排序输出。

    SELECT a.CNO
    FROM BORROW a,BOOKS b
    WHERE a.BNO=b.BNO
        AND b.BNAME IN(N'计算方法',N'组合数学')
    GROUP BY a.CNO
    HAVING COUNT(*)=2
    ORDER BY a.CNO DESC
    

    5,索引

    6,关系运算

    1)集合运算符

    并(∪)、差(-)、交(∩)、笛卡尔积(×)

    笛卡尔积(直积):表示为X × Y,第一个对象是X的成员而第二个对象是Y的所有可能有序对的其中一个成员。
    例如,A={a,b}, B={0,1,2},则
    A×B={(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}
    

    2)专门的关系运算符

    ①选择(限制、σ)

    在关系R中选择满足给定条件的诸元组。

    ②投影(π)

    关系R上的投影是从R中选择出若干属性列组成新的关系。
    这里写图片描述
    投影之后可既改变行,又改变元组的数量。

    ③连接(θ连接、⋈)

    从两个关系的笛卡尔积中选取属性间满足一定条件的元组。(连接由乘积(笛卡尔积)、选择、投影组成)
    分为等值连接(=)、自然连接(要求比较的分量是相同的属性组,并在结果中把重复的属性列去掉)。
    这里写图片描述

    ④除运算(➗)

    RS÷S的意义就是:“在R和S的联系RS中,找出与S中所有的元组有关系的R元组”。

    3)算术比较符

    4)逻辑运算符

    非与或

    7,数据库完整性

    1)实体完整性

    主键唯一且不为空。

    2)参照完整性

    不允许修改外码
    级连操作:当删除或修改被参照表时,同时删除或修改参照表中的不一致元祖。

    3)用户定义的完整性

    4)触发器(Trigger)

    是用户定义在关系表上的一类由事件驱动的特殊过程。一旦定义,任何用户对标的增删改操作均由服务器自动激活相应触发器,在DBMS核心层进行集中的完整性控制。

    8,存储过程(Stored Procedure)

    1)概念

    存储过程是一组为了完成特定功能的SQL 语句集,存储在数据库中,经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。

    2)优点

    ①执行效率高

    存储过程因为SQL 语句已经预编译过了,因此运行的速度比较快。

    ②降低了客户机和服务器之间的通信

    存储过程在服务器端运行,减少客户端的压力。
    减少网络流量,客户端调用存储过程只需要传存储过程名和相关参数即可,与传输SQL 语句相比自然数据量少了很多。

    ③方便实施企业规则(提高了可维护性、安全性)

    可以把企业规则的运算程序写成存储过程放入数据库服务器中,由RDBMS管理,既有利于集中控制,又能够方便地进行维护。
    当用户规则发生变化时,只要修改存储过程,无须修改其他应用程序。

    允许模块化程序设计,就是说只需要创建一次过程,以后在程序中就可以调用该过程任意次,类似方法的复用。
    增强了使用的安全性,充分利用系统管理员可以对执行的某一个存储过程进行权限限制,从而能够实现对某些数据访问的限制,避免非授权用户对数据的访问,保证数据的安全。程序员直接调用存储过程,根本不知道表结构是什么,有什么字段,没有直接暴露表名以及字段名给程序员。

    ④安全性高

    可设定只有某些用户才具有对指定存储过程的使用权。

    3)缺点

    调试麻烦(至少没有像开发程序那样容易),可移植性不灵活(因为存储过程是依赖于具体的数据库)。

    4)场景

    当一个事务涉及到多个SQL语句时或者涉及到对多个表的操作时就要考虑用存储过程;
    当在一个事务的完成需要很复杂的商业逻辑时(比如,对多个数据的操作,对多个状态的判断更改等)要考虑;还有就是比较复杂的统计和汇总也要考虑,但是过多的使用存储过程会降低系统的移植性。

    sql尽量放在存储过程中。
    面对大量数据,用orcle比sql server稳定。

    5)代码

    ①创建

    use test1
    set ansi_nulls on
    go
    set quoted_identifier on
    go
    create procedure procedure_student
    	-- add the parameters for the stored procedure here
    	@gradeid int,
    	@gradename varchar(10) --传入的参数
    as
    begin
    	--计算内容
    end
    go
    

    ②执行

    exec dbo.procedure_student 1,'g'
    

    9,数据库恢复技术

    1)事务

    10,并发控制

    为了保证事务的隔离性和一致性,DBMS需要对并发操作进行正确调度。

    1)并发操作带来的数据不一致性

    ①更新丢失

    ②读“脏”数据

    事务T1修改数据,T2读取数据,T1由于某种原因被撤销,则数据修改回原值,但T2读取的数据是之前修改的数据,即脏数据、不正确的数据。

    ③不可重复读

    事务T1读数据后,T2修改了数据,T1无法再现上一次读取的结果。

    ④幻读

    事务T1读数据后,T2新增或者删除了数据,T1无法再现上一次读取的结果。

    2)并发控制技术

    悲观锁:封锁
    乐观锁:版本号、时间戳

    3)封锁分类(悲观锁)

    ①共享锁(S锁、读锁)

    (读取)操作创建的锁。其他用户可以并发读取数据,但任何事物都不能获取数据上的排它锁,直到已释放所有共享锁。
    若事务T对数据对象A加上S锁,则事务T只能读A;其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。这就保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。

    ②排它锁(X锁、写锁,eXclusive lock)

    若事物T对数据对象A加上X锁,则只允许T读取和修改A,其它任何事务都不能再对A加任何类型的锁,直到T释放A上的锁。它防止任何其它事务获取资源上的锁,直到在事务的末尾将资源上的原始锁释放为止。

    ③更新锁(U锁)

    用来预定要对此页施加X锁,它允许其他事务读,但不允许再施加U锁或X锁;当被读取的页将要被更新时,则升级为X锁;U锁一直到事务结束时才能被释放。

    4)封锁问题

    ①活锁

    i>饥饿

    考虑一台打印机分配的例子,当有多个进程需要打印文件时,系统按照短文件优先的策略排序,该策略具有平均等待时间短的优点,似乎非常合理,但当短文件打印任务源源不断时,长文件的打印任务将被无限期地推迟,导致饥饿以至饿死。

    ii>活锁概念

    与饥饿相关的另外一个概念称为活锁,在忙式等待条件下发生的饥饿,称为活锁。

    a)忙式等待:不进入等待状态的等待。
    b)阻塞式等待:进程得不到共享资源时将进入阻塞状态,让出CPU 给其他进程使用。
    c)忙等待和阻塞式等待的相同之处:
    在于进程都不具备继续向前推进的条件,不同之处在于处于忙等待的进程不主动放弃CPU,尽管CPU 可能被剥夺,因而是低效的;而处于阻塞状态的进程主动放弃CPU ,因而是高效的。

    iii>举例

    事务T1请求封锁R,T2请求封锁R,T3请求封锁R……
    T1释放R之后,系统批准了T3的请求,然后是T4……请求,T2可能永远等待下去。(在整个过程中,事务T2 在不断的重复尝试获取锁R)。

    iv>与死锁区别

    活锁的时候,进程是不会阻塞的,这会导致耗尽CPU 资源,这是与死锁最明显的区别。
    处于活锁的实体是在不断的改变状态,所谓的“活”, 而处于死锁的实体表现为等待;活锁有一定几率解开,而死锁是无法解开的。

    v>避免方式

    采用先来先服务策略。

    ②死锁

    i>概念

    是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去,此时称系统处于死锁状态或系统产生了死锁。

    ii>举例

    T1请求封锁R1,T2请求封锁R2,然后T1又请求封锁R2,T1一直等待T2释放R2,此时,T2请求封锁R1,T2将一直等待T1释放R1。

    iii>死锁原因

    在数据库中,产生死锁的原因主要是:
    两个或多个事务都已封锁了一些数据对象,然后又都请求其他事务已封锁的数据对象,从而出现死等待。

    产生死锁的四个必要条件:
    (1) 互斥条件:一个资源每次只能被一个进程使用。
    (2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
    (3) 不可剥夺条件: 进程已获得的资源,在末使用完之前,不能强行剥夺。
    (4) 环路等待条件: 若干进程之间形成一种头尾相接的循环等待资源关系。
    只要系统发生了死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死
    锁。

    iv>死锁预防

    预防死锁的发生只需破坏死锁产生的四个必要条件之一即可。

    1. 破坏互斥条件
      如果允许系统资源都能共享使用,则系统不会进入死锁状态。但有些资源根本不能同时访问,如打印机等临界资源只能互斥使用。所以,破坏互斥条件而预防死锁的方法不太可行,而且在有的场合应该保护这种互斥性。
    2. 破坏不剥夺条件
      当一个已保持了某些不可剥夺资源的进程,请求新的资源而得不到满足时,它必须释放已经保持的所有资源,待以后需要时再重新申请。这意味着,一个进程已占有的资源会被暂时释放,或者说是被剥夺了,或从而破坏了不可剥夺条件。
      该策略实现起来比较复杂,释放已获得的资源可能造成前一阶段工作的失效,反复地申请和释放资源会增加系统开销,降低系统吞吐量。这种方法常用于状态易于保存和恢复的资源,如CPU 的寄存器及内存资源,一般不能用于打印机之类的资源。
    3. 破坏请求和保持条件
      釆用预先静态分配方法,即进程在运行前一次申请完它所需要的全部资源,在它的资源未满足前,不把它投入运行。一旦投入运行后,这些资源就一直归它所有,也不再提出其他资源请求,这样就可以保证系统不会发生死锁。
      这种方式实现简单,但缺点也显而易见,系统资源被严重浪费,其中有些资源可能仅在运行初期或运行快结束时才使用,甚至根本不使用。而且还会导致“饥饿”现象,当由于个别资源长期被其他进程占用时,将致使等待该资源的进程迟迟不能开始运行。
    4. 破坏环路等待条件
      为了破坏循环等待条件,可釆用顺序资源分配法。首先给系统中的资源编号,规定每个进程,必须按编号递增的顺序请求资源,同类资源一次申请完。也就是说,只要进程提出申请分配资源Ri,则该进程在以后的资源申请中,只能申请编号大于Ri 的资源。
      这种方法存在的问题是,编号必须相对稳定,这就限制了新类型设备的增加;尽管在为资源编号时已考虑到大多数作业实际使用这些资源的顺序,但也经常会发生作业使甩资源的顺序与系统规定顺序不同的情况,造成资源的浪费;此外,这种按规定次序申请资源的方法,也必然会给用户的编程带来麻烦。

    都不好用,一般采用死锁的诊断和解除。

    v>死锁的诊断和解除

    a)超时法
    如果一个事务等待时间超时,则认为发生死锁。(可能误判)
    b)事务等待图法
    事务等待图是一个有向图,反映了事务的等待情况。如果图中出现回路,就表示出现了死锁。

    处理方案是:选择一个处理代价最小的事务,将其撤销并释放所有锁。
    a) 从死锁进程处剥夺资源
    b) 终止部分或全部进程

    5) 两段锁协议(Two-Phase Locking――2PL)

    两段锁协议规定所有的事务应遵守的规则:
    ① 在对任何数据进行读、写操作之前,首先要申请并获得对该数据的封锁。
    ② 在释放一个封锁之后,事务不再申请和获得其它任何封锁。
    即事务的执行分为两个阶段:
    第一阶段是获得封锁的阶段,称为扩展阶段。
    第二阶段是释放封锁的阶段,称为收缩阶段。

    定理:若所有事务均遵守两段锁协议,则这些事务的所有交叉调度都是可串行化的。
    对于遵守两段协议的事务,其交叉并发操作的执行结果一定是正确的。值得注意的是,上述定理是充分条件,不是必要条件。一个可串行化的并发调度的所有事务并不一定都符合两段锁协议,存在不全是2PL的事务的可串行化的并发调度。
    同时我们必须指出,遵循两段锁协议的事务有可能发生死锁。

    此时事务T1 、T2同时处于扩展阶段,两个事务都坚持请求加锁对方已经占有的数据,导致死锁。
    为此,又有了一次封锁法。一次封锁法要求事务必须一次性将所有要使用的数据全部加锁,否则就不能继续执行。因此,一次封锁法遵守两段锁协议,但两段锁并不要求事务必须一次性将所有要使用的数据全部加锁,这一点与一次性封锁不同,这就是遵守两段锁协议仍可能发生死锁的原因所在。

    11,常见图

    DFD 数据流图(Data Flow Diagram):
    这里写图片描述
    ER图 实体-联系图(Entity-Relationship Diagram)
    这里写图片描述

    12,数据库连接:JDBC与JdbcTemplate

    13,数据库安全

    1)SQL注入

    ①概念

    在SQL 语句在拼接的情况下,用户输入为一部分sql语句。

    ②解决方法

    i> 对特殊字符进行过滤、转义或者使用预编译的sql 语句绑定变量

    SQL执行时,2种方式:
    ①字符串处理(拼接),然后执行SQL
    用户输入的时候,可以通过输入sql语句来进行SQL注入。
    ②传参,执行SQL -->交给SQL引擎**(推荐)**
    用prepareStatement,参数用set 方法进行填装。

    String sql= "insert into userlogin values(?,?)";
    PreparedStatement ps=conn.prepareStatement(sql);
    for(int i=1;i<100;i++){
    ps.setInt(1, i);
    ps.setInt(2, 8888);
    ps.executeUpdate();
    ps.close();
    conn.close();
    

    ii> 当sql 语句运行出错时,不要把数据库返回的错误信息全部显示给用户,以防止泄漏服务器和数据库相关信息

    iii>检查变量的数据类型和格式

    只要是有固定格式的变量,在SQL 语句执行前,应该严格按照固定格式去检查,确保变量是我们预想的格式,这样很大程度上可以避免SQL 注入攻击。
    例如:对于where id={$id}这种形式,数据库里所有的id 都是数字,那么就应该在SQL 被执行前,检查确保变量id 是int 类型。

    iv>所有的SQL 语句都封装在存储过程中

    所有的SQL 语句都封装在存储过程中,这样不但可以避免SQL 注入,还能提高一些性能。

    14,分布式数据库

    1)概念

    分布式数据库是一个物理上分散的而逻辑上集中的数据集。
    它有三大特点: 数据分布性 逻辑关联性 站点自治性

    2)五个基本原则

    ①资源的重复性
    指分布式系统中硬件,软件以及数据的冗余配置。
    ②物理上的分布性
    从硬件,软件以及数据上看都是相互独立地分布。
    ③高层操作系统(或者分布式操作系统)
    高层操作系统负责对分布性的资源进行统一的控制,它使一个简单的硬件堆积转变为一个统一协调的工作系统。
    ④系统的透明性
    透明性是分布式系统的灵魂,实现不同层次的透明性是分布式系统必须解决的关键问题之一。
    ⑤协作的自治性
    每一节点都是一个完整的处理系统,同时又是合作的。 简而言之:分布式系统是一个多节点的,处理或数据分布的,在统一下提高综合处理能力的协作体。

    3)待解决问题

    不完整系统状态信息
    时间延迟
    通信的代价
    负载均衡

    4)分类(从控制方式角度)

    ①紧耦合式DDBMS

    全局控制信息放在一个称为中心站点的站点上。所有的全局访问都必须通过中心站点来确定远程数据片的位置。
    优点:容易实现数据的一致性和完整性。
    缺点:易产生访问瓶颈,系统效率不高,可靠性较差。

    ②联邦式DDBMS

    每个站点都包含全局控制信息的一个副本,都可以接受全局访问。任何对远程数据的请求,都可以通过广播方式传播到其他节点。
    优点:具有较好的可靠性和可用性,并行性好,更容易适应旧有的系统集成和异构分布式数据库系统的建立。
    缺点:保持数据的一致性很困难,实现难度大。

    ③组合式DDBMS

    是上述方案的折衷,它把站点分为两类,一类具有全局控制信息,称为主节点,可以接受全局任务,另一类没有全局信息,只能为主节点提供数据服务。
    优点:灵活性较好,易于实现层次控制结构。
    缺点:设计复杂。

    5)分布透明性

    即在分布式数据库系统中用户不必关心数据的分布情况。分为三个层次:

    ①分片透明性

    它是分布式数据库系统的最高透明性层次,它向用户完全屏蔽了DDB的分片信息。这样的透明性保持了高水平的数据独立性。

    ②位置透明性

    用户的应用程序不需要关心数据分片的具体存储站点,当数据库的数据片的存储站点发生改变时,只需改变对应的GRS/NRS映射就可以保持全局表示模式不发生改变

    ③数据模型透明性

    它向用户屏蔽的只是本站点的具体数据库存储及其管理情况。 在异构的情况下,这种透明性避免了用户对不同数据模型的转换的实现。
    本地透明性是3种透明方式中最低的。

    6)数据分割方法

    ①水平分割

    把全局关系的元组分割成一些子集,这些子集被称为数据分片或段(Fragment)。
    水平分割可以通过关系运算“选择”来定义。

    水平分片是对全局关系执行“选择”操作,把具有相同性质的元组进行分组,构成若干个不相交的子集.水平分片的方法可归为初级分片和导出分片两类。

    ②垂直分割

    把全局关系按照属性组(纵向)分隔成一些数据分片或段。
    垂直分割可以通过关系运算“投影”来定义。

    ③混合分割

    可把水平分割和垂直分割这两种方法结合起来使用,产生混合式数据分片。

    ④数据分片应遵循的原则

    若R={R1,R2,…,Rn}满足:
    1)完整性(completeness)条件:
    如果分片 a∈R,则必有a∈Ri,i=l,2,…,n
    2)可重构(reconstructed)条件:
    R=∪ Ri,(水平分片)或R=∞Ri,(垂直分片)
    3)不相交(disjoint)条件:
    Ri∩ Rj=φ,i≠j,I,j:=1,2,…,,n(水平 分片)
    Ri∩Rj=主键属性,I,j=1,2,…,n(垂直分片)

    7)分布式数据库和集中式区别

    分布式(distributed)是指在多台不同的服务器中部署不同的服务模块,通过远程调用协同工作,对外提供服务。
    集群(cluster)是指在多台不同的服务器中部署相同应用或服务模块,构成一个集群,通过负载均衡设备对外提供服务。

    15,数据库优化

    1)优化SQL 语句

    ①explain

    通过explain(查询优化神器)用来查看SQL 语句的执行效果,可以帮助选择更好的索引和优化查询语句,写出更好的优化语句。
    通常我们可以对比较复杂的尤其是涉及到多表的SELECT 语句,把关键字EXPLAIN 加到前面,查看执行计划。例如:explain select * from news;

    explain语法:

    explain select … from … [where ...] 
    

    ② 用具体的字段列表代替“*

    任何地方都不要使用select * from t ,不要返回用不到的任何字段。

    ③ 不在索引列做运算或者使用函数

    ④ 查询尽可能使用limit 减少返回的行数,减少数据传输时间和带宽浪费。

    2)优化表的数据类型

    ① 使用procedure analyse()函数对表进行分析

    该函数可以对表中列的数据类型提出优化建议。能小就用小。表数据类型第一个原则是:使用能正确的表示和存储数据的最短类型。这样可以减少对磁盘空间、内存、cpu 缓存的使用。
    使用方法:select * from 表名procedure analyse();

    ② 对表进行拆分

    通过拆分表可以提高表的访问效率。有2 种拆分方法:
    1.垂直拆分
    把主键和一些列放在一个表中,然后把主键和另外的列放在另一个表中。如果一个表中某些列常用,而另外一些不常用,则可以采用垂直拆分。
    2.水平拆分
    根据一列或者多列数据的值把数据行放到二个独立的表中。

    ③ 使用中间表来提高查询速度

    创建中间表,表结构和源表结构完全相同,转移要统计的数据到中间表,然后在中间表上进行统计,得出想要的结果。

    3)硬件优化

    ①CPU 的优化

    选择多核和主频高的CPU。

    ②内存的优化

    使用更大的内存。将尽量多的内存分配给MYSQL 做缓存。

    ③磁盘I/O 的优化

    i>使用磁盘阵列

    RAID 0 没有数据冗余,没有数据校验的磁盘陈列。实现RAID 0至少需要两块以上的硬盘,它将两块以上的硬盘合并成一块,数据连续地分割在每块盘上。
    RAID1 是将一个两块硬盘所构成RAID 磁盘阵列,其容量仅等于一块硬盘的容量,因为另一块只是当作数据“镜像”。
    使用RAID-0+1 磁盘阵列。RAID 0+1 是RAID 0 和RAID 1 的组合形式。它在提供与RAID 1 一样的数据安全保障的同时,也提供了与RAID 0 近似的存储性能。

    ii>调整磁盘调度算法

    选择合适的磁盘调度算法,可以减少磁盘的寻道时间。

    4)MySQL 自身的优化

    对MySQL 自身的优化主要是对其配置文件my.cnf 中的各项参数进行优化调整。如指定MySQL 查询缓冲区的大小,指定MySQL 允许的最大连接进程数等。

    5)应用优化

    ①使用数据库连接池

    ②使用查询缓存

    它的作用是存储select 查询的文本及其相应结果。如果随后收到一个相同的查询,服务器会从查询缓存中直接得到查询结果。查询缓存适用的对象是更新不频繁的表,当表中数据更改后,查询缓存中的相关条目就会被清空。

    6)大访问量的优化

    ①使用优化查询的方法

    (见上面)

    ②主从复制,读写分离

    i>主从复制(master,slave):

    通过配置两台(或多台)数据库的主从关系,可以将一台数据库服务器的数据更新同步到另一台服务器上。网站可以利用数据库的这一功能,实现数据库的读写分离,从而改善数据库的负载压力。一个系统的读操作远远多于写操作,因此写操作发向master,读操作发向slaves 进行操作(简单的轮循算法来决定使用哪个slave)。
    利用数据库的读写分离,Web 服务器在写数据的时候,访问主数据库(Master),主数据库通过主从复制机制将数据更新同步到从数据库(Slave),这样当Web 服务器读数据的时候,就可以通过从数据库获得数据。这一方案使得在大量读操作的Web 应用可以轻松地读取数据,而主数据库也只会承受少量的写入操作,还可以实现数据热备份,可谓是一举两得的方案。
    这里写图片描述

    负载均衡(Load Balance,简称LB)

    7)数据库分表、分区、分库

    分表见上面描述。
    分区就是把一张表的数据分成多个区块,这些区块可以在一个磁盘上,也可以在不同的磁盘上,分区后,表面上还是一张表,但数据散列在多个位置,这样一来,多块硬盘同时处理不同的请求,从而提高磁盘I/O 读写性能,实现比较简单。包括水平分区和垂直分区。
    分库是根据业务不同把相关的表切分到不同的数据库中,比如web、bbs、blog 等库。

    17,应用

    1)服务器与服务器之间传输文件夹下的文件,一个文件夹下有10 个文件,另一个文件夹下有100 个文件,两个文件夹大小相等,问,哪个传输更快?

    10 个文件更快。
    1)建立连接数更少,建立连接的开销比传输文件的开销大。
    2)文件写入磁盘,要计算文件的起始位置,文件数目少的话,这个开销就小了

    展开全文
  • MPC模型预测控制

    万次阅读 多人点赞 2018-12-17 17:02:00
    可以把约束显式表示在一个在线求解的二次规划或非线性规划问题中.  模型预测控制具有控制效果好、鲁棒性强等优点,可有效地克服过程的不确定性、非线性和并联性,并能方便的处理过程被控变量和操纵变量中的各种...

    这篇主要讲一下模型预测控制,如果对PID控制了解的同学,那效果更好。如果不了解PID控制,还是熟悉下比较好。

    模型预测控制,顾名思义,基于模型,预测未来,进行控制。这个控制是基于模型的,也就是model-based。

    有人会问,我这个系统的模型怎么来呢?我想到两点解决方法:

    1. 文献上去找别人已经建好的,公认的模型;

    2. 首先进行系统辨识,再进行建模。(难度太大,不建议)

    下面给上经典的MPC控制流程图:

    模型预测控制是一种基于模型的闭环优化控制策略。

    预测控制算法的三要素:内部(预测)模型、参考轨迹、控制算法。现在一般则更清楚地表述为内部(预测)模型、滚动优化、反馈控制。 
    大量的预测控制权威性文献都无一例外地指出, 预测控制最大的吸引力在于它具有显式处理约束的能力, 这种能力来自其基于模型对系统未来动态行为的预测, 通过把约束加到未来的输入、输出或状态变量上, 可以把约束显式表示在一个在线求解的二次规划或非线性规划问题中. 
    模型预测控制具有控制效果好、鲁棒性强等优点,可有效地克服过程的不确定性、非线性和并联性,并能方便的处理过程被控变量和操纵变量中的各种约束。[1]

    在线性模型预测控制(Linear Model Predictive Control, LMPC)的基础上,发展了非线性模型预测控制(Non-linear Model Predictive Control, NMPC),显示模型预测控制(Explicit Model Predictive Control, EMPC)和 鲁棒模型预测控制(Robust Model Predictive Control)

    首先,我们定义一个模型来描述我们的车辆。[2]

    这是自行车模型,运动学上面经常使用。

    (x, y)是车辆的质心,ψ是当前车身的角度,v是当前车辆的速度,lf是当前车辆质心到原点的距离, β是速度和车身的角度。在我们的例子中,我们假设β为零,也就是没有侧滑。

    在我们的模型中,我们可以通过控制前轮的转角δf 以及车辆的加速度a来控制车辆轨迹。简单起见,我们只考虑前轮驱动的车辆,并且将δf记作δ。

      模型预测控制的细节

    每个控制周期,我们都从传感器读取数据并得到车辆状态量:

    • 车辆的位置(x,y)

    • 速度v

    • 车身角度 ψ

    • 转向角(舵角) δ

    • 加速度a

    轨迹模型:

    我们的道路检测系统应该能够为我们规划好路线,比如,以接下来6个航点的坐标的形式。在我们的例子中,我们使用6个航点去逼近一个3阶多项式函数。我们用这个模型去计算y坐标和相对于x轴的车身角度ψ。

    使用模型预测控制和PID实现自动驾驶的车道保持

    轨迹模型一般有规划模块给出,在这里就不做深入的研究。

    动态模型:

    接下来,我们要创建动态模型利用t时刻的状态去预测在t+1拍时刻的车辆状态。利用动力学模型,我们可以轻易地从最新时刻地采样推导出下一时刻的位置,车身角度和速度。

    使用模型预测控制和PID实现自动驾驶的车道保持

    我们可以在添加另外2个状态去衡量轨迹跟踪误差和车身角度误差ψ:

    使用模型预测控制和PID实现自动驾驶的车道保持

    损失函数:

    在模型预测控制中,我们需要定义损失函数来优化路径。如果模型不能保持目标速度,那么我们就要惩罚模型。如果可能的话,我们并不想要突然的加减速或者突然的转向。但是既然这些实际上是不可避免的,我们可以尽可能地抑制加减速和转向地变化率。这减轻了晕车同时更加省油(也省人民币)。模型的损失函数应当包含

    • 跟踪误差

    • 转向误差

    • 速度损失函数项(尽量保持在100英里每小时)

    • 转向损失函数项(尽量避免转向)

    • 加速度损失函数项(尽量保持0加速度)

    • 转向变化率(越小越好)

    • 加速度变化率(越小越好)

    因为这些目标也许会相互冲突,我们需要给这些损失项定义权重以体现优先级。损失函数如下:

    使用模型预测控制和PID实现自动驾驶的车道保持

    总而言之:

    我们需要用模型预测控制来寻找最优路径,那么就需要动力学模型来预测下一拍的状态,以下是动力学模型和系统约束:

    使用模型预测控制和PID实现自动驾驶的车道保持

    这是下面GitHub链接里,别人给的权重。

        const int cte_cost_weight = 2000;
        const int epsi_cost_weight = 2000;
        const int v_cost_weight = 1;
        const int delta_cost_weight = 10;
        const int a_cost_weight = 10;
        const int delta_change_cost_weight = 100;
        const int a_change_cost_weight = 10;

     

    优化模型预测控制

    我们通过解决一个约束条件下优化损失函数的问题来解决了控制问题。这些约束条件包括油门和转向的控制。

    1. 从道路中检测下6个航点,并且计算3次插值的来建立行驶轨迹

    2. 从传感器读取当前速度v,  方向ψ,  转向角 δ 以及加速度  a

    3. 使用传感器读取的数据和动力学模型计算出第一个车辆状态

    4. 根据1秒内的车辆状态响应优化控制动作,控制的周期为100ms,所以1s内有10个周期

    5. 模型预测控制的两个变量(也是控制量):加速度(油门对应正加速度,刹车对应负加速度)和转向角

    6. 给出加速度和转向角的约束范围

    7. 我们将动态模型计算9次,得到未来9个时间拍的系统状态

    8. 给出每个采样计算周期的损失函数

    9. 用1个优化器解算出在约束定义下周期1到周期9的最小总损失(注意,在我们的定义中,时间周期并不从0开始,而是从1开始到10)

    10. 我们仅仅选择周期1给出的控制量

    11. 但是,我们延时100ms后再将控制量给模拟器。这样能够模拟现实世界,毕竟处理计算(读取传感器)和执行都需要时间。

    12. 从步骤1开始重复,寻找下一个最优控制量。

     

    可调性:

    在我们的例子中,我们计算了1秒中内的最优解,这个参数是可以调节的。长时间窗口的优化会给控制器的动作漂亮的曲线,但是也会积累过多的误差。实际上,如果这个优化时间窗口太大,汽车反而会脱离期望轨迹。

    上面的文章内容都来自于链接[2]中,但是很多人对MPC还是有点不明白。模型也建立好了,约束我也会给,那怎么求解呢?求的解怎么利用呢?

    现在我们看第一个问题:

    1. 如何求解

    上面的文章其实来自于Udacity的自动驾驶的一个课程。

    大家可以去GitHub上下载下来,自己跑一下上面的代码。链接是这个https://github.com/mvirgo/MPC-Project,里面是一位博主写好的代码。大家配置好环境后可以直接跑起来的,然后有个可视化软件,可以看到3D引擎看到动画。

    比如像这样的:https://github.com/mvirgo/MPC-Project/blob/master/MPC_vid.mov

    这个代码尽量在Ubuntu上去跑,因为装的东西比较多,给的教程关于LInux的。教程还是看Udacity给的模板比较好,但是代码不要下这个网址的,当时我环境配置好了之后还是有报错,我还以为是我环境配置的有问题。https://github.com/udacity/CarND-MPC-Project

    这个代码是C++写的。

    主函数中的调用

     /*
              * Calculate steering angle and throttle using MPC.
              * Both are in between [-1, 1].
              * Simulator has 100ms latency, so will predict state at that point in time.
              * This will help the car react to where it is actually at by the point of actuation.
              */
              
              // Fits a 3rd-order polynomial to the above x and y coordinates
              auto coeffs = polyfit(ptsx_car, ptsy_car, 3);
              
              // Calculates the cross track error
              // Because points were transformed to vehicle coordinates, x & y equal 0 below.
              // 'y' would otherwise be subtracted from the polyeval value
              double cte = polyeval(coeffs, 0);
              
              // Calculate the orientation error
              // Derivative of the polyfit goes in atan() below
              // Because x = 0 in the vehicle coordinates, the higher orders are zero
              // Leaves only coeffs[1]
              double epsi = -atan(coeffs[1]);
              
              // Center of gravity needed related to psi and epsi
              const double Lf = 2.67;
              
              // Latency for predicting time at actuation
              const double dt = 0.1;
              
              // Predict state after latency
              // x, y and psi are all zero after transformation above
              double pred_px = 0.0 + v * dt; // Since psi is zero, cos(0) = 1, can leave out
              const double pred_py = 0.0; // Since sin(0) = 0, y stays as 0 (y + v * 0 * dt)
              double pred_psi = 0.0 + v * -delta / Lf * dt;
              double pred_v = v + a * dt;
              double pred_cte = cte + v * sin(epsi) * dt;
              double pred_epsi = epsi + v * -delta / Lf * dt;
              
              // Feed in the predicted state values
              Eigen::VectorXd state(6);
              state << pred_px, pred_py, pred_psi, pred_v, pred_cte, pred_epsi;
              
              // Solve for new actuations (and to show predicted x and y in the future)
              auto vars = mpc.Solve(state, coeffs);
              
              // Calculate steering and throttle
              // Steering must be divided by deg2rad(25) to normalize within [-1, 1].
              // Multiplying by Lf takes into account vehicle's turning ability
              double steer_value = vars[0] / (deg2rad(25) * Lf);
              double throttle_value = vars[1];

    MPC函数的实现

    // MPC class definition implementation.
    //
    MPC::MPC() {}
    MPC::~MPC() {}
    
    vector<double> MPC::Solve(Eigen::VectorXd state, Eigen::VectorXd coeffs) {
      bool ok = true;
      typedef CPPAD_TESTVECTOR(double) Dvector;
      
      // State vector holds all current values neede for vars below
      double x = state[0];
      double y = state[1];
      double psi = state[2];
      double v = state[3];
      double cte = state[4];
      double epsi = state[5];
    
      // Setting the number of model variables (includes both states and inputs).
      // N * state vector size + (N - 1) * 2 actuators (For steering & acceleration)
      size_t n_vars = N * 6 + (N - 1) * 2;
      // Setting the number of constraints
      size_t n_constraints = N * 6;
    
      // Initial value of the independent variables.
      // SHOULD BE 0 besides initial state.
      Dvector vars(n_vars);
      for (int i = 0; i < n_vars; i++) {
        vars[i] = 0.0;
      }
    
      Dvector vars_lowerbound(n_vars);
      Dvector vars_upperbound(n_vars);
      // Sets lower and upper limits for variables.
      // Set all non-actuators upper and lowerlimits
      // to the max negative and positive values.
      for (int i = 0; i < delta_start; i++) {
        vars_lowerbound[i] = -1.0e19;
        vars_upperbound[i] = 1.0e19;
      }
      
      // The upper and lower limits of delta are set to -25 and 25
      // degrees (values in radians).
      for (int i = delta_start; i < a_start; i++) {
        vars_lowerbound[i] = -0.436332;
        vars_upperbound[i] = 0.436332;
      }
      
      // Acceleration/decceleration upper and lower limits.
      for (int i = a_start; i < n_vars; i++) {
        vars_lowerbound[i] = -1.0;
        vars_upperbound[i] = 1.0;
      }
    
      // Lower and upper limits for the constraints
      // Should be 0 besides initial state.
      Dvector constraints_lowerbound(n_constraints);
      Dvector constraints_upperbound(n_constraints);
      for (int i = 0; i < n_constraints; i++) {
        constraints_lowerbound[i] = 0;
        constraints_upperbound[i] = 0;
      }
      
      // Start lower and upper limits at current values
      constraints_lowerbound[x_start] = x;
      constraints_lowerbound[y_start] = y;
      constraints_lowerbound[psi_start] = psi;
      constraints_lowerbound[v_start] = v;
      constraints_lowerbound[cte_start] = cte;
      constraints_lowerbound[epsi_start] = epsi;
      
      constraints_upperbound[x_start] = x;
      constraints_upperbound[y_start] = y;
      constraints_upperbound[psi_start] = psi;
      constraints_upperbound[v_start] = v;
      constraints_upperbound[cte_start] = cte;
      constraints_upperbound[epsi_start] = epsi;
    
      // object that computes objective and constraints
      FG_eval fg_eval(coeffs);
    
      //
      // NOTE: You don't have to worry about these options
      //
      // options for IPOPT solver
      std::string options;
      // Uncomment this if you'd like more print information
      options += "Integer print_level  0\n";
      // NOTE: Setting sparse to true allows the solver to take advantage
      // of sparse routines, this makes the computation MUCH FASTER. If you
      // can uncomment 1 of these and see if it makes a difference or not but
      // if you uncomment both the computation time should go up in orders of
      // magnitude.
      options += "Sparse  true        forward\n";
      options += "Sparse  true        reverse\n";
      // NOTE: Currently the solver has a maximum time limit of 0.5 seconds.
      // Change this as you see fit.
      options += "Numeric max_cpu_time          0.5\n";
    
      // place to return solution
      CppAD::ipopt::solve_result<Dvector> solution;
    
      // solve the problem
      CppAD::ipopt::solve<Dvector, FG_eval>(
          options, vars, vars_lowerbound, vars_upperbound, constraints_lowerbound,
          constraints_upperbound, fg_eval, solution);
    
      // Check some of the solution values
      ok &= solution.status == CppAD::ipopt::solve_result<Dvector>::success;
    
      // Cost
      auto cost = solution.obj_value;
      std::cout << "Cost " << cost << std::endl;
    
      // Return the first actuator values, along with predicted x and y values to plot in the simulator.
      vector<double> solved;
      solved.push_back(solution.x[delta_start]);
      solved.push_back(solution.x[a_start]);
      for (int i = 0; i < N; ++i) {
        solved.push_back(solution.x[x_start + i]);
        solved.push_back(solution.x[y_start + i]);
      }
      
      return solved;
    
    }

     具体源码大家还是去直接下载代码看看看。跑下看看效果。然后可以改下预测步长N和采样周期t。这里给的N=10,t=0.1s。

    大家有什么问题,我们可以一起交流下,相互促进,共同进步。我C++一般,是硬伤,Linux也是用了没多久,就为了跑这个工程。

    如何求解的问题已经解决。

    2. 如何利用

    如何利用比求解简单多了啊,看代码:

    // Send values to the simulator
              json msgJson;
              msgJson["steering_angle"] = steer_value;
              msgJson["throttle"] = throttle_value;
    
              // Display the MPC predicted trajectory
              vector<double> mpc_x_vals = {state[0]};
              vector<double> mpc_y_vals = {state[1]};
    
              // add (x,y) points to list here, points are in reference to the vehicle's coordinate system
              // the points in the simulator are connected by a Green line
              
              for (int i = 2; i < vars.size(); i+=2) {
                mpc_x_vals.push_back(vars[i]);
                mpc_y_vals.push_back(vars[i+1]);
              }
    
              msgJson["mpc_x"] = mpc_x_vals;
              msgJson["mpc_y"] = mpc_y_vals;
    
              // Display the waypoints/reference line
              vector<double> next_x_vals;
              vector<double> next_y_vals;
    
              // add (x,y) points to list here, points are in reference to the vehicle's coordinate system
              // the points in the simulator are connected by a Yellow line
              double poly_inc = 2.5;
              int num_points = 25;
              
              for (int i = 1; i < num_points; i++) {
                next_x_vals.push_back(poly_inc * i);
                next_y_vals.push_back(polyeval(coeffs, poly_inc * i));
              }
              
              msgJson["next_x"] = next_x_vals;
              msgJson["next_y"] = next_y_vals;
    
              auto msg = "42[\"steer\"," + msgJson.dump() + "]";
              std::cout << msg << std::endl;
              // Latency
              // The purpose is to mimic real driving conditions where
              // the car doesn't actuate the commands instantly.
              this_thread::sleep_for(chrono::milliseconds(100));
              ws.send(msg.data(), msg.length(), uWS::OpCode::TEXT);
            }
          } else {
            // Manual driving
            std::string msg = "42[\"manual\",{}]";
            ws.send(msg.data(), msg.length(), uWS::OpCode::TEXT);
          }
    

     主要看前两句,就是把计算好的发送到模拟器,实际的话应该是发信号给方向盘和脚踏板。还有预测的轨迹点也输出到模拟器。

    现在大家再看看链接[2]中的这段话,是不是有点感觉:

    自动驾驶的3大核心科技是定位(在哪里),感知(周围是啥)以及控制(咋开车呢)。通过车道检测,我们可以对车的行进路线进行路径规划。本篇文章主要通过一个自行车的动力学模型讨论车辆的加速、刹车和转向的模型预测控制。目的不仅在于尽可能地控制车辆轨迹,同时也还要尽可能使速度平滑以避免晕车和频繁的刹车。

    模型预测控制主要在约束条件下使损失函数最小。例如,我们想要以100ms的周期调整转向和速度,在转向角度不能超过25°的约束下,最小化以规划的路径和实际路径之间的误差。我们通过传感器获取车辆的状态,比如速度,而我们的动作基于传感器读数以一个短的周期执行(例如1s)。例如,我们顺时针转向20°,然后每100ms周期减小1°。加入这些动作可以1秒钟之后的损失函数最小,我们将会采用第一个动作:顺时针转动20°,但是却并不执行后续的动作,而是在100ms后,重复优化过程。100ms后,有了新的读数,我们就重新计算下一个最优动作。模型预测控制通过预测接下来一段较长时间(1s)的损失函数,来计算选择出下一个较短周期(100ms)的最优动作。相比于短视的贪心算法,模型预测控制具有鲁棒性,因此能够控制得更好。

    给出一张图,大家可能看的更明白了。

    这是维基百科上的图[3]。 

    这一篇就到这里吧,写的也不够深入,下一篇我会讲MATLAB中的实现。感谢下以下三个链接的作者。

     [1] https://www.cnblogs.com/kui-sd具体u/p/9026796.html

     [2] https://www.leiphone.com/news/201812/3iia3PiNHnHiUFMb.html(中文翻译)

         https://medium.com/@jonathan_hui/lane-keeping-in-autonomous-driving-with-model-predictive-control-50f06e989bc9(英文原版,视频需翻墙)

     [3] https://zh.wikipedia.org/wiki/%E6%A8%A1%E5%9E%8B%E9%A0%90%E6%B8%AC%E6%8E%A7%E5%88%B6

    展开全文
  • python发邮件详解,smtplib和email模块详解

    万次阅读 多人点赞 2018-09-06 18:20:56
    SMTP协议属于TCP/IP协议簇,即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式,python实现发邮件也是基于此基础上进行封装的。 1.python发邮件所需要的基础包 python...

    在介绍具体的实现python发邮件的具体操作之前,我觉得有必要介绍下SMTP,更有助于理解python发邮件的实现原理。SMTP协议属于TCP/IP协议簇,即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式,python实现发邮件也是基于此基础上进行封装的。

    1.python发邮件所需要的基础包

    python发送邮件需要用到python自带的两个模块,smtplib和email。直接import导入,无需下载。
    python的smtplib提供了一种很方便的途径发送电子邮件,它对smtp协议进行了简单的封装。

    2.smtplib的用法

    smtplib用法相对来说很简单,就是分为两步。

    • 创建SMTP的操作对象并连接smtp目标服务器,可以是163、QQ等
    • 根据自己的账号登录目标服务器(自己的邮箱地址和邮箱授权码)
    • 调用对象中的方法,发送邮件到目标地址

    python与smtp服务器之间的具体交互的通用代码:

    import smtplib
    server = smtplib.SMTP(mailserver, port)  # 发件人邮箱中的SMTP服务器,端口是25
    server.login(sender, passwd)  # 发件人邮箱账号、邮箱授权码
    # msg.as_string()中as_string()是将msg(MIMEText或MIMEMultipart对象)变为str。
    server.sendmail(sender, receive, msg.as_string())  
    server.quit()

    具体的python连接目标服务器的代码如下:注:本文章用的是qq的smtp服务器。
    常用邮箱的smtp服务器地址:
    新浪邮箱:smtp.sina.com,搜狐邮箱:smtp.sohu.com,qq邮箱:smtp.qq.com

    sender_maile='80617252@qq.com' # 发送方的邮箱地址
    sender_pass = 'lsjdfsljdfk' # 邮箱提供的授权码,可在第三方登录,我这个是随便打的。
    sftp_obj =smtplib.SMTP('smtp.qq.com', 25)
    sftp_obj.login(sender_mail, sender_pass)
    #三个参数分别是:发件人邮箱账号,收件人邮箱账号,发送的邮件体
    sftp_obj.sendmail(sender_mail, receiver_mail, msg_root.as_string())
    sftp_obj.quit()
    3.email模块的详细理解和使用

    email模块下的mime模块下有常用的三个模块,三个模块中有三个大类。其实就是下边这三个了,说的很绕,下边为导入方式,一目了然。

    from email.mime.text import MIMEText    
    from email.mime.image import MIMEImage
    from email.mime.multipart import MIMEMultipart    

    简单说下他们的关系,如果构造一个MIMEText对象,就表示一个文本邮件对象,如果构造一个MIMEImage对象,就表示一个作为附件的图片对象,要把多个对象组合起来,就用MIMEMultipart对象,他代表的是整个邮件。这样说应该还不是很清晰,下边就分开来说,最后会总的总结,在最后边就是完整的代码(可以发送一切内容的代码)。

    A.MIMEText对象中有三个需要我们设置的参数,一个是正文内容,一个是正文内容的类型,例如:”text/plain”和”text/html”,一个是正文内容的编码。

    构造普通文本:

    text_info = 'hello world '
    text_sub = MIMEText(text_info,'plain', 'utf-8')  

    构造超文本:

    url = "https://blog.csdn.net/chinesepython"
    html_info = """
        <p>点击以下链接,你会去向一个更大的世界</p>
        <p><a href="%s">click me</a></p>
        <p>i am very glasses for you</p>
        """ % url
    html_sub = MIMEText(html_info, 'html', 'utf-8')  
    # 如果不加下边这行代码的话,上边的文本是不会正常显示的,会把超文本的内容当做文本显示
    html_sub["Content-Disposition"] = 'attachment; filename="csdn.html"'

    构造base64数据流,用于发送文件的时候使用,构造附件代码:

    txt_file = open(r'D:\python_files\files\hello_world.txt', 'rb').read()
    txt = MIMEText(txt_file, 'base64', 'utf-8')
    txt["Content-Type"] = 'application/octet-stream'
    # 命名发送的附件
    txt.add_header('Content-Disposition', 'attachment', filename='hello_world.txt')
    B.MIMEImage对象中只需要把读取的文件传入就行

    构造图片:

    image_file = open(r'D:\python_files\images\test.png', 'rb').read()
    image = MIMEImage(image_file)
    image.add_header('Content-ID', '<image1>')
    # 命名发送的图片
    image["Content-Disposition"] = 'attachment; filename="red_people.png"'
    C.MIMEMultipart对象创建的类型有三种,此模块主要是通过attach方法把上边构造的内容传入到邮件的整体内容中。
    • 邮件类型为”multipart/alternative”的邮件正文中包括纯文本正文(text/plain)和超文本正文(text/html)。
    • 邮件类型为”multipart/related”的邮件正文中包括图片,声音等内嵌资源。
    • 邮件类型为”multipart/mixed”的邮件包含附件,图片,文本等都可以添加,所以发的内容多的话一般是用这个的,选择mixed类型,什么内容都可以发。
    3.邮件头添加内容

    直接上示例代码:

    from email.mime.multipart import MIMEMultipart
    
    
    msg_root = MIMEMultipart('mixed')
    # 发件人
    msg_root['From'] = 'aaa@qq.com<aaa@qq.com>'
    # 收件人
    msg_root['To'] = '666666@qq.com'
    # 邮件主题
    subject = 'python sendemail test successful'
    msg_root['subject'] = Header(subject, 'utf-8')
    
    4.特别的用法说明:

    注:以下的msg_root为:
    msg_root = MIMEMultipart(‘mixed’)

    msg_root.as_string()是将msg_root对象变为str。
    msg_root.attach(MIMEText或者MIMEImage对象),因为MIMEMultipart对象代表邮件本身,其他连个是代表邮件正文,所以这个方法还是很强大的,把其他的构造内容添加到MIMEMultipart对象中就可以把文本,html,附件等一起发送了。

    5.发送各种内容的具体代码实现:

    所有代码合到一块,发送文本,html,图片,txt内容,用的时候你可以把需要的部分摘出来,也就是把没有加入到msg_root的对象拿出来,直接通过下边命令发送,例如只发送文本。
    sftp_obj.sendmail(sender_mail, receiver_mail, text_sub.as_string())。

    import smtplib
    from email.header import Header
    from email.mime.text import MIMEText
    from email.mime.image import MIMEImage
    from email.mime.multipart import MIMEMultipart
    
    
    def send_email_by_qq(to):
        sender_mail = '80617252@qq.com'
        sender_pass = 'aljflsjdf'#同样是乱打的
    
        # 设置总的邮件体对象,对象类型为mixed
        msg_root = MIMEMultipart('mixed')
        # 邮件添加的头尾信息等
        msg_root['From'] = '80617252@qq.com<80617252@qq.com>'
        msg_root['To'] = to
        # 邮件的主题,显示在接收邮件的预览页面
        subject = 'python sendemail test successful'
        msg_root['subject'] = Header(subject, 'utf-8')
    
        # 构造文本内容
        text_info = 'hello world'
        text_sub = MIMEText(text_info, 'plain', 'utf-8')
        msg_root.attach(text_sub)
    
        # 构造超文本
        url = "https://blog.csdn.net/chinesepython"
        html_info = """
        <p>点击以下链接,你会去向一个更大的世界</p>
        <p><a href="%s">click me</a></p>
        <p>i am very galsses for you</p>
        """% url
        html_sub = MIMEText(html_info, 'html', 'utf-8')
        # 如果不加下边这行代码的话,上边的文本是不会正常显示的,会把超文本的内容当做文本显示
        html_sub["Content-Disposition"] = 'attachment; filename="csdn.html"'   
        # 把构造的内容写到邮件体中
        msg_root.attach(html_sub)
    
        # 构造图片
        image_file = open(r'D:\python_files\images\test.png', 'rb').read()
        image = MIMEImage(image_file)
        image.add_header('Content-ID', '<image1>')
        # 如果不加下边这行代码的话,会在收件方方面显示乱码的bin文件,下载之后也不能正常打开
        image["Content-Disposition"] = 'attachment; filename="red_people.png"'
        msg_root.attach(image)
    
        # 构造附件
        txt_file = open(r'D:\python_files\files\hello_world.txt', 'rb').read()
        txt = MIMEText(txt_file, 'base64', 'utf-8')
        txt["Content-Type"] = 'application/octet-stream'
        #以下代码可以重命名附件为hello_world.txt  
        txt.add_header('Content-Disposition', 'attachment', filename='hello_world.txt')
        msg_root.attach(txt)
    
        try:
            sftp_obj =smtplib.SMTP('smtp.qq.com', 25)
            sftp_obj.login(sender_mail, sender_pass)
            sftp_obj.sendmail(sender_mail, to, msg_root.as_string())
            sftp_obj.quit()
            print('sendemail successful!')
    
        except Exception as e:
            print('sendemail failed next is the reason')
            print(e)
    
    
    if __name__ == '__main__':
        # 可以是一个列表,支持多个邮件地址同时发送,测试改成自己的邮箱地址
        to = '666666@qq.com'
        send_email_by_qq(to)
    6.总结

    为了让不是很理解发邮件的朋友能更好的理解,在这里是把所有的参数都写死了,比如说发送文件的具体内容,在真正开发使用过程中,可以把具体的内容通过预留出来参数去传入之后发送你想要发送的内容。
    发邮件功能还是很实用的,在真正的开发中或者大多数场合都能用到,比如说项目中一个重要的模块如果出问题了,你需要第一时间知道,就可以加入这个功能,把项目出问题报的具体内容发到你的邮箱,也可以第一时间想下处理的对策。
    下面以我通过此程序发送的邮件内容的截图做结尾吧。
    这里写图片描述

    展开全文
  • 《数据库原理》— 数据库系统概论第五版习题解析

    万次阅读 多人点赞 2017-05-29 14:57:48
     500 这个数字可以表示一件物品的价格是 500 元,也可以表示一个学术会议参加的人数有 500 人,可以表示一袋奶粉重 500 克。 ( 2 )数据库( DataBase ,简称 DB ) :数据库是长期储存在计算机内...
  • [机器学习]回归--Support Vector Regression(SVR)

    万次阅读 多人点赞 2018-05-09 12:28:54
    缩放的目的主要是 1)防止某个特征过大或过小,从而在训练中起的作用不平衡; 2)为了计算速度。因为在核计算中,会用到内积运算或exp运算,不平衡的数据可能造成计算困难。 对于SVM算法,我们首先导入sklearn.svm...
  • 蚁群算法求解有时间窗约束的车辆路径问题 matlab ... %select表示城市标号,to_visit(select)才表示城市 end %判断载重是否超限,并对路径修改 if load>W %判断车是否超载,超载就回到原地 ...
  • 基于MATLAB的水果分级设计

    万次阅读 多人点赞 2018-06-14 14:19:35
    我们可以通过图像中水果的不同大小的缺陷来对水果进行分级操作。 图 1-1 苹果分级系统总体设计结构图 1.5 本章小结 本章介绍了水果自动识别在实际应用上的重要性,指出了水果识别在实际应用方面取代人工识别的...
  • Python实验实例

    万次阅读 多人点赞 2019-06-27 19:28:05
    实验目的:  1、熟练运用 Python 运算符。  2、熟练运用 Python 内置函数。实验内容:  1、编写程序,输入任意大的自然数,输出各位数字之和。  2、编写程序,输入两个集合 setA 和 setB,分别输出它们的交集、...
  • 知识图谱构建技术一览

    万次阅读 多人点赞 2019-09-03 23:21:11
    知识图谱构建技术一览一、什么是知识图谱二、知识图谱技术架构(一)数据获取(Data Acquisition)(二)信息抽取(Information Extraction)(1)实体抽取(Entity Extraction)/命名实体识别(Name Entity ...
  • 逻辑英语语法笔记

    万次阅读 多人点赞 2019-04-02 21:32:03
    该笔记是笔者学习钟平老师的逻辑英语英语语法的笔记,主要目的总结和复习,如需要更深入学习请到网易有道精品课里学习。 一、中英文对切公式 1、基本公式 主干相同:主谓宾位置不变 修饰语英文后置,中文...
  • 知识表示

    千次阅读 2018-07-05 11:58:47
    http://pelhans.com/2018/03/16/xiaoxiangkg-note2/本讲首先对早期的知识...知识表示历史知识的概念早期的知识表示方法一阶谓词逻辑产生式系统框架表示法语义网络基于语义网的知识表示框架RDF简介RDF概念RDF和RDFSO...
  • GCN:网络表示学习NRL与图神经网络GNN的简介、应用、经典案例之详细攻略 目录 网络表示学习NRL与图神经网络GNN的简介 1、网络表示学习与图神经网络的重要进展 1.1、1986年的Distributed Representation 1.2...
  • 还是两个都可以用,为什么?答:首先,我要指出的是,在C#中,int其实就是System.Int32, 即都是32位的。其次,(int)和 Convert.ToInt32 是两个不同的概念,前者是类型转换,后者是内容转换,他们并不总是等效的。...
  • JAVA中(PO,VO,TO,BO,DAO,POJO)分别是指什么

    万次阅读 多人点赞 2018-09-12 22:35:34
    通俗点讲,就是将对象与关系数据库绑定,用对象来表示关系数据。 在O/R Mapping的世界里,有两个基本的也是重要的东东需要了解,即VO,PO。 O/R Mapper 对象/关系 映射  定义好所有的mapping之后,这个O/R  ...
  • Learning to Segment Every Thing算法笔记

    千次阅读 2017-12-25 22:37:59
    论文:Learning to Segment Every Thing 链接:https://arxiv.org/abs/1711.10370Instance segmentation算法几乎都是fully supervised training,监督学习就要求数据中的object都有instance mask标注,但是由于这种...
  • PMSM 仿真1:三相永磁同步电机的数学建模与坐标变换1,三相PMSM的基本数学模型  1.1 三相PMSM 的结构  1.2 基本数学模型2,三相PMSM的坐标变换  2.1 d-q轴模型是什么  2.2 坐标变换的目的  2.3帕克变换与...
  • Oracle的并行度

    千次阅读 2016-03-28 15:58:16
    查看dba_tables数据字典时,可以发现有“DEGREE”字段,这个字段表示的就是数据的并行度。这个参数的设置,关系着数据库的I/O,以及sql的执行效率。   并行度的优点就是能够最大限度的利用机器的多个cpu...
  • stop doing sth是“停止做某事”,doing是stop 的宾语,是要停止的动作, stop to do sth 是“停下来开始做某事”,to do是stop的状语,表示目的,是要开始做的事情,例如: 1、The two girls stopped talking when ...
  • 1.add_to_collection add_to_collectio为Graph的一个方法,可以简单地认为Graph下维护了一个字典,key为name,value为list,而add_to_collection就算把变量添加到对应key下的list中 add_to_collection(name,value...
  • IP地址0.0.0.0表示什么

    万次阅读 2015-03-25 22:25:17
    今天遇到这样的问题,0.0.0.0代表什么?参考RFC文档: 0.0.0.0/8 - Addresses in this block refer to source hosts on “this” network. Address 0.0.0.0/32 may be used as a source address for this host on...
  • with Coarse-to-fine Convolutional Network Cascade》,发表于2013年ICCV上的一篇用于定位多个人脸特征点的文献,实现了68个人脸特征点的高精度定位。这篇paper没有给出训练数据,也没有给出测试模型、源代码等,...
  • LTE-TDD随机接入过程(1)-目的和分类

    万次阅读 多人点赞 2016-03-08 16:17:18
    UE通过检测MSG2中是否携带了其发送的Preamble码来标识是否收到了eNB的随机接入响应,但此时没有完成竞争解决,并不表示此次eNB侧的应答就是针对本UE的应答。 C.UE向eNB发送MSG3( First scheduled UL transmission...
  • 上一篇文章已经介绍了几篇关于Seq-to-Seq模型的论文和应用,这里就主要从具体的模型细节、公式推导、结构图以及变形等几个方向详细介绍一下Seq-to-Seq模型。这里我们主要从下面几个层次来进行介绍: Seq-to-Seq框架1...
  • BlockChain:【中本聪】历史之作《Bitcoin: A Peer-to-Peer Electronic Cash System》 《比特币:一种点对点的电子现金系统》—九页中英文对照翻译 导读 1、了解区块链底层原理技术,还是要看原汁原味的白皮书,对...
  • switch_to宏调试
  • JAVA_HOME should point to a JDK not a JRE

    万次阅读 2014-08-19 12:31:18
    e:/"再运行java A, 看看会有什么结果~~:)~~~, 一切正常, java命令通过CLASSPATH找到了.class文件!  3,设置PATH:   道理很简单, 你想在任何时候都使用%JAVA_HOME%/bin/java 等来执行java命令吗, 当然不会,...
  • FDB - MAC地址

    千次阅读 2016-10-17 00:18:32
    英文: Forwarding Database 中文: MAC地址 介绍: 网络设备都以MAC地址来唯一地标识自己,而交换机要实现设备...也叫MAC地址,主要由MAC地址、VLAN号、端口号和一些标志域等信息组成,如果收到数据帧的目的M
  • (1) 实验目的 ①熟练掌握线性表的结构特点和基本操作。 ②巩固C相关的程序设计方法与技术。 ③学会使用顺序解决实际问题。 (2) 实验过程 ①建立一个顺序,输入n个元素并输出, 定义函数名为CreatList(SqList...
  • gcc编译器----中间表示

    千次阅读 2014-05-06 20:38:36
    中间表示( intermediate representation, IR) 指编译器对于源程序进行扫描后生成的内部表示,代表源程序的语义和语法结构,编译器的各个阶段都在IR上进行分析或优化变换,因而它对编译器的整体结构、效率和健壮...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 423,162
精华内容 169,264
关键字:

to除了表目的还表示什么