SQL(下):

联结表:

SQL最强大的功能之一就是可以在数据查询的执行中联结表。联结表是利用SQL的SELECT能够执行的最重要的操作。

关系表:

例子:有一个包含产品目录的数据库表,它存储的信息包括,产品描述,价格,供应商信息(供应商名字,地址,联系方式)。如果同一个供应商有不同的产品,那么在表中就要存储很多重复的供应商信息。所以可以把产品和供应商分开存储,好处是:1.重复不大;2.供应商信息发生变化时,只需要修改一次。

关系表的设计就是要把信息分解为多个表,一类数据一个表,每个表之间可以通过某些共同的值相互关联。像上面例子:可以建立一个表存储产品,只包含供应商名字,另一个表包含供应商信息,通过供应商名字让两者关联。关系数据可以有效的存储,方便的处理,因此伸缩性比非关系数据库要好。(伸缩性:能够适应不断增加的工作量而不失败)

创建联结:

联结是一种机制,用来在一条SELECT语句中关联表。使用特殊的语法,可以从多个表中返回一组输出;联结在运行时关联表中正确的行。联结本身不是物理实体,它在实际的数据库表中并不存在。DBMS会根据需要建立联结,它在查询执行期间一直存在。创建联结的方式:指定要联结的表以及关联它们的方式即可。

SELECT 表1的列,表2的列
FROM 表1,表2
WHERE 表1.列=表2.列;--这两个表通过WHERE子句进行联结,指示表1的某个列和表2的某个列匹配起来

注意:

  1. 在指定匹配的两列时,使用了完全限定列名,因为在引用的列有可能造成歧义时,就要使用完全限定列名,否则会返回错误。
  2. WHERE的重要性:要记住,在一条SELECT语句中联结几个表时,它们的关系是在运行中被构造的。在数据库表中没有指示DBMS如何对表进行联结。在联结两个表时,实际上要做的就是将第一个表中的每一行和第二个表中的每一行进行配对。而WHERE子句作为过滤条件只包含那些匹配联结条件的行。在没有WHERE子句时,第一个表的每一行都会与第二个表的每一行进行配对,而不管它们是否能在一起。
  3. 笛卡儿积:由没有联结条件的表关系返回的结果为笛卡儿积。这种方式检索出来的行的数目是第一个表的行数乘以第二个表的行数。所以不要忘了WHERE子句,否则DBMS将返回比想要的数据多得多的数据。有时候,返回笛卡儿积的联结也叫做叉联结。

内联结:

目前使用的联结叫做等值联结,它基于两个表之间的相等测试。这种联结也叫做内联结,其实内联结还有不同的语法。使用INNER JOIN+ON。

SELECT 表1的列,表2的列
FROM 表1 INNER JOIN 表2 ON 表1.列=表2.列;

使用方式:INNER JOIN用于指定两个表的关系,联结条件用ON子句。传递给ON的实际条件与传递给WHERE的相同。

联结多个表:

SQL不限制于一条SELECT语句中可以联结的表的数目。创建联结的基本规则也相同,首先列出表,再定义表的关系。

SELECT 表1的列1,表2的列1,表3的列1
FROM 表1,表2,表3
WHERE 表1.列=表2.列 AND 表2.列=表3.列;

注意:

  1. 性能考虑:DBMS会在运行时关联指定的每个表,以处理联结。这种处理可能非常耗费资源,因此,应该注意,不要联结不必要的表。
  2. 联结的表的最大数目:虽然SQL不限制每个联结约束中表的数目,但是实际上许多DBMS都有限制。

创建高级联结:

使用表别名:前面说过可以对列名或者计算字段使用别名,SQL还允许给表名起别名。这样做的好处有:1.缩短SQL语句;2.允许在一条SELECT语句中多次使用相同的表。注意:1.Oracle中没有AS,在Oracle中使用别名直接简单指定列名即可;2.表的别名只在查询执行中使用,与列名不同的是,表的别名不返回到客户端中。

自联结:

上面说到在一条SELECT语句中多次使用相同的表。举一个例子:完成Jim同一公司的所以顾客发送邮件。首先要找到Jim的公司,再找到该公司下的员工。这种情况可以使用子查询,先查询Jim公司,再WHERE比对出其他员工。也可以使用联结:

SELECT c1.列,c1.列
FROM 表 AS c1,表 AS c2--一个表多个别名,实际上还是同一个表
WHERE c1.公司名=c2.公司名 AND c2.名字='Jim';

表名出现了两次,为了避免歧义性,所以使用表别名,让DBMS知道是哪个。自联结通常作为外部语句,用来替代从表中检索数据的使用子查询语句。

自然联结:

无论何时对表进行联结,应该至少有一列不止出现在一个表中(被联结的列)。标准的联结返回所有数据,相同的列甚至多次出现。自然联结排除多次出现,使每一列只返回一次。

外联结:

许多联结将一个表中的行于另一个表中的行进行相互关联,但是有时候需要包含那些没有关联行的那些行。比如:对每个客户订单计数,包括那些没有购买的客户或者列出所有产品的订购数量,包括没有订购的产品。这些都是联结包含了那些在相关表中没有关联行的行。这种联结称为外联结。

SELECT 表1.列,表2.列
FROM 表1
LEFT OUTER JOIN 表2 ON 表1.列1=表2.列1;

与内联结的INNER JOIN不同的是,外联结使用OUTER JOIN前面再加一个关键字(LEFT.RIGHT,FULL).LEFT表示加入OUTER JOIN左边的表中未关联的行;RIGHT表示加入OUTER JOIN右边的表中未关联的行;FULL加入OUTER JOIN左右两边的表中未关联的行。

使用带聚集函数的联结:

聚集函数用来汇总数据,这些函数也可以和联结一起使用。

联结使用事项:

  • 注意使用的联结类型,一般使用内联结,但是外联结也很有效。
  • 关于确切的联结用法,应该看文档,因为DBMS支持的语法不同。
  • 保证使用正确的联结条件。
  • 在一个联结中可以包含多个表,甚至可以对每个联结采用不同的联结类型。

组合查询:

多数SQL查询只包含从一个或者多个表中返回数据的单条SELECT语句;或者是从多个SELECT语句中查询,并且将结果作为一个查询结果集返回。这些组合查询通常叫做并或者叫做复合查询。主要有两种情况需要组合查询:1.在一个查询中从不同的表返回结构数据。2.对一个表执行多个查询,按一个查询返回数据。

创建组合查询:

使用UNION操作符来组合数条SQL查询,可以将多条SELECT语句的结果组合成为一个结果集。使用方式为:在两条SELECT语句之间放入UNION关键字表示组合两者的结果。

SELECT 列
FROM 表
WHERE 列 IN(值)
UNION
SELECT 列
FROM 表
WHERE 列=1;

UNION规则:

  1. UNION组合SELECT的数目在SQL中没有限制,但是,最好还是看一下DBMS文档。
  2. UNION必须由两条或者两条以上的SELECT语句组成,语句之间使用UNION分隔。
  3. UNION中每个查询都必须包含相同的列,表达式或者聚集函数,不过,每个列不需要以相同的次序列出。如果UNION遇到两个表中有不同的列名时,首先它会返回第一个表的列名,而这个列名还可以使用别名;第二个列名则不会被管。这样会带来一个副作用:由于只使用了第一个列名,那么可以对它排序,而不能对第二个表那个不同的列名排序。
  4. 列数据类型必须兼容。
  5. UNION还会从查询结果集中自动去除重复的行,这是UNION的默认行为。如果想要保留,也就是所有的匹配行都返回不去除,那么可以使用UNION ALL替代UNION。
  6. 对组合查询进行排序:在用到UNION组合查询时,只能使用一条ORDER BY子句,它必须位于最后一条SELECT语句之后。因为对于结果集不允许一种方式排序一部分,另一种方式排序另一部分,所以不允许使用多条ORDER BY子句。
  7. 某些DBMS还支持两种UNION:EXCEPT,可以用来检索只在第一个表存在而第二个表不存在的行;INTERSECT可以用来检索两个表都存在的行。

插入数据:

顾名思义,INSERT用来将行插入或者添加到数据库表中,使用插入时有可能需要特定的权限,所以在使用前应该确保自己是否有权限。而插入的情况有:1.插入完整的一行;2.插入行的一部分;3.插入某些查询的结果。

插入完整的行

把数据插入表中的最简单方法就是使用基本的INSERT语法,它要求指定表名和插入到新行中的值。INSERT关键字后面跟着INTO,它在某些SQL实现中INTO是可选的,但是写上保证SQL代码之间的可移植性。

INSERT INTO 表
VALUES(列1的值,列2的值……);
  1. INSERT INTO后面跟着插入的表名,VALUES子句里面包括要存储在表中每一列的数据,必须在每一列都提供一个值。如果某列没有值,那么应该使用NULL值(假定表允许对该列指定空值)。
  2. 这种语法虽然简单,但是并不安全。因为上面的SQL语句高度依赖于表中列的定义次序,还依赖于其容易获取的次序信息。即使可以得到这种次序信息,也不能保证在各列在下一次表结构变动后保持完全相同的次序。

编写INSERT语句更加安全但是更加烦琐的方法为:

INSERT INTO 表(列1,列2)
VALUES(列1的值,列2的值……);

与前面不同的是,这个在表后面给出了明确的列名,在插入行时,DBMS将用VALUES子句中的相应值填入列表中的对应项。也就是按照次序,VALUES中的第一个值将对应于表中第一个指定的列名;VALUES中的第二个值将对应于表中第二个指定的列名;以此类推。而表中的列的次序也不一定按照表中列的实际次序,其优点就是,即使表的结构改变,这样INSERT语句仍然可以正确工作。所以不要使用没有明确给出列的INSERT语句。注意:插入的主键是具有唯一性的,DBMS不允许插入相同主键的新行。

插入部分行:

​#这个表有三个列
INSERT INTO 表(列1,列2)
VALUES(列1的值,列2的值);

​

我们可以利用明确给出表的列名的方法实现只给某些列提供值,某些列不提供值。如上述省略了列3及其对应的值。在省略列,只提供部分值的情况下,我们必须满足省略的列具有以下某个条件:1.该列定义为允许NULL值(无值或者空值);2.在表中给出了默认值,则表示如果没有插入值,就使用默认值。如果表中不允许有NULL值和默认值,还省略了表中的值,那么DBMS会报错,插入失败。

插入检索出来的数据:

INSERT一般用来给表插入具有指定列值的行。INSERT还存在另外一种情况,就是利用它将SELECT语句的结果插入表中,这就是所谓的INSERT SELECT。顾名思义,它是由一条SELECT和一条INSERT组成的。

INSERT INTO 表(列1,列2)
SELECT 列1,列2
FROM 检索的表;

把检索的表的列插入到另一个表的列中。同样的,不一定要求列名匹配,比如:检索列1和表列1匹配,其实DBMS使用的是列的位置,也就是检索列的第一位对应于表的第一位,以此类推。SELECT语句中将插入多少行取决于检索的表,如果表为空,则没有行被插入。如果表有数据,则所有数据插入表中。SELECT还可以包括WHERE过滤插入的数据。INSERT通常只插入一行,要插入多行,必须执行多个INSERT语句。但是INSERT SELECT是一个例外。

从一个表复制到另一个表:

有一种数据插入不使用INSERT语句。要将一个表的内容复制到另一个全新的表,也就是运行中创建的表,可以使用CREATE SELECT语句(或者在SQL server中使用SELECT INTO语句)。DB2不支持这里描述的CREATE SELECT。与INSERT SELECT将数据插入到一个已经存在的表不同的是,CREATE SELECT是复制到新表。

CREATE TABLE 新表 AS SELECT * FROM 表;
#把表的全部内容检索到新表中

SELECT * INTO 新表 FROM 表;
#SQL Server写法

当然在复制时,可以只复制几列或者使用任何的SELECT选项和子句,包括WHERE和GROUP BY;也可以利用联结从多个表中插入数据;不管从多个表中检索数据,最后都是只能插入到一个表中。

更新和删除数据:

更新表中的数据,可以使用UPDATE语句。它有两种使用的方式:更新表中的所有行;更新表中的特定行。同样的,使用UPDATE语句时要注意自己是否有权限。如果在UPDATE中省略了WHERE子句,那么就会更新表中的所有行。

UPDATE 表
SET 列=值
WHERE 过滤条件;

正如上述:

  1. 基本的UPDATE由三部分组成:要更新的表;列名和它的新值;确定要更新哪些行的过滤条件。
  2. 其中SET命令用来将新的值赋予给要被更新的列,UPDATE以WHERE子句结束,它用于告诉DBMS要更新哪一行。在更新多个列时,也是一条SET命令就足够了,各个需要更新的列和新值用逗号进行分隔,最后一列不用逗号。
  3. 在UPDATE中还可以使用子查询,使得能够用SELECT语句检索出来的数据来更新列数据。
  4. 有些DBMS还支持FROM子句,它也可以用一个表中数据更新另一个表中的行。
  5. 要删除某个列的值,可以把这个列的值设置为NULL(假设表中允许NULL值)。

删除数据:

从一个表中删除数据,使用DELETE语句。它有两种使用的方式:从表中删除所有的行;从表中删除特定的行。同样的,使用DELETE语句时要注意自己是否有权限。如果在DELETE中省略了WHERE子句,那么就会删除表中的所有行。

DELETE FROM 表
WHERE 过滤条件;

正如上述:

  1. 基本的DELETE语句由要删除数据的表名和确定要删除哪些行的过滤条件组成。
  2. 在某些SQL实现中,跟在DELETE后面的FROM是可选的,但是最好提供这个关键字,提高可移植性。
  3. DELETE不需要列名或者通配符。因为DELETE是删除整行而不是单独删除列的,如果要删除指定的列,那么可以使用UPDATE语句。
  4. DELETE删除行,甚至是删除表中所有的行时。表还在,因为不删除表本身
  5. 要想删除所有行,不要使用DELETE,可以使用TRUNCATE TABLE语句。它可以完成相同的工作,但是速度更加快。

更新和删除的使用建议:

  • 除非确定要删除或者更新每一行,否则绝对不要使用不带WHERE子句的UPDATE或者DELETE语句。
  • 保证每个表都有主键,尽可能像对待WHERE那样使用它。
  • 在使用DELETE或者UPDATE语句之前,应该先使用SELECT进行测试,保证它过滤的是正确的行,以防止编写的WHERE不正确。
  • 使用强制实施引用完整性的数据库,这样DBMS不允许删除数据与其他表相关联的行。
  • 有的DBMS允许数据库管理员加上约束,以防止不带WHERE子句的UPDATE和DELETE语句。
  • 若是SQL没有撤销按钮,则要非常小心使用这两个语句,以免造成麻烦。

外键:

外键约束(也称为引用约束引用完整性约束)可定义表间以及表内必需的关系。例如,典型的外键约束可能规定 EMPLOYEE 表中的每个职员必须 是一个现有部门的成员,该部门在 DEPARTMENT 表中定义。引用完整性是数据库的一种状态,在该状态中,所有外键的所有值都有效。 外键是表中的一列或一组列,它的值需要与其父表的行的至少一个主键或唯一键值相匹配。 引用约束是这样一种规则,仅当满足下列其中一个条件时,外键的值才有效:它们作为父键的值出现。或者外键的某些组成部分为空。包含父键的表称为引用约束的父表,包含外键的表被认为是该表的从属表

当 SQL 操作尝试更改数据的方式导致引用完整性受到影响时,可能是违反了引用约束。 例如:

  • 插入操作可能尝试将一个数据行插入到子表中,该行的外键列中的值与相应父表的父键中的值不匹配。
  • 更新操作可能尝试将子表的外键列中的值更改为一个在相应父表的父键中没有匹配值的值。
  • 更新操作可能尝试将父表的父键中的值更改为一个在子表的外键列中没有匹配值的值。
  • 删除操作可能尝试从父表中移除在子表的外键列中具有匹配值的记录。

创建和操纵表:

SQL不仅仅可以用来表的数据操纵,而且还可以用来执行数据库和表的所有操作,包括表本身的创建和处理。一般有两种创建表的方法:1.多数DBMS都具有交互式创建和管理数据库表的工具;2.表也可以直接用SQL语句操纵。用第二种方法时,可以使用SQL的CREATE TABLE语句。需要注意的是使用第一种方法时其实也是在使用SQL语句。不过这些语句是界面工具自动生成并且执行的SQL语句。在不同的SQL实现中,语法可能有所不同。

​
CREATE TABLE 表名
(
列1名 数据类型 是否允许NULL,
列2名 数据类型 是否允许NULL,
列3名 数据类型 是否允许NULL DEFAULT 1,
……
);

可以看到:

  1. 利用CREATE TABLE创建表时,必须给出新表的名字,在CREATE TABLE后面给出;表列的名字和定义,用逗号分隔;有的DBMS还要指定表的位置。
  2. 每一列的定义由列名开始,列名在表中必须是唯一的;后面跟着列的数据类型;再后面跟着是否支持NULL,NULL就是没有值或者缺值。不允许没有NULL的情况下,在插入和更新时该列必须有值,不然报错。(支持就写上NULL(也是默认),不支持就写上NOT NULL)。最后以分号结束。
  3. 主键和NULL:主键是其值可以唯一的标识表中每一行的列。只有不允许NULL值的列可以作为主键,允许NULL值的列不能作为唯一的标识。
  4. SQL还允许指定默认值,在插入行时如果不给出值的话,DBMS将自动采用默认值。默认值的设置在CREATE TABLE语句的列定义中使用关键字DEFAULT指定。默认值还经常用于日期或者时间戳列中,例如:通过指定引用系统日期的函数或者变量,就可以将系统日期用作默认日期。
  5. 注意:在创建新的表时,指定的表名必须不存在,否则会出错。也防止意外覆盖已有的表,SQL要求首先手工的删除该表,然后再重建它,而不是简单的用创建表的语句来覆盖它。

浅谈数据类型:

数据类型是定义列中可以存储什么数据以及数据实际上怎么样存储的基本规则。数据类型主要用于:1.允许限制存储在列中的数据;2.允许在内部更加有效的存储数据;3.数据类型允许变换排序顺序。但是不同的DBMS数据类型可能有很大的不同。数据类型有:

字符串数据类型说明
CHAR1-255个字符的定长字符串
NCHARCHAR的特殊形式,用来支持多字节或Unicode字符
NVARCHARTEXT的特殊形式,用来支持多字节或Unicode字符
TEXT变长文本
  • 定长字符串在创建表时指定长度,定长列不允许传入的字符串多于指定的长度,反之,少于长度使用空格填充。
  • 变长字符串存储任意长度的文本,最大长度随不同数据类型和DBMS而变化。有些变长数据类型具有最小的定长,而有些是完全变长的。
  • 不管什么形式,字符串值都要括在单引号内。

数值数据类型说明
BIT单个二进制值
DECIMAL定点或者精度可变的浮点值
FLOAT浮点值
INT4字节整数值
REAL 4字节浮点值
SMALLINT2字节整数值
TINYINT1字节整数值

日期和时间数据类型说明
DATE日期值
DATETIME 日期时间值
SMALLDATETIME日期时间值,精确到分
TIME 时间值
  • 所有的DBMS都支持用来存储日期和时间的数据类型,但是每种有不同的精度或者取值范围。而且不存在所有DBMS都理解的定义日期的标准方法。

二进制数据类型说明
BINARY定长二进制数据
LONG  RAW变长二进制数据,最多2GB
RAW定长二进制数据,最多255B
VARBINARY变长二进制数据,最多在255-8000B
  • 二进制数据类型是最不具有兼容性的数据类型,与前面不一样的是,二进制数据类型可以包含任何数据,甚至是包含二进制信息,比如:图像,多媒体,字处理文档等等。

更新表:

更新表可以使用ALTER TABLE语句,虽然所有的DBMS都支持ALTER TABLE,但是它们所允许更新的内容差别却很大。更新表需要考虑

  • 理想情况下,不要对表中包含数据时对其更新。应该在表的设计过程中充分考虑未来的需求,避免以后对表结构做出大的更改。
  • 所有的DBMS都允许给现有的表增加列,不过在增加列时对数据类型有所限制。
  • 许多DBMS都不允许删除或者更改表中的列。
  • 多数DBMS允许重新命名表中的列。
  • 许多DBMS限制对已经填有数据的列进行更改,对没有数据的列几乎没有限制。
ALTER TABLE 表名
ADD 列 数据类型;--增加列

ALTER TABLE 表名
DROP COLUMN 列 ;--删除列

正如上述:

  1. 在使用ALTER  TABLE语句时首先要给出更改的表名,再列出要进行哪些更改。
  2. 上面例子中:第一个使用ADD增加列,第二个使用DROP COLUMN删除列
  3. 使用ALTER TABLE时应该小心,应该在使用之前完成备份。

复杂的表结构更改一般需要手动删除的过程,它一般涉及以下步骤:

  1. 用新的表布局创建一个新的表;
  2. 使用INSERT SELECT语句(在插入数据那章)从旧表将数据复制到新表中,有必要的话还可以使用转换函数和计算字段;
  3. 检验包含所需数据的新表;
  4. 重命名旧表,甚至是删除;
  5. 用旧表的名字重命名新表;
  6. 根据需要,还可以创建触发器,存储过程,索引和外键。

删除表:

删除表指的是删除整个表而不是其的内容,使用DROP TABLE语句,删除表没有确定步骤,也不能撤销,执行后永久删除表。许多DBMS允许强制实施有关规则,防止删除与其他的表有关联的表,直到该关系被删除为止。

DROP TABLE 表;

重命名表:

每个DBMS的标准不一样,对于DB2 ,MariaDB,MySQL和PostgreSQL使用RENAME语句;SQL Server使用sp_rename存储过程;SQLite使用ALTER TABLE语句。重命名操作基本语法都要求指定旧表名和新表名。

使用视图:

视图是虚拟的表,与包含数据的表不一样,视图只包含使用时动态检索数据的查询。例如:

​
SELECT 表1的列1,表2的列1,表3的列1
FROM 表1,表2,表3
WHERE 表1.列=表2.列 AND 表2.列=表3.列 AND 表1.列2=3;

​

上面是联结多个表,并且检索出表1的列2等于3的表1的列1,表2的列1,表3的列1。现在,可以把整个查询包装为一个虚拟表(视图),更加轻松的检索出数据:

​
SELECT 表1的列1,表2的列1,表3的列1
FROM 视图
WHERE 表1.列2=3;

这就是视图是作用,作为一个视图,它不包含任何的列或者数据,包含的只是一个查询。所有的DBMS都支持视图创建语法。

为什么使用视图?

  • 重用SQL语句。
  • 简化复杂的SQL操作。
  • 使用的是表的一部分而不是整个表。
  • 保护数据,可以授予用户访问表的特定部分的权限,而不是整个表的访问权限。
  • 更改数据格式和表示,视图可以返回与底层表的表示和格式不同的数据。
  • 创建视图之后,可以使用与表基本相同的方式使用它们。
  • 重要的是,视图仅仅是用来查看存储在其他地方数据的一种设施。视图本身不包含数据,因此返回的数据都是从其他表中检索出来的。表被更改后,视图返回的也是更改后的数据。

视图的规则和限制:

  • 与表一样,视图必须唯一的命名。
  • 对于可以创建的视图数目没有限制。
  • 创建视图,必须有足够的访问权限。这些权限通常由数据库管理人员授予。
  • 视图可以被嵌套,即可以从其他的视图中检索数据的查询来构造视图。但是嵌套视图在不同的DBMS中所允许的层数不同,且可能严重降低性能。
  • 许多DBMS禁止在视图查询中使用ORDER BY子句。
  • 有些DBMS要求对返回的所有列进行命名,如果列是计算字段,则需要使用别名。
  • 视图不能索引,也不能有关联的触发器或者默认值。
  • 有些DBMS把视图作为只读的查询,这就表示可以从视图检索数据,但是不能将数据写回底层表。
  • 有些DBMS允许创建这样的视图,它不能进行导致行不再属于视图的插入和更新。

创建视图:

视图使用CREATE VIEW 语句来创建。与CREATE TABLE一样,它也是只能用于创建不存在的视图。删除视图使用DROP VIEW语句。覆盖或者更新视图,必须先删除它,然后再重新创建。

利用视图简化联结:

​CREATE VIEW 视图 AS​
SELECT 表1的列1,表2的列1,表3的列1
FROM 表1,表2,表3
WHERE 表1.列=表2.列 AND 表2.列=表3.列 ;

上述利用创建了一个视图,它联结了三个表,那么我们在使用时就可以利用视图进行检索数据:

​
SELECT 表1的列1,表2的列1,表3的列1
FROM 视图
WHERE 表1.列2=3;

视图不仅仅极大的简化了复杂SQL语句的使用,还可以一次性编写基础的SQL,然后根据需要多次使用。

用视图重新格式化检索的数据:

--这是重新格式化检索出来的数据
​SELECT RTRIM(列1)+RTRIM(列2)--或者SELECT RTRIM(列1)+'('+RTRIM(列2)+')'
AS 别名--给这个新的值起一个替换名
FROM 表
ORDER BY 列1;
 

--现在假设经常需要这个格式的结果,我们使用视图就可以不必每次进行拼接
CREATE VIEW 视图 AS
​SELECT RTRIM(列1)+RTRIM(列2)--或者SELECT RTRIM(列1)+'('+RTRIM(列2)+')'
AS 别名--给这个新的值起一个替换名
FROM 表
ORDER BY 列1;

SELECT *FROM 视图;--这时检索可以这样写

用视图过滤不想要的数据:

视图对于应用普通的WHERE子句也很有用。例如:

CREATE VIEW 视图 AS
​SELECT 列1,列2
FROM 表
WHERE 列 IS NOT NULL;--排除空值的列

SELECT *FROM 视图;--这时检索可以这样写

​

从视图检索数据时如果使用了一条WHERE子句,则两组子句(一组在视图中,一组是传递给视图的)将自动组合。

使用视图和计算字段:

在简化计算字段的使用上,视图也很有用。例如:

​CREATE VIEW 视图 AS
​SELECT 列1,列2,列1*列2 AS 别名
FROM 表;

SELECT * FROM 视图;--这时检索可以这样写
SELECT * FROM 视图 WHERE 列1=值;--或者可以再加上过滤

使用存储过程:

迄今为止,我们使用的大多数SQL语句都是针对一个或者多个表的单条语句。并非所有操作都那么简单,经常有些操作需要多条语句才能完成,且执行SQL语句的次序也不是固定的。那么,除了可以单独编写每条SQL语句,并且根据结果有条件的执行其他语句;还可以创建存储过程,存储过程就是为以后使用而保存的一条或者多条SQL语句,可以将其视为批文件,虽然它们的作用不限于批处理。

为什么要使用存储过程:

  • 通过把处理封装在一个易用的单元里,可以简化复杂的操作。
  • 由于不要求反复建立一系列处理步骤,因而保证了数据的一致性。从而防止错误。
  • 简化变动的管理。如果表名,列名,业务逻辑有变化,那么只需要更改存储过程的代码。使用它的人员甚至不需要知道这些变化。从而提高安全性。
  • 因为存储过程通常以编译过的形式存储,所以DBMS处理命令所需的工作量少,提高了性能。
  • 存在一些只能用在单个请求中的SQL元素和特性,存储过程可以使用它们来编写功能更强更灵活的代码。
  • 换句话说,使用存储过程有三个主要的好处:简单,安全,高性能。

在将SQL代码转换为存储过程前,也必须知道它的一些缺陷:

  • 不同的DBMS中的存储过程语法有所不同。事实上,编写可移值存储过程几乎是不可能的。
  • 一般来说,编写存储过程比编写基本SQL语句更加复杂。
  • 大多数DBMS把编写存储过程所需的安全和访问权限和执行存储过程所需的安全和访问权限分开来。

执行存储过程:

存储过程的执行比编写要频繁的多,执行存储过程的SQL语句为:EXECUTE。它接收存储过程名和需要传递给它的任何参数。参数会匹配存储过程的预期变量。而表中的主键不作为属性传递给存储过程,最好让它生成自动化。

EXECUTE 存储过程(值1,值2……);

创建存储过程:

不同的DBMS实现不一样,仅仅提供SQL Server一个例子:

CREATE PROCEDURE 存储过程
AS
DECLARE @局部变量 INTEGER
SELECT @局部变量=COUNT(*)
FROM 表
WHERE 过滤条件;
RETURN @局部变量;
DECLARE @value INT
EXECUTE @value=存储过程;
SELECT @value;

管理事务处理:

使用事务处理,通过确保成批的SQL操作要么完全执行,要么完全不执行,以此来维护数据库的完整性如果没有错误发生,则整组语句提交到数据库表,如果发生错误,则进行撤销,将数据库恢复到某个安全已知的状态。正如关系数据库把数据存储在多个表中,使得数据更容易操作,维护和重用。

术语:

  • 事务:指一组SQL语句。
  • 回退:指撤销指定的SQL语句的过程。
  • 提交:指将未存储的SQL语句结果写入数据库表。
  • 保留点:指事务处理中设置的临时占位符,可以对它发布回退。
  • 事务处理可以用来管理INSERT,UPDATE,DELETE语句,不能回退SELECT,CREATE,DROP语句。

控制事务处理:

管理事务的关键在于将SQL语句分解为逻辑块,并且明确规定数据何时应该回退,何时不应该回退。有的DBMS要求明确标识事务处理块的开始和约束,不同的DBMS实现不同。

简述:

  • SQL的ROLLBACK命令用来回退SQL语句。
  • COMMIT语句:一般的SQL语句都是针对数据库表直接执行和编写的。这就是所谓的隐式提交,即提交操作是自动进行的。在事务处理块中,提交不会隐式进行。不过不同的DBMS做法不一样。而进行明确的提交,应该使用COMMIT语句。
  • 使用保留点:前面的都是写入或者撤销整个事务,要支持回退部分事务,必须在事务处理块中的合适位置放置占位符。这样就可以回退到占位符上。在MariaDB,MySQL,Oracle上使用SAVEPOINT创建占位符。

使用游标:

SQL检索操作返回一组称为结果集的行,这组返回的行都是与SQL语句相匹配的行,但是简单使用SELECT语句,没有办法得到第一行,下一行这些。有时候,需要在检索出来的行中前进或者后退一行或者多行,这就是游标的用途所在。游标是一个存储在DBMS服务器的数据库查询,它不是一条SELECT语句,而是被该语句检索出来的结果集。在存储了游标之后,应用程序可以根据需要滚动或者游览其中的数据。

不同的DBMS支持不同的游标选项和特性,常见的如下:

  • 能够标记游标为只读,但不能更新和删除。
  • 能够控制可以执行的定向操作。
  • 能够标记某些列为可以编辑的,某些列不可编辑的。
  • 规定范围,使游标对创建它的特定请求或者对所有请求可访问。
  • 指示DBMS对检索出来的数据进行复制,使数据在游标打开和访问期间不变化。
  • 游标主要用于交互式应用。

使用游标:

在使用游标前,必须要定义它。这个过程实际上没有检索数据,它只是定义要使用的SELECT语句和游标选项。一旦声明,就必须打开游标使用。对于填有数据的游标,根据需要取出各行。在结束游标使用时,必须关闭游标。在使用游标时,语句为OPEN CURSOR语句,它会执行查询,存储检索出的数据以供游览和滚动。现在就可以使用FETCH语句来访问游标数据了。

创建游标:

使用DECLARE语句创建游标,语法在不同的DBMS有所不同。DECLARE语句命名游标,并且定义相应的SELECT语句。

关闭游标:

游标在使用完毕后要关闭,不同的DBMS有不同的语法。例如DB2,Oracle和PostgreSQL为CLOSE语句。

补充:

索引:

索引是用来排序数据以加快搜索和排序操作的速度。数据库的索引中,主键数据总是排序的,这就是DBMS的工作,按主键检索特定行总是一种快速有效的操作。但是这样其他列的搜索通常效率不高,那么还是可以使用索引,可以在一个或者多个列上定义索引,再使用DBMS保存其内容的一个排过序的列表。DBMS搜索排过序的索引,找出匹配的位置,然后检索。

注意事项:

  1. 索引用CREATE INDEX语句创建,不同的DBMS有区别。
  2. 索引改善检索的性能,但是降低了插入,更改,删除的性能。在执行这些操作时,DBMS应该动态更新索引。
  3. 索引数据可能要占有大量的存储空间。
  4. 并非所有的数据都适合作为索引。取值不多的数据不如取值多的好处大,索引还适合数据过滤和数据排序。
  5. 可以在索引定义多个列。

触发器:

触发器是特殊的存储过程,它在特定的数据库活动发生时自动执行。触发器可以与特定表中的插入,更改,删除操作相关联。与存储过程不同的是,触发器与单个表相关联。触发器代码有:插入操作中所有新数据;更改操作中所有的新旧数据;删除操作中删除的数据的访问权。根据DBMS不同,触发器可以在特定操作执行之前或者之后执行。

数据库安全:

大多数DBMS给管理员提供了管理机制,利用管理机制授予或者限制对数据的访问。任何安全系统的基础都是用户授权和身份确认。一般来说需要保护的有:

  1. 对数据库管理功能的访问;
  2. 对特定数据库或者表的访问;
  3. 访问的类型;
  4. 仅仅通过视图或者存储过程对表进行访问;
  5. 创建多层次的安全措施,从而允许多种基于登录的访问和控制;
  6. 限制管理用户账号的能力。

安全性使用SQL的GRANT和REVOKE来管理。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mo@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值