coolcfan
[翻译] Java字符串连接性能内幕
展开Biu

本帖最后由 coolcfan 于 2012-6-21 13:06 编辑

说明:这篇是我的经理在公司博客上发表的文章,原文为英文,我来翻译一下。

作者:Liferay中国公司的核心软件开发工程师,Liferay Portal性能优化负责人,我的上司>.<

摘要:如何写程序能够让字符串拼接过程中,产生的垃圾更少,以便改善程序的GC性能;并介绍了自行实现的StringBundler类——在实际的环境中,它明显地改善了我们产品的GC性能。

【原文地址】

【第一部分:分析JDK提供的字符串连接方法】

Java语言中的String是不可改变的。

这是Java安全性以及线程安全的基石。如果字符串可以任意修改,Java将变得非常脆弱。

更高的安全性往往意味着更低的性能,Java字符串的这种特性使得每次“修改”字符串都变成“新建”字符串,而这一过程意味着原先的字符串对象被丢弃,成为“垃圾”。虽然在Java的GC机制(自动的垃圾收集和清理)的帮助下,程序员可以不必担心那些字符串垃圾会在内存中越积越多,但如果抱持着“反正有GC机制,我怎么写程序都不重要”的想法去编程,那么你的程序将因为GC过多而不堪重负。

JDK的开发者并不会忽视这一点——他们为JDK加入了StringBuffer(Since 1.0)和StringBuilder(Since 1.5)——统称SB类。这两个类所做的事情其实没什么区别,只不过后者本身不是线程安全的。但实际上,大部分字符串操作都是在一个线程内执行,并不涉及线程间的数据同步。所以,JDK的建议是,当你需要连接字符串的时候,使用两个SB类;当你的字符串连接操作发生在一个线程以内的时候,使用StringBuilder。根据这条建议,SB类应该比String.concat()方法更为高效;但现实世界总是复杂的,单纯使用SB类并不一定是最为高效的!下面我们就来深入讨论字符串连接的性能内幕。

首先,来看看这样一个说法:有些人说,『SB类一定比String.concat()更为高效』;但这是错误的!某些场合下,后者比前者更好!

比如,连接下面两个字符串:

[mw_shl_code=java,true]String a = "abcdefghijklmnopq"; //length=17

String b = "abcdefghijklmnopqr"; //length=18[/mw_shl_code]

为了证明『SB类一定比String.concat()更为高效』是错误的,我们来分析一下使用不同方法连接这两个字符串的时候,产生垃圾的数量。这里所说的“垃圾”,并不考虑a和b这两个原始字符串,因为它并不是由我们的代码创建的(你可以认为他们是两个常量);同样,也不考虑String类的其余内部属性,而只考虑String的字符数组char[]的变化。

方法1:使用String.concat()

[mw_shl_code=java,true]String result = a.concat(b);[/mw_shl_code]

看上去非常的简单。在这个过程中究竟发生了什么呢?一起来看看JDK的实现:

[mw_shl_code=java,true]public String concat(String str) {

int otherLen = str.length();

if (otherLen == 0) {

return this;

}

char buf[] = new char[count + otherLen];

getChars(0, count, buf, 0);

str.getChars(0, otherLen, buf, count);

return new String(0, count + otherLen, buf);

}

String(int offset, int count, char value[]) {

this.value = value;

this.offset = offset;

this.count = count;

}[/mw_shl_code]

这段代码新建了一个char[],长度等于a的长度加上b的长度,然后将a和b的内容分别复制到新的char[]里面,最后用新的char[]新建了一个String。这里需要注意,它调用的构造方法直接将参数里的char value[]作为构建出的String对象的内部字符数组,并没有做任何复制保护,因此这个方法是包内可见的,否则String的不可改变性就会被打破(用这个方法建立String对象,然后修改传过去的字符数组)。

通过上面的分析可以看出,使用方法1的过程中,并没有产生任何的垃圾。

【中午更新】

方法2:使用StringBuilder.append()

[mw_shl_code=java,true]String result = new StringBuilder().append(a).append(b).toString();[/mw_shl_code]

这段代码看上去比使用String.concat()的要复杂得多,那么性能呢?(为了清晰)我们将整个过程分为四步来分析:new StringBuilder(),append(a),append(b)和toString()。

第一步,是new StringBuilder()。它的源代码如下:

[mw_shl_code=java,true]public StringBuilder() {

super(16); // super(16) calls AbstractStringBuilder(int capacity)

}

AbstractStringBuilder(int capacity) {

value = new char[capacity];

}[/mw_shl_code]

在这一步,我们建立了一个长度为16的char[],并没有产生垃圾。

第二步,append(a),代码如下:

[mw_shl_code=java,true]public StringBuilder append(String str) {

super.append(str);

return this;

}

public AbstractStringBuilder append(String str) {

if (str == null) str = "null";

int len = str.length();

if (len == 0) return this;

int newCount = count + len;

if (newCount > value.length)

expandCapacity(newCount);

str.getChars(0, len, value, count);

count = newCount;

return this;

}

void expandCapacity(int minimumCapacity) {

int newCapacity = (value.length + 1) * 2;

if (newCapacity < 0) {

newCapacity = Integer.MAX_VALUE;

} else if (minimumCapacity > newCapacity) {

newCapacity = minimumCapacity;

}

value = Arrays.copyOf(value, newCapacity);

}[/mw_shl_code]

这段代码首先保证内部数组的容量可以容纳append(str)中的str,于是它新建了一个长度为34(17*2)的char[],这样一来,建立SB对象时候建立的那个长度16的char[]就变成了垃圾。

第一个垃圾,长度16的char[]。

第三步,append(b)。

代码逻辑同上,为了保证内部数组能够容纳字符串,再次新建一个数组,长度为70((17+18)*2)的char[],这样一来,前面那个长度34的char[]又变成了垃圾。

第二个垃圾,长度34的char[]。

第四步,toString(),代码如下:

[mw_shl_code=java,true]public String toString() {

// Create a copy, don't share the array

return new String(value, 0, count);

}

public String(char value[], int offset, int count) {

if (offset < 0) {

throw new StringIndexOutOfBoundsException(offset);

}

if (count < 0) {

throw new StringIndexOutOfBoundsException(count);

}

// Note: offset or count might be near -1>>>1.

if (offset > value.length - count) {

throw new StringIndexOutOfBoundsException(offset + count);

}

this.offset = 0;

this.count = count;

this.value = Arrays.copyOfRange(value, offset, offset+count);

}[/mw_shl_code]

这里调用的String构造方法是public方法,因此它不会直接将value[]当作自己的内部字符数组使用,而是会复制来保证内部数组的不可修改性。于是,它会建立一个长度70的char[],将SB的内容复制到自己的char[]中。这时,SB的任务已经完成,之前的长度70的char[]也成为了垃圾。

所以在整个追加字符串的过程中,一共产生了三个垃圾对象,大小为16+34+70=120!Java默认使用Unicode-16,这意味着240字节的垃圾!

有一件事可以让SB变得好一些,就是将前面的代码改成

[mw_shl_code=java,true]String result = new StringBuilder(a.length() + b.length()).append(a).append(b).toString();[/mw_shl_code]

这时候SB的初始长度为35,可以直接容纳a和b,唯一的垃圾产生于toString(),也就是SB自身的长度35的char[]。仍然不大好,不是么?

与String.concat()比起来,SB产生了大量的垃圾(任何大于0的数和0比较都相当于无穷!),同时,SB过程中的栈调用也比String.concat()多得多。

如果进行更深入的研究,你就会发现,当需要连接的字符串数量小于4(不包括4)的时候,String.concat()要远好于SB。(感兴趣的可以自己来研究研究看)

那么是不是说,当我们要连接4个或者更多字符串的时候,用SB就OK了呢?

不一定!

SB固有的问题是,它使用一个可以“自增长”的内部数组char[]来追加字符串,而每次当要追加的字符串大于这个数组的剩余量的时候,它就会“自增长”——新建一个“更大”的char[]来存储字符,而原先的那个就成为了垃圾。所以,如果我们可以非常确定地告诉SB,我们要连接的字符串总共有多少字符,那么就可以避免绝大多数垃圾的产生。

但是要预测SB最终会有多大,谈何容易!!

【第一部分完;第二部分将在3楼更新】

[查看全文]
ApfelZaft
java中运用label跳转
展开Biu

goto是java的保留词,但java里并没有goto.

goto可以随心所欲地在代码里跳转,看似很方便,但带来的代码混乱成为其被人诟病的原因。

然而有些时候必要的goto可以带来很大的方便。所以java里虽然没有goto,但有label,和goto相同的机制。

配合break和continue可以让程序完成一定的跳转,主要是在循环嵌套里。

通常break,或者continue都只能在一个循环中,配合上label可以实现在几个嵌套的循环里跳动。当你需要以下跳出几个循环时显得非常有用。

但label的位置是有限制的,唯一能放label的地方就是循环语句外,而且其中不能有其他语句。

continue label跳转到目标label位置,重新进入跟在后面的循环。

而break label 则是从这个label后面的循环的“底部溜出去”(thinking in java 中的说法)也就是略过这个循环执行循环后面的语句。

示例代码(thinking in java )

[mw_shl_code=java,true]class GoTo{

public static void main(String[] args){

int i=0;

outer:

while(true){

inner:

for(;i<10;i++){

System.out.println("i = "+i);

if(i==2){

System.out.println("Continue");

continue;

}

if(i==3){

System.out.println("Break");

i++;

break;

}

if(i==7){

System.out.println("continue outer");

i++;

continue outer;

}

if(i==8){

System.out.println("break outer");

break outer;

}

for(int k=0;k<5;k++){

if(k==3){

System.out.println("continue inner");

continue inner;

}

}

}

}

}

}

[/mw_shl_code]

…嘛…增加代码灵活性还是不错的…

[查看全文]
懒RP
【推荐】SQL入门书
展开Biu

这是我在书城找到的一本SQL入门书——《SQL入门经典(第5版)》

出版社:人民电邮出版社 著 译 者:(美)Ryan Stephens 出版日期:2011-11-01

个人觉得里面讲的比较简单易懂,挺适合初学者的。有需要的话可以去书城借来看看。

内容简介:

《sql入门经典(第5版)》的作者都是数据库教学与应用的专家,有着丰富的经验。《sql入门经典(第5版)》详细介绍了sql语言的基本语法、基本概念,说明了各种sql实现与ansi标准之间的差别。书中包含了大量的范例,直观地说明了如何使用sql对数据进行处理。每章后面还有针对性很强的测验与练习,能够帮助读者更好地理解和掌握学习的内容。在最后的附录里还有关于安装mysql的详细介绍、书中用到的关键sql语句、测验和练习的答案。

《sql入门经典(第5版)》的内容层次清晰,针对性强,非常适合初学者作为入门教材。

书籍目录:

《sql入门经典(第5版)》

第一部分 sql概念综述

第1章 欢迎来到sql世界 3

1.1 sql定义及历史 3

1.1.1 什么是sql 4

1.1.2 什么是ansi sql 4

1.1.3 新标准:sql-2008 4

1.1.4 什么是数据库 5

1.1.5 关系型数据库 5

1.1.6 客户端/服务器技术 6

1.1.7 基于web的数据库系统 7

1.1.8 主流数据库厂商 7

1.2 sql会话 7

1.2.1 connect 8

1.2.2 disconnect和exit 8

1.3 sql命令的类型 8

1.3.1 定义数据库结构 8

1.3.2 操作数据 9

1.3.3 选择数据 9

1.3.4 数据控制语言 9

.1.3.5 数据管理命令 10

1.3.6 事务控制命令 10

1.4 本书使用的数据库 10

1.4.1 表命名标准 11

1.4.2 数据一瞥 11

1.4.3 表的构成 13

1.4.4 范例和练习 14

1.5 小结 14

1.6 问与答 14

1.7 实践 15

1.7.1 测验 15

1.7.2 练习 15

第二部分 建立数据库

第2章 定义数据结构 19

2.1 数据是什么 19

2.2 基本数据类型 19

2.2.1 定长字符串 20

2.2.2 变长字符串 21

2.2.3 大对象类型 21

2.2.4 数值类型 21

2.2.5 小数类型 22

2.2.6 整数 22

2.2.7 浮点数 23

2.2.8 日期和时间类型 23

2.2.9 直义字符串 23

2.2.10 null数据类型 24

2.2.11 布尔值 24

2.2.12 自定义类型 25

2.2.13 域 25

2.3 小结 25

2.4 问与答 26

2.5 实践 26

2.5.1 测验 26

2.5.2 练习 27

第3章 管理数据库对象 29

3.1 什么是数据库对象 29

3.2 什么是规划 29

3.3 表:数据的主要存储方式 31

3.3.1 列 31

3.3.2 行 31

3.3.3 create table语句 32

3.3.4 命名规范 33

3.3.5 alter table命令 34

3.3.6 从现有表新建另一个表 36

3.3.7 删除表 37

3.4 完整性约束 37

3.4.1 主键约束 38

3.4.2 唯一性约束 38

3.4.3 外键约束 39

3.4.4 not null约束 40

3.4.5 检查约束 40

3.4.6 去除约束 41

3.5 小结 41

3.6 问与答 41

3.7 实践 42

3.7.1 测验 42

3.7.2 练习 42

第4章 规格化过程 45

4.1 规格化数据库 45

4.1.1 原始数据库 45

4.1.2 数据库逻辑设计 46

4.1.3 规格形式 47

4.1.4 命名规范 49

4.1.5 规格化的优点 50

4.1.6 规格化的缺点 50

4.2 去规格化数据库 50

4.3 小结 51

4.4 问与答 51

4.5 实践 51

4.5.1 测验 52

4.5.2 练习 52

第5章 操作数据 53

5.1 数据操作概述 53

5.2 用新数据填充表 53

5.2.1 把数据插入到表 54

5.2.2 给表里指定列插入数据 55

5.2.3 从另一个表插入数据 56

5.2.4 插入null值 57

5.3 更新现有数据 58

5.3.1 更新一列的数据 58

5.3.2 更新一条或多记录里的多个字段 59

5.4 从表里删除数据 59

5.5 小结 60

5.6 问与答 60

5.7 实践 61

5.7.1 测验 61

5.7.2 练习 62

第6章 管理数据库事务 63

6.1 什么是事务 63

6.2 控制事务 63

6.2.1 commit命令 64

6.2.2 rollback命令 66

6.2.3 savepoint命令 67

6.2.4 rollback to savepoint命令 67

6.2.5 release savepoint命令 68

6.2.6 set transaction命令 68

6.3 事务控制与数据库性能 69

6.4 小结 69

6.5 问与答 69

6.6 实践 70

6.6.1 测验 70

6.6.2 练习 70

第三部分 从查询中获得有效的结果

第7章 数据库查询 73

7.1 什么是查询 73

7.2 select语句 73

7.2.1 select语句 74

7.2.2 from子句 75

7.2.3 where子句 76

7.2.4 order by子句 77

7.2.5 大小写敏感性 79

7.3 简单查询的范例 79

7.3.1 统计表里的记录数量 81

7.3.2 从另一个用户表里选择数据 81

7.3.3 使用字段别名 82

7.4 小结 82

7.5 问与答 83

7.6 实践 83

7.6.1 测验 83

7.6.2 练习 84

第8章 使用操作符对数据进行分类 85

8.1 什么是sql里的操作符 85

8.2 比较操作符 85

8.2.1 相等 86

8.2.2 不等于 86

8.2.3 小于和大于 87

8.2.4 比较操作符的组合 88

8.3 逻辑操作符 88

8.3.1 is null 89

8.3.2 between 89

8.3.3 in 90

8.3.4 like 90

8.3.5 exists 91

8.3.6 all、some和any操作符 92

8.4 连接操作符 93

8.4.1 and 93

8.4.2 or 94

8.5 求反操作符 95

8.5.1 不相等 96

8.5.2 not between 96

8.5.3 not in 97

8.5.4 not like 97

8.5.5 is not null 98

8.5.6 not exists 98

8.6 算术操作符 98

8.6.1 加法 99

8.6.2 减法 99

8.6.3 乘法 99

8.6.4 除法 100

8.6.5 算术操作符的组合 100

8.7 小结 101

8.8 问与答 101

8.9 实践 101

8.9.1 测验 102

8.9.2 练习 102

第9章 汇总查询得到的数据 104

9.1 什么是汇总函数 104

9.1.1 count函数 105

9.1.2 sum函数 107

9.1.3 avg函数 108

9.1.4 max函数 108

9.1.5 min函数 109

9.2 小结 110

9.3 问与答 110

9.4 实践 111

9.4.1 测验 111

9.4.2 练习 111

第10章 数据排序与分组 113

10.1 为什么要对数据进行分组 113

10.2 group by子句 114

10.2.1 分组函数 114

10.2.2 对选中的数据进行分组 114

10.2.3 创建分组和使用汇总函数 115

10.2.4 以整数代表字段名称 117

10.3 group by与order by 117

10.4 cube和rollup语句 119

10.5 having子句 121

10.6 小结 122

10.7 问与答 122

10.8 实践 123

10.8.1 测验 123

10.8.2 练习 123

第11章 调整数据的外观 125

11.1 ansi字符函数 125

11.2 常用字符函数 126

11.2.1 串接函数 126

11.2.2 translate函数 127

11.2.3 replace 128

11.2.4 upper 128

11.2.5 lower 129

11.2.6 substr 129

11.2.7 instr 130

11.2.8 ltrim 131

11.2.9 rtrim 131

11.2.10 decode 132

11.3 其他字符函数 132

11.3.1 length 132

11.3.2 ifnull(检查null值) 133

11.3.3 coalesce 133

11.3.4 lpad 134

11.3.5 rpad 134

11.3.6 ascii 135

11.4 算术函数 135

11.5 转换函数 136

11.5.1 字符串转换为数字 136

11.5.2 数字转换为字符串 137

11.6 字符函数的组合使用 137

11.7 小结 138

11.8 问与答 138

11.9 实践 139

11.9.1 测验 139

11.9.2 练习 139

第12章 日期和时间 141

12.1 日期是如何存储的 141

12.1.1 日期和时间的标准数据类型 141

12.1.2 datetime元素 142

12.1.3 不同实现的日期类型 142

12.2 日期函数 143

12.2.1 当前日期 143

12.2.2 时区 144

12.2.3 时间与日期相加 144

12.2.4 其他日期函数 146

12.3 日期转换 146

12.3.1 日期描述 147

12.3.2 日期转换为字符串 149

12.3.3 字符串转换为日期 149

12.4 小结 150

12.5 问与答 150

12.6 实践 150

12.6.1 测验 151

12.6.2 练习 151

第四部分 建立复杂的数据库查询

第13章 在查询里结合表 155

13.1 从多个表获取数据 155

13.2 结合的类型 156

13.2.1 结合条件的位置 156

13.2.2 等值结合 156

13.2.3 使用表的别名 157

13.2.4 不等值结合 158

13.2.5 外部结合 159

13.2.6 自结合 161

13.2.7 结合多个主键 162

13.3 需要考虑的事项 163

13.3.1 使用基表 163

13.3.2 笛卡尔积 164

13.4 小结 166

13.5 问与答 166

13.6 实践 167

13.6.1 测验 167

13.6.2 练习 167

第14章 使用子查询定义未确定数据 169

14.1 什么是子查询 169

14.1.1 子查询与select语句 170

14.1.2 子查询与insert语句 171

14.1.3 子查询与update语句 172

14.1.4 子查询与delete语句 173

14.2 嵌套的子查询 173

14.3 关联子查询 175

14.4 子查询的效率 176

14.5 小结 176

14.6 问与答 176

14.7 实践 177

14.7.1 测验 177

14.7.2 练习 178

第15章 组合多个查询 179

15.1 单查询与组合查询 179

15.2 组合查询操作符 180

15.2.1 union 180

15.2.2 union all 182

15.2.3 intersect 183

15.2.4 except 184

15.3 组合查询里使用order by 184

15.4 组合查询里使用group by 186

15.5 获取准确的数据 187

15.6 小结 187

15.7 问与答 187

15.8 实践 188

15.8.1 测验 188

15.8.2 练习 189

第五部分 sql性能调整

第16章 利用索引改善性能 193

16.1 什么是索引 193

16.2 索引是如何工作的 194

16.3 create index命令 194

16.4 索引的类型 195

16.4.1 单字段索引 195

16.4.2 唯一索引 195

16.4.3 组合索引 196

16.4.4 隐含索引 196

16.5 何时考虑使用索引 196

16.6 何时应该避免使用索引 197

16.7 修改索引 198

16.8 删除索引 198

16.9 小结 199

16.10 问与答 199

16.11 实践 199

16.11.1 测验 199

16.11.2 练习 200

第17章 改善数据库性能 201

17.1 什么是sql语句调整 201

17.2 数据库调整与sql语句调整 202

17.3 格式化sql语句 202

17.3.1 为提高可读性格式化sql语句 202

17.3.2 from子句里的表 204

17.3.3 结合条件的次序 204

17.3.4 最严格条件 205

17.4 全表扫描 206

17.5 其他性能考虑 207

17.5.1 使用like操作符和通配符 207

17.5.2 避免使用or操作符 208

17.5.3 避免使用having子句 208

17.5.4 避免大规模排序操作 209

17.5.5 使用存储过程 209

17.5.6 在批加载时关闭索引 209

17.6 基于成本的优化 210

17.7 性能工具 210

17.8 小结 210

17.9 问与答 211

17.10 实践 211

17.10.1 测验 211

17.10.2 练习 211

第六部分 使用sql管理用户和安全

第18章 管理数据库用户 215

18.1 数据库的用户管理 215

18.1.1 用户的类型 216

18.1.2 谁管理用户 216

18.1.3 用户在数据库里的位置 216

18.1.4 不同规划里的用户 217

18.2 管理过程 217

18.2.1 创建用户 217

18.2.2 创建规划 219

18.2.3 删除规划 220

18.2.4 调整用户 221

18.2.5 用户会话 222

18.2.6 禁止用户访问 222

18.3 数据库用户使用的工具 222

18.4 小结 223

18.5 问与答 223

18.6 实践 223

18.6.1 测验 224

18.6.2 练习 224

第19章 管理数据库安全 225

19.1 什么是数据库安全 225

19.2 什么是权限 226

19.2.1 系统权限 226

19.2.2 对象权限 227

19.2.3 谁负责授予和撤销权限 228

19.3 控制用户访问 228

19.3.1 grant命令 228

19.3.2 revoke命令 229

19.3.3 控制对单独字段的访问 230

19.3.4 数据库账户public 230

19.3.5 权限组 230

19.4 通过角色控制权限 231

19.4.1 create role语句 232

19.4.2 drop role语句 232

19.4.3 set role语句 232

19.5 小结 233

19.6 问与答 233

19.7 实践 233

19.7.1 测验 234

19.7.2 练习 234

第七部分 摘要数据结构

第20章 创建和使用视图及异名 237

20.1 什么是视图 237

20.1.1 使用视图来简化数据访问 238

20.1.2 使用视图作为一种安全形式 238

20.1.3 使用视图维护摘要数据 239

20.2 创建视图 239

20.2.1 从一个表创建视图 239

20.2.2 从多个表创建视图 241

20.2.3 从视图创建视图 241

20.3 with check option 242

20.4 从视图创建表 243

20.5 视图与order by子句 244

20.6 通过视图更新数据 244

20.7 删除视图 244

20.8 嵌套视图对性能的影响 245

20.9 什么是异名 245

20.9.1 创建异名 245

20.9.2 删除异名 246

20.10 小结 246

20.11 问与答 247

20.12 实践 247

20.12.1 测验 247

20.12.2 练习 247

第21章 使用系统目录 248

21.1 什么是系统目录 248

21.2 如何创建系统目录 249

21.3 系统目录里包含什么内容 249

21.3.1 用户数据 250

21.3.2 安全信息 250

21.3.3 数据库设计信息 250

21.3.4 性能统计 250

21.4 不同实现里的系统目录表格 250

21.5 查询系统目录 251

21.6 更新系统目录对象 253

21.7 小结 253

21.8 问与答 253

21.9 实践 254

21.9.1 测验 254

21.9.2 练习 254

第八部分 在实际工作中应用sql知识

第22章 高级sql主题 257

22.1 光标 257

22.1.1 打开光标 258

22.1.2 从光标获取数据 258

22.1.3 关闭光标 260

22.2 存储过程和函数 260

22.3 触发器 262

22.3.1 create trigger语句 262

22.3.2 drop trigger语句 263

22.3.3 for each row语句 264

22.4 动态sql 264

22.5 调用级接口 264

22.6 使用sql生成sql 265

22.7 直接sql与嵌入sql 265

22.8 窗口表格函数 266

22.9 使用xml 266

22.10 小结 267

22.11 问与答 267

22.12 实践 267

22.12.1 测验 267

22.12.2 练习 268

第23章 sql扩展到企业、互联网和内部网 269

23.1 sql与企业 269

23.1.1 后台程序 269

23.1.2 前台程序 270

23.2 访问远程数据库 270

23.2.1 odbc 271

23.2.2 jdbc 271

23.2.3 ole db 271

23.2.4 厂商连接产品 272

23.2.5 通过web接口访问远程数据库 272

23.3 sql与互联网 273

23.3.1 让数据可以被全世界的顾客使用 273

23.3.2 向雇员和授权顾客提供数据 273

23.4 sql与内部网 273

23.5 小结 274

23.6 问与答 274

23.7 实践 275

23.7.1 测验 275

23.7.2 练习 275

第24章 标准sql的扩展 276

24.1 各种实现 276

24.1.1 不同实现之间的区别 276

24.1.2 遵循ansi sql 277

24.1.3 sql的扩展 278

24.2 扩展范例 278

24.2.1 transact-sql 279

24.2.2 pl/sql 279

24.2.3 mysql 280

24.3 交互sql语句 280

24.4 小结 281

24.5 问与答 281

24.6 实践 282

24.6.1 测验 282

24.6.2 练习 282

第九部分 附录

附录a 常用sql命令 285

a.1 sql语句 285

a.2 sql子句 288

附录b 使用数据库进行练习 290

b.1 在windows操作系统中安装mysql的指令 290

b.2 在windows操作系统中安装oracle的指令 292

b.3 在windows操作系统中安装microsoft sql server的指令 293

附录c 测验和练习的答案 295

附录d 本书范例的create table语句 333

d.1 mysql 333

d.2 oracle和sql server 334

附录e 书中范例所涉数据的insert语句 336

e.1 mysql和sql server 336

e.1.1 employee_tbl 336

e.1.2 employee_pay_tbl 336

e.1.3 customer_tbl 337

e.1.4 orders_tbl 338

e.1.5 products_tbl 338

e.2 oracle 339

e.2.1 employee_tbl 339

e.2.2 employee_pay_tbl 339

e.2.3 customer_tbl 340

e.2.4 orders_tbl 341

e.2.5 products_tbl 341

附录f 额外练习 342

术语表 347

[查看全文]
氺菓
在linux下你看到端口被占用很烦恼吧!
展开Biu

本内容已隐藏,回复后刷新可见哦

[查看全文]
软软的上嘴唇
SQL Server数据库开发中的十大问题
展开Biu

在SQL Server中进行开发会让你身处险地,并且寻找快速解决方案。我们编辑了前十名关于SQL Server开发的常见问题。对常见的针对表和字段的名字约束进行探究。学习如何解决并发问题,并且在不了解T-SQL的情况下编写存储过程。

查看这些解决方案的快速参考,并且了解更多内容。

在SQL Server开发问题中你可能会问到的十个问题:

1、什么是常见的对表和字段的名字约束?

2、有没有可能在不了解T-SQL的情况下编写存储过程

3、T-SQL 中如何比较CLR 存储过程和函数的性能?

4、我如何在一个存储过程中使用另一个存储过程产生的结果?

5、我如何解决SQL Server 2005的并发问题?

6、在SQL Server 2005中用什么工具替代了查询分析器?

7、你能提供一些有关SQL 和T-SQL的详细信息吗?

8、SQL Server 2005 有没有新的索引类型?

9、我如何创建一个脚本在表中进行选择?

10、我如何列出那些没有记录的数据库表?

对于表和字段的常见名字约束

专家回答:

SQL Server 2000下的表和字段名称有1到128字节的限制,并且遵循用于标识的规则。第一个字母必须是如下的一种:

Unicode Standard 2.0中规定的字母。

Unicode对字母的定义包括:拉丁字母,从A到Z,除了来自其他语言的字母之外。

下划线(_),at符号(@),或者数字符号(#)

在SQL Server中以这些符号作为标识符的开始具有特殊的含义。一个以at符号(@)开头的标识符表示一个本地的变量或者参数。一个以数字符号(#)开头的标识符代表一个临时表或者过程。一个以两个数字符号(##)开头的标识符标识的是一个全局临时对象。一些Transact-SQL函数的名字以两个at符号(@@)开头。为了避免与这些函数混淆,推荐你不要使用两个at符号(@@)开头的标识符。接下来的字母可以是以下的任意几种:

Unicode Standard 2.0定义的字母

来自基础拉丁文或者其他语音的十进制数字

at符号(@),美元符号($),数字符号(#),或者下划线

标识符绝对不能是Transact-SQL的保留字。SQL Server保留了一些大写和小写的保留字。内建的空间或者特殊的字母都不允许出现,尽管你可以在好的老版本的Northwind中看到它们包含了内建的空间。你必须通过把它们括在括号中才可以访问。

不具有任何T-SQL知识的情况下编写SQL Server2005存储过程吗?

作为过去几年里面微软试图用SQL Server 2005的.net集成来称霸市场的野心的结果,许多程序员都认为创建SQL Server存储过程不再必需T-SQL了。不幸的是(或者并非如此,这根据你的观点),这并不全是事实。在技术上是可以在不了解T-SQL的情况下创建存储过程的,但是没有T-SQL的话则无法访问任何的数据。

在CLR存储过程内部进行数据访问,是通过使用标准的ADO.NET类来完成的。开发人员会在应用程序层发现很多同样的没有用处的数据访问代码,这些代码会很轻易地转移到SQLCLR例程中去。当中间层的这些ADO.NET类需要使用T-SQL来访问数据的时候,在 CLR主机提供的环境中就会使用同样的类。

我要强调的是,从技术角度来说,不使用T-SQL来编写存储过程是可能的。那么有没有理由这么做呢?一种情况就是这是一个用来从普通文件或者网络服务中检索数据的CLR存储过程,并将数据格式设置为行集。这里可能就会用到不需要T-SQL的操作——但是这并不是对T -SQL存储过程能力的一个很好的比喻。

CLR存储过程vs. T-SQL存储过程

CLR存储过程和函数与T-SQL存储过程和函数相比,性能如何?

专家回答:

这里是用来比较T-SQL例程和CLR例程性能的一种常用的规则:用你的数据,在你的服务器上,测试两套配置,看看哪一个比较好。 就是说,许多人都运行过性能测试,一般的结果就是T-SQL在标准的CRUD(创建、读取、更新、删除)操作上表现要比好一点,而在复杂数学、字符串赋值和其他的超过数据访问的任务上,则是CLR的性能表现更好一点。 SQL Server 的专家Gustavo Larriera编辑了如下一些关于这个主题的有用链接:

在 SQL Server 2005中使用CLR Integration。

简单介绍在 SQL Server 2005中的 CLR Integration。

在 SQL Server 2005中对CLR 和T-SQL做出选择。

介绍 SQL Server 2005中的 CLR Integration。

SQL Server 闲谈: SQL Server 2005 Beta 2 CLR问题与回答。

数据库管理员的防御.NET。 ·用户自定义函数的性能比较。

如何在一个存储过程中使用另一个存储过程的结果

专家回答:

只要存储过程只产生了一个单个的结果,要在另外一个存储过程中使用这个存储过程产生的输出,这个技术是非常直接的。这个技术就是使用一个临时表来装载存储过程的巨额iguo,然后通过INSERT EXEC语句来执行这个过程并保存结果。一旦结果保留在临时表中了,他们就可以像使用其它表数据一样来使用它了。 这里是我们可能会复用的一个过程例子:

CREATE PROC usp_Demo_AllAuthors as

select * from pubs..authors

GO

[查看全文]
软软的上嘴唇
SQL 视图 局部变量 全局变量 条件语句 事务 触发器
展开Biu

一.视图

--------------------------------------------------------------------------------

1.视图是一张虚拟表,他所存储的不是实际数据,而是查询语句,但我们可以对视图进行像数据表一样的操作。

2.为什么使用视图呢?我的理解是:1.在远程传输数据时,可以避免过长的查询字符,减少流量。2.他可以简化繁杂的多表嵌套查询语句。3.安全性,防止非法用户访问敏感数据,因为我们可以通过创建视图展示给用户,我们想要给他们查看的数据。

3.视图的创建

create view vw_city

as

select cityName from city --这个查询语句可以随便的写,如果是些多层次的嵌套查询语句的话,那么下面使用视图的简易性就突出了。应为只用一句简短的查询语句就能把原本繁杂的搞定 4.视图的查询

select * from vw_city5.由于视图是以查询语句的形式存储的,所以一般视图只用于查看数据,一般不对视图进行增删改。如果数据库中的表数据改变那么视图中的数据也会随之改变,因为视图就相当于查询语句。

--------------------------------------------------------------------------------

二.局部变量(使用便于写数据库方法,及存储过程等)

--------------------------------------------------------------------------------

1.局部变量的声明(一个@)

declare @n int --声明变量关键字为declare 然后@加变量名 后面是变量类型

declare @s varchar(36) 2.局部变量的赋值

set @s='f4'

set @n=@n+1 --变量的赋值有两种方法,一种是通过set,一种是select 如果变量不附初始值则默认为null,null参与计算的结果还是null,这一行的@n就等于null

select @n=age from students --如过变量通过select赋值,这里可能在表中查到很多age结果,这里只赋值查询出来的最后一个age结果,如果set使用这种方法会出错。

set @n=(select age from Students where ID='1')--亦可以这样给他赋值

--------------------------------------------------------------------------------

三.全局变量

--------------------------------------------------------------------------------

1.全局变量是系统自定义,维护的,我们不能修改全局变量的值。以@@开头。

2.全局变量一览

select APP_NAME ( ) as w --当前会话的应用程序

select @@ERROR --返回最后执行的 Transact-SQL 语句的错误代码(integer)(如果最后一条语句不出错,就一直是0)

select @@IDENTITY --返回最后插入的标识值

select USER_NAME() --返回用户数据库用户名

select @@CONNECTIONS --返回自上次SQL启动以来连接或试图连接的次数。

select GETDATE() --当前时间

select @@CPU_BUSY/100 --返回自上次启动SQL 以来 CPU 的工作时间,单位为毫秒

USE tempdb select @@DBTS as w --为当前数据库返回当前 timestamp 数据类型的值。这一 timestamp 值保证在数据库中是唯一的。

select @@IDLE as w --返回SQL自上次启动后闲置的时间,单位为毫秒

select @@IO_BUSY AS w --返回SQL自上次启动后用于执行输入和输出操作的时间,单位为毫秒

select @@LANGID AS w --返回当前所使用语言的本地语言标识符(ID)

select @@LANGUAGE AS w --返回当前使用的语言名

select @@LOCK_TIMEOUT as w --当前会话的当前锁超时设置,单位为毫秒。

select @@MAX_CONNECTIONS as w --返回SQL上允许的同时用户连接的最大数。返回的数不必为当前配置的数值

EXEC sp_configure --显示当前服务器的全局配置设置

select @@MAX_PRECISION as w --返回 decimal 和 numeric 数据类型所用的精度级别,即该服务器中当前设置的精度。默认最大精度38。

select @@OPTIONS as w --返回当前 SET 选项的信息。

select @@PACK_RECEIVED as w --返回SQL自启动后从网络上读取的输入数据包数目。

select @@PACK_SENT as w --返回SQ自上次启动后写到网络上的输出数据包数目。

select @@PACKET_ERRORS as w --返回自SQL启动后,在SQL连接上发生的网络数据包错误数。

select @@SERVERNAME as w --返回运行SQL服务器名称。

select @@SERVICENAME as w --返回SQL正在其下运行的注册表键名

select @@TIMETICKS as w --返回SQL服务器一刻度的微秒数

select @@TOTAL_ERRORS AS w --返回 SQL服务器自启动后,所遇到的磁盘读/写错误数。

select @@TOTAL_READ as w --返回 SQL服务器自启动后读取磁盘的次数。

select @@TOTAL_WRITE as w --返回SQL服务器自启动后写入磁盘的次数。

select @@TRANCOUNT as w --返回当前连接的活动事务数。

select @@VERSION as w --返回SQL服务器安装的日期、版本和处理器类型。

--------------------------------------------------------------------------------

四.条件语句

--------------------------------------------------------------------------------

1.条件语句

if(条件表达式)

begin

语句...

end

else

begin

语句...

end2.循环语句

while

begin

语句....

break/continue

end

--------------------------------------------------------------------------------

五.事务(去不了终点,回到原点)

--------------------------------------------------------------------------------

1.事务:如果你要一起执行多条语句,如果有一条失败你就可以让他们全部都撤销执行。

begin tran --开启一个事物

delete from city

select * from city ---这里查询没有数据,因为上一句删除了

rollback tran

select * from city --这里在查询,惊奇的发现,数据又恢复了,因为上一句rollback是 让这个事务回滚的效果,

begin tran --开启一个事物

delete from city

select * from city ---这里查询没有数据,因为上一句删除了

commit tran

select * from city --这里在查询,不好意思,数据真的没了,即便下边你在rollback数据也回不来了,因为commit执行了数据真的把数据删掉了2.事务小案例

---bank表为转账表,MeMoney字段为我的账余额,HeMoney为朋友的账户余额,这个事务完成的是我给朋友转账

begin tran

declare @ersum int --定义这个局部变量为了记载这个事务过程中是否会出错,如果出错则最终将得不到为0的值,也就完成了我们判断这个事务是否出错过

set @ersum=0

update bank set MeMoney=MeMoney-1000 where ID=me ---从我卡里扣掉1000

set @ersum=@ersum+@@ERROR --如果不出错这里还是0,如果错了,这里将不是0

update bank set HeMoney=HeMoney+100 where ID=he ---给我朋友卡里加上1000

set @ersum=@ersum+@@ERROR --如果这里的结果是0将表明没有出错

if(@ersum<>0) --true有错,false没错

begin

rollback tran ---回滚事务

end

else

begin

commit tran --执行事务end

--------------------------------------------------------------------------------

六.触发器

--------------------------------------------------------------------------------

1.触发器,当数据库中的表有所改动(添删改)是会触发一中事件,这样一种机制,就是触发器。

2.触发器种类:after跟for一样,是语句执行完毕后触发事件。instead of :本来你要执行一种操作,结果执行了另外一种操作,原本要执行的操作被替换。

3.触发器的创建

create trigger 触发器名 on 操作表(实际要操作的表)

for|after|instead of --选其任意一种类型,其中for跟after是一样的

update|delete|insert --原本要执行哪一种动作

as

sql语句..... ---你想要执行的sql语句4.触发器的小案例

--这个例子是,删除Tb1里面的数据,把删除的数据同时备份到Tb1Bak表中

create trigger tri_bak on Tb1 --声明一个tri_bak ,如果Tb1表中的数据变化触发这个触发器

after delete ---删除完成后执行下面的操作

as

insert into Tb1Bak select * from deleted ---这里的deleted是系统自动生成的表,存放为上一次的数据库表中删除的数据。

5.小知识点:数据更新插入删除的过程为,插入数据库表的同时,也插入了系统表的insert表,删除的同时把删除的这条数据插入到了deleted表中,跟新的同时,deleted表中插入就数据,insert表中也添加了新数据。 我这里的insert 、deleted表都为系统自动生成的,不是我们操作的表。

[查看全文]
软软的上嘴唇
数据库设计词汇对照表
展开Biu

1. Access method(访问方法):此步骤包括从文件中存储和检索记录。

2. Alias(别名):某属性的另一个名字。在SQL中,可以用别名替换表名。

3. Alternate keys(备用键,ER/关系模型):在实体/表中没有被选为主健的候选键。

4. Anomalies(异常)参见更新异常(update anomalies)

5. Application design(应用程序设计):数据库应用程序生命周期的一个阶段,包括设计用户界面以及使用和处理数据库的应用程序。

6. Attribute(属性)(关系模型):属性是关系中命名的列。

7. Attribute(属性)(ER模型):实体或关系中的一个性质。

8. Attribute inheritance(属性继承):子类成员可以拥有其特有的属性,并且继承那些与超类有关的属性的过程。

9. Base table(基本表):一个命名的表,其记录物理的存储在数据库中。

10. Binary relationship(二元关系):一个ER术语,用于描述两个实体间的关系。例如,panch Has Staff。

11. Bottom-up approach(自底向上方法):用于数据库设计,一种设计方法学,他从标识每个设计组建开始,然后将这些组件聚合成一个大的单元。在数据库设计中,可以从表示属性开始底层设计,然后将这些属性组合在一起构成代表实体和关系的表。

12. Business rules(业务规则):由用户或数据库的管理者指定的附加规则。

13. Candidate key(候选键,ER关系模型):仅包含唯一标识实体所必须得最小数量的属性/列的超键。

14. Cardinality(基数):描述每个参与实体的可能的关系数目。

15. Centralized approach(集中化方法,用于数据库设计):将每个用户试图的需求合并成新数据库应用程序的一个需求集合

16. Chasm trap(深坑陷阱):假设实体间存在一根,但某些实体间不存在通路。

17. Client(客户端):向一个或多个服务器请求服务的软件应用程序。

18. Clustering field(群集字段):记录总的任何用于群集(集合)航记录的非键字段,这些行在这个字段上有相同的值。

19. Clustering index(群集索引):在文件的群集字段上定义的索引。一个文件最多有一个主索引或一个群集索引。

20. Column(列):参加属性(attribute)。

21. Complex relationship(复杂关系):度数大于2的关系。

22. Composite attribute(复合属性):由多个简单组件组成的属性。

23. Composite key(复合键):包含多个列的主健。

24. Concurrency control(并发控制):在多用户环境下同时执行多个十五并保证数据完整性的一个DBMS服务。

25. Constraint(约束):数据库不允许包含错误数据的一致性规则。

26. Data conversion and loading(数据转换和加载):数据库应用生命周期重的一个阶段,包括转换现有数据到新数据库中以及酱下耨应用程序转换到新的数据库上运行。

27. Data dictionary(数据字典):参见系统目录(system catalog)。

28. Data independence(数据独立性):使用数据的应用程序的数据描述部分。这意味着,如果将新的数据结构添加到数据库中,或者数据库中现有的结构被修改了,那么使用此数据库的就会受到影响,除非应用程序不直接依赖于被修改的部分。

29. Data model(数据模型):描述数据、数据间关系以及数据的约束的概念的一个集成的集合。

30. Data redundancy(数据冗余):参见冗余数据(redundant data)。

31. Data security(数据安全):包括对数据库对象(如表和视图)的访问和使用以及用户可以在这些对象上实施的操作。

32. Database(数据库):是逻辑上相关的数据(以及这些数据的描述)的一个共享的集合,用于解决公司对信息的需求。

33. Database design(数据库设计):数据库应用生命周期中的一个阶段,包括创建一个支持公司的操作和目标的数据库的设计。

34. Database integrity(数据库完整性):指存储数据的正确定和一致性。完整性通常用约束来表达。

35. Database Management System,DBMS(数据库管理系统):一个能够让用户定义、创建和维护数据库并控制对数据库的访问的软件系统。

36. Database planning(数据库规划):能尽可能有效的实现数据库应用的各阶段的管理活动。

37. Database server(数据库服务器):同服务器。

38. DBMS engine(DBMS引擎):同服务器。

39. DBMS selection(DBMS选择):数据库应用生命周期中的一个阶段,包括选择一个合适的DBMS来支持数据库应用。

40. Degree of a relationship(关系的度):一个关系中参与的实体的个数。

41. Denormalization(反规范化):形式上,这个术语指的是对基本表结构的修改,这样新的表比原始的表的规范化程度要低。但也可以用此属于更宽泛地形容将两个表和并成一个新表的情形,而这个新表与原来的表具有相同的范式,但比原表包含更多的空值。

42. Derived attribute(派生属性):表示其值可以从一个相关属性和属性集的值派生得到的属性,这个属性在实体中不是必须的。

43. Design methodology(设计方法学):一种结构化的方法,它使用过程、工具和文档来支持和简化设计过程。

44. Disjoint constraint(无连接约束):描述子类的成员间的关系,并指明超类某个成员是否有可能成为一个或多个子类的成员。

45. Domain(域):一个或多个属性的取值范围。

46. Entity(实体):具有相同性质的对象的集合,它是由用户或公司标识并可独立存在的。

47. Entity integrity(实体完整性):在一个基本表中,主健列的值不能为空。

48. Entity occurrence(实体出现):实体中的一个唯一可标识的对象。

49. Entity-Relationship model(实体关系模型):公司的实体、属性和关系的详细逻辑表示。

50. Fact-finding(事实发现):使用诸如面谈和提问等技术收集关于系统的事实、需求和性能的形式化过程。

51. Fan trap(扇形陷阱):但从第三个实体扇出的两个实体有1:*关系时出现扇形陷阱,但这两个实体在他们之间应该有直接关系以提供必要的信息。

52. Field(字段):同元组(Tuple)。

53. File(文件):存储在副主存储器中的相关记录的一个命名集合。

54. File-based system(基于文件的系统):一个文件集合,用来管理(创建、插入、删除、更新和检索)一个或多个文件中的数据,并产生基于这些文件中的数据的应用(通常是报表)。

55. File organization(文件组织):当文件存储在磁盘上时,对文件中的记录的安排方式。

56. First normal form(1NF,第一范式):表中的每个列的交叉处以及记录包含切进包含一个值的表。

57. Foreign key(外健):一个表中的一个列或者多个列的集合,这些列匹配某些其他(也可能是同一个)表中的候选键。

58. 4GL, Fourth-Generation Language(第四代语言):一种非过程化语言,比如SQL,他只需要用户定义必须完成什么操作,4GL负责将所进行的操作翻译成如何实现这些操作。

59. Full functional dependency(完全函数依赖):一个列在功能上依赖于复合主健,但不依赖于主健的任何一个子集的条件。

60. Functional dependency(函数依赖):描述表中列之间的关系。

61. Generalization(泛化):通过标识实体间的公共特征使实体间差别最小化的过程。

62. Generalization hierarchy(泛化层次结构):同类型层次(type hierarchy)。

63. Global data model(全局数据模型):代表整个公司(和被模型化的公司的一部分)的数据模型。

64. Implementation(实现):数据库应用生命周期中的一个阶段,包括数据库和应用程序设计的物理实现。

65. Index(索引):一种允许DBMS将特定的记录更快的放置到文件中,从而加快对用户查询的响应的数据结构。

66. Infomation system(信息系统):能够在整个公司范围内收集、管理、控制和分发数据/信息的资源。

67. Inheritance(继承):参见属性继承(attribute inheritance)。

68. Integrity constaints(完整性约束):防止出现数据库中的数据不一致的约束。

69. IS-A hierarchy(IS-A层次结构):同类型层次结构(type hierarchy)。

70. Local logical data model(局部逻辑数据模型):代表特定用户视图或用户视图的组合的数据模型。

71. Logical database design(逻辑数据库设计):基于特定的数据模型构建公司的数据的模型的过程,但不依赖于特定的DBMS以及其他的物理条件。

72. Meta-data(元数据):关于数据的数据,参见系统目录(system catalog)。

73. Mision objective(使命目标):标识数据库必须支持的特定任务。

74. Mission statement(使命语句):定义数据库应用程序的主要目标。

75. Multiplicity(多样性):定义与某个相关实体的一次出现有关的实体的出现数目。

76. Multi-valued attribute(多值属性):为一个实体的出现保存多个值的属性。

77. Nonkey attribute/column(非键属性/列):不是键的一部分的属性/列。

78. Normal forms(范式):规范化过程的一个阶段。前三个范式分别为第一范式(1NF)、第二范式(2NF)、第三范式(3NF)。

79. Normalization(规范化):一种产生带有需要的特性的技术,这种特性能支持用户和公司的需求。

80. Null(空值):表示当前不知道或对于这条记录来说不可使用的一个列的值。

81. Operational maintenance(操作维护):数据库应用生命周期的一个阶段,包括监视和维护系统安装后的运行。

82. Participation constraint(参与约束,EER模型):确定超类中的每个出现是否必须作为子类的一个成员进行参与。

83. Participation constraint(参与约束,ER模型):确定是否所有或者仅仅是某些实体出现参与到关系中。

84. Physical database design(物理数据库设计):在二级存储上产生数据库实现的描述的过程,它描述基本表、文件的组织、用于获得有效访问的索引以及所有与完整性约束和安全性限制有关的说明。

85. Primary index(主索引):在文件的有序键字段上构建的索引。一个文件最多可以有一个主索引或一个群集索引。

86. Primary key(主健,ER模型):用来标识每个实体的出现的候选键。

87. Primary key(主健,关系模型):在一个表中用来标识记录唯一性的候选键。

88. Privileges(权限):允许用户在给定基本表和视图上执行的操作。

89. Prototyping(原型):数据库的应用程序生命周期的一个阶段,包括勾践数据库应用程序的工作模型。

90. Query-by-Example(QBE):一种用于关系型DBMS的非过程化的数据库语言。QBE是一个图形化的“点-按”查询数据库的方法。

91. RDBMS:关系型DBMS。

92. Record(记录):同元组(Tuple)。

93. Recovery control(恢复控制):当时百事,将数据库还原到正确状态的过程。

94. Rcursive relationship(递归关系):一种关系,挡同一个实体在不同的角色中参与多次时就会出现递归关系。例如Staff Supervises Staff。

95. redundant data(冗余数据):在多个表中存储的重复数据。

96. Referential integrity(参照完整性):如果一个表中存在外健,则外健值必须匹配主表中的某些记录的候选键的值。

97. Relation(关系):一个关系是一张表,它也有列和行。

98. Relational model(关系模型):以表(或关系)的形式表示数据的数据模型。

99. Relational database(关系数据库):规范化表的集合。

100. Relation(关系):实体间有意义的关系。

101. Relationship occurrence(关系出现):两个实体出现之间的唯一可标识的联系。

102. Requirements collection and analysis(需求收集于分析):数据库应用程序生命周期的一个阶段,包括收集和分析数据库应用程序所要支持的关于公司的信息,并使用这些信息来标识新的数据库应用需求。

103. Row(行):同元组(Tuple)。

104. Second normal form(第二范式):一个已经是第一范式的表,同时满足所有的非主健列只能从构成主健的全部列中获得。

105. Secondary index(二级索引):在数据文件的非有序字段上定义的索引。

106. Security(安全):指防止数据库被非授权的用户访问,包括有意的和无意的。RDBMS通常提供两种类型的安全:数据安全和系统安全。

107. Server(服务器):为发出请求的客户提供服务的软件应用程序。参见两层/三层客户端-服务器体系结构。

108. Simple attribute(简单属性):只有一个组件的属性。

109. Single-valued attribute(单值属性):对于一个实体出现只有一个值的属性。

110. Specialization(特化):通过标识用来区分实体间成员的特征来最大花实体间成员的差别的过程。

111. Specialization hierarchy(特化层次结构):同类型层次结构(Type hierarchy)。

112. SQL(Structured Query Language,结构化查询语言):一种用于RDBMS的非过程化数据库语言。换言之,你只需要指定你需要那些信息,而不需要指定如何得到这些信息。 SQL已经被国际标准化组织(ISO)标准化了,因此SQL是定义和操纵RDBMS的正式和实际上的标准语言。

113. Strong entity(强实体):一个不依赖于其他实体的主健的存在而存在的实体。

114. Subclass(子类):为(超类)实体中的某些出现并保持特定属性和关系并有不同角色的实体

115. Superclass(超类):为实体中的所有出现保存公共属性和关系的实体。可参见特化和泛化。

116. Superkey(超键,ER模型):一个属性或属性集,诶译的标识了每个实体地出现。

117. Superkey(超键,关系模型):一个列或者列集,唯一的标识了表中地一个记录。

118. System catalog(系统目录):保存关于数据库地结构、用户、应用程序等信息地数据。

119. System definition(系统定义):数据库应用声明周期重的一个阶段,包括定义数据库应用程序以及他的主要用户视图地范围和边界。

120. System security(系统安全):在系统级保护数据库地访问和使用,不如用户名和密码。

121. Table(表):同关系(relation)。

122. Ternary relationship(三元关系):三个实体间的关系。例如panch,staff和member之间的Registers关系。

123. Testing(测试):数据库应用生命周期的一个阶段,包括执行应用程序并有意地发现错误。

124. Third normal form,3NF(第三范式):一个已经是1NF和2NF的表,同时满足所有的非主健的列的值仅能从主健列得到,而不能从其他列得到。

125. 3GL, Third-Generation Language(第三代语言):一种过程化的语言,比如COBOL、C、C++,它需要用户(通常是程序员)指定必须要干什么事情以及如何干这些事情。

126. Three-tier client-server architecture(三层客户端-服务器体系结构):由处理用户界面的客户和处理业务逻辑的应用程序服务器以及数据处理曾组成,而数据库服务器是用来来运行DBMS的。

127. Top-down approach(自顶向下方法,用于数据库设计):一种设计方法,此种方法从定义系统的主要结构开始,然后将这些结构逐步细分成更小的单元。在数据库设计中,通过标识实体和数据间的关系开始这个顶层的步骤,然后逐步添加细节,比如你希望保存的关于实体和关系的信息(成为属性)以及在实体、关系和属性上的所有约束。

128. Transaction(事务):由用户和应用程序执行的一个动作或一系列动作,这些动作访问或修改数据库的内容。

129. Transaction Processing Monitor,TPM(事务处理监视器):控制数据在客户端和服务器键转换的程序,以便为联机事务处理(OLTP)提供一个一致的环境。

130. Transitive dependency(传递依赖):假设A、B、C是表中的列,如果B依赖于A(A-->B),并且C依赖于B(B-->C),则C通过B传递而依赖于A(假设A不依赖于B或C)。如果在主健上存在一个传递依赖,则此表就不是3NF的。必须从表中去掉传递依赖以达到3NF的要求。

131. Tuple(元组):关系中的一行记录。

132. Two-tier client-server architecture(两层客户端-服务器体系结构):由处理主要业务和数据处理逻辑以及与用户的接口的客户端应用程序和管理和控制数据库访问的服务器程序组成。

133. Type hierarchy(类型层次结构):一个是提以及它的子类和他们的超类,等等。

134. UML(Unified Modeling Language,统一建模语言):在20世纪80年代和90年代引入的诸多面向对象分析与设计方法重的一种较新的方法。

135. Update anomalies(更新异常):当用户视图更新一个包含冗余数据的标识可能引起的不一致。有三种类型的异常:插入、删除和更新。

136. User view(用户视图):从特定的作业(比如经理或管理者)角度或业务应用领域(比如市场、职员或库存控制)定义的数据库应用的需求。

137. View(视图):一个“虚拟底表”,它不实际存在数据库中,但他由DBMS从现有底它所涉及的基本表中产生。

138. View integration approach(视图综合法,用于数据库设计):每个用户视图的需求,用来构建代表用户试图底独立数据模型。在数据库设计阶段,结果数据库模型被合并成一个更大的模型。

[查看全文]
软软的上嘴唇
数据库设计原则
展开Biu

1. 原始单据与实体之间的关系

可以是一对一、一对多、多对多的关系。在一般情况下,它们是一对一的关系:即一张原始单据对应且只对应一个实体。

在特殊情况下,它们可能是一对多或多对一的关系,即一张原始单证对应多个实体,或多张原始单证对应一个实体。

这里的实体可以理解为基本表。明确这种对应关系后,对我们设计录入界面大有好处。

〖例1〗:一份员工履历资料,在人力资源信息系统中,就对应三个基本表:员工基本情况表、社会关系表、工作简历表。

这就是“一张原始单证对应多个实体”的典型例子。

2. 主键与外键

一般而言,一个实体不能既无主键又无外键。在E—R 图中, 处于叶子部位的实体, 可以定义主键,也可以不定义主键

(因为它无子孙), 但必须要有外键(因为它有父亲)。

主键与外键的设计,在全局数据库的设计中,占有重要地位。当全局数据库的设计完成以后,有个美国数据库设计专

家说:“键,到处都是键,除了键之外,什么也没有”,这就是他的数据库设计经验之谈,也反映了他对信息系统核

心(数据模型)的高度抽象思想。因为:主键是实体的高度抽象,主键与外键的配对,表示实体之间的连接。

3. 基本表的性质

  基本表与中间表、临时表不同,因为它具有如下四个特性:

(1) 原子性。基本表中的字段是不可再分解的。

(2) 原始性。基本表中的记录是原始数据(基础数据)的记录。

(3) 演绎性。由基本表与代码表中的数据,可以派生出所有的输出数据。

(4) 稳定性。基本表的结构是相对稳定的,表中的记录是要长期保存的。

理解基本表的性质后,在设计数据库时,就能将基本表与中间表、临时表区分开来。

4. 范式标准

  基本表及其字段之间的关系, 应尽量满足第三范式。但是,满足第三范式的数据库设计,往往不是最好的设计。

为了提高数据库的运行效率,常常需要降低范式标准:适当增加冗余,达到以空间换时间的目的。

〖例2〗:有一张存放商品的基本表,如表1所示。“金额”这个字段的存在,表明该表的设计不满足第三范式,

因为“金额”可以由“单价”乘以“数量”得到,说明“金额”是冗余字段。但是,增加“金额”这个冗余字段,

可以提高查询统计的速度,这就是以空间换时间的作法。

在Rose 2002中,规定列有两种类型:数据列和计算列。“金额”这样的列被称为“计算列”,而“单价”和

“数量”这样的列被称为“数据列”。

表1 商品表的表结构

商品名称 商品型号 单价 数量 金额

电视机 29吋 2,500 40 100,000

5. 通俗地理解三个范式

通俗地理解三个范式,对于数据库设计大有好处。在数据库设计中,为了更好地应用三个范式,就必须通俗地理解

三个范式(通俗地理解是够用的理解,并不是最科学最准确的理解):

第一范式:1NF是对属性的原子性约束,要求属性具有原子性,不可再分解;

第二范式:2NF是对记录的惟一性约束,要求记录有惟一标识,即实体的惟一性;

第三范式:3NF是对字段冗余性的约束,即任何字段不能由其他字段派生出来,它要求字段没有冗余。

没有冗余的数据库设计可以做到。但是,没有冗余的数据库未必是最好的数据库,有时为了提高运行效率,就必须降

低范式标准,适当保留冗余数据。具体做法是:在概念数据模型设计时遵守第三范式,降低范式标准的工作放到物理

数据模型设计时考虑。降低范式就是增加字段,允许冗余。

6. 要善于识别与正确处理多对多的关系

  若两个实体之间存在多对多的关系,则应消除这种关系。消除的办法是,在两者之间增加第三个实体。这样,原来一

个多对多的关系,现在变为两个一对多的关系。要将原来两个实体的属性合理地分配到三个实体中去。这里的第三个

实体,实质上是一个较复杂的关系,它对应一张基本表。一般来讲,数据库设计工具不能识别多对多的关系,但能处

理多对多的关系。

〖例3〗:在“图书馆信息系统”中,“图书”是一个实体,“读者”也是一个实体。这两个实体之间的关系,是一

个典型的多对多关系:一本图书在不同时间可以被多个读者借阅,一个读者又可以借多本图书。为此,要在二者之

间增加第三个实体,该实体取名为“借还书”,它的属性为:借还时间、借还标志(0表示借书,1表示还书),另外,

它还应该有两个外键(“图书”的主键,“读者”的主键),使它能与“图书”和“读者”连接。

7. 主键PK的取值方法

   PK是供程序员使用的表间连接工具,可以是一无物理意义的数字串, 由程序自动加1来实现。也可以是有物理意义

的字段名或字段名的组合。不过前者比后者好。当PK是字段名的组合时,建议字段的个数不要太多,多了不但索引

占用空间大,而且速度也慢。

8. 正确认识数据冗余

主键与外键在多表中的重复出现, 不属于数据冗余,这个概念必须清楚,事实上有许多人还不清楚。非键字段的重

复出现, 才是数据冗余!而且是一种低级冗余,即重复性的冗余。高级冗余不是字段的重复出现,而是字段的派生出现。

〖例4〗:商品中的“单价、数量、金额”三个字段,“金额”就是由“单价”乘以“数量”派生出来的,它就是冗余,

而且是一种高级冗余。冗余的目的是为了提高处理速度。只有低级冗余才会增加数据的不一致性,因为同一数据,可

能从不同时间、地点、角色上多次录入。因此,我们提倡高级冗余(派生性冗余),反对低级冗余(重复性冗余)。

9. E--R图没有标准答案

信息系统的E--R图没有标准答案,因为它的设计与画法不是惟一的,只要它覆盖了系统需求的业务范围和功能内容,

就是可行的。反之要修改E--R图。尽管它没有惟一的标准答案,并不意味着可以随意设计。好的E—R图的标准是:

结构清晰、关联简洁、实体个数适中、属性分配合理、没有低级冗余。

10 . 视图技术在数据库设计中很有用

  与基本表、代码表、中间表不同,视图是一种虚表,它依赖数据源的实表而存在。视图是供程序员使用数据库的

一个窗口,是基表数据综合的一种形式, 是数据处理的一种方法,是用户数据保密的一种手段。为了进行复杂处理、

提高运算速度和节省存储空间, 视图的定义深度一般不得超过三层。 若三层视图仍不够用, 则应在视图上定义临时表,

在临时表上再定义视图。这样反复交迭定义, 视图的深度就不受限制了。

对于某些与国家政治、经济、技术、军事和安全利益有关的信息系统,视图的作用更加重要。这些系统的基本表完

成物理设计之后,立即在基本表上建立第一层视图,这层视图的个数和结构,与基本表的个数和结构是完全相同。

并且规定,所有的程序员,一律只准在视图上操作。只有数据库管理员,带着多个人员共同掌握的“安全钥匙”,

才能直接在基本表上操作。请读者想想:这是为什么?

11. 中间表、报表和临时表

中间表是存放统计数据的表,它是为数据仓库、输出报表或查询结果而设计的,有时它没有主键与外键(数据仓

库除外)。临时表是程序员个人设计的,存放临时记录,为个人所用。基表和中间表由DBA维护,临时表由程序员

自己用程序自动维护。

12. 完整性约束表现在三个方面

  域的完整性:用Check来实现约束,在数据库设计工具中,对字段的取值范围进行定义时,有一个Check按钮,通

过它定义字段的值城。

参照完整性:用PK、FK、表级触发器来实现。

用户定义完整性:它是一些业务规则,用存储过程和触发器来实现。

13. 防止数据库设计打补丁的方法是“三少原则”

   (1) 一个数据库中表的个数越少越好。只有表的个数少了,才能说明系统的E--R图少而精,去掉了重复的多余的

实体,形成了对客观世界的高度抽象,进行了系统的数据集成,防止了打补丁式的设计;

(2) 一个表中组合主键的字段个数越少越好。因为主键的作用,一是建主键索引,二是做为子表的外键,所以组

合主键的字段个数少了,不仅节省了运行时间,而且节省了索引存储空间;

(3) 一个表中的字段个数越少越好。只有字段的个数少了,才能说明在系统中不存在数据重复,且很少有数据冗

余,更重要的是督促读者学会“列变行”,这样就防止了将子表中的字段拉入到主表中去,在主表中留下许

多空余的字段。所谓“列变行”,就是将主表中的一部分内容拉出去,另外单独建一个子表。这个方法很简

单,有的人就是不习惯、不采纳、不执行。

数据库设计的实用原则是:在数据冗余和处理速度之间找到合适的平衡点。“三少”是一个整体概念,综合观点,

不能孤立某一个原则。该原则是相对的,不是绝对的。“三多”原则肯定是错误的。试想:若覆盖系统同样的功

能,一百个实体(共一千个属性) 的E--R图,肯定比二百个实体(共二千个属性) 的E--R图,要好得多。

提倡“三少”原则,是叫读者学会利用数据库设计技术进行系统的数据集成。数据集成的步骤是将文件系统集成

为应用数据库,将应用数据库集成为主题数据库,将主题数据库集成为全局综合数据库。集成的程度越高,数据

共享性就越强,信息孤岛现象就越少,整个企业信息系统的全局E—R图中实体的个数、主键的个数、属性的个数

就会越少。

提倡“三少”原则的目的,是防止读者利用打补丁技术,不断地对数据库进行增删改,使企业数据库变成了随意

设计数据库表的“垃圾堆”,或数据库表的“大杂院”,最后造成数据库中的基本表、代码表、中间表、临时表

杂乱无章,不计其数,导致企事业单位的信息系统无法维护而瘫痪。

“三多”原则任何人都可以做到,该原则是“打补丁方法”设计数据库的歪理学说。“三少”原则是少而精的

原则,它要求有较高的数据库设计技巧与艺术,不是任何人都能做到的,因为该原则是杜绝用“打补丁方法”

设计数据库的理论依据。

14. 提高数据库运行效率的办法

在给定的系统硬件和系统软件条件下,提高数据库系统的运行效率的办法是:

(1) 在数据库物理设计时,降低范式,增加冗余, 少用触发器, 多用存储过程。

(2) 当计算非常复杂、而且记录条数非常巨大时(例如一千万条),复杂计算要先在数据库外面,以文件系统方

式用C++语言计算处理完成之后,最后才入库追加到表中去。这是电信计费系统设计的经验。

(3) 发现某个表的记录太多,例如超过一千万条,则要对该表进行水平分割。水平分割的做法是,以该表主键

PK的某个值为界线,将该表的记录水平分割为两个表。若发现某个表的字段太多,例如超过八十个,则

垂直分割该表,将原来的一个表分解为两个表。

(4) 对数据库管理系统DBMS进行系统优化,即优化各种系统参数,如缓冲区个数。

(5) 在使用面向数据的SQL语言进行程序设计时,尽量采取优化算法。

总之,要提高数据库的运行效率,必须从数据库系统级优化、数据库设计级优化、程序实现级优化,这三

个层次上同时下功夫。

上述十四个技巧,是许多人在大量的数据库分析与设计实践中,逐步总结出来的。对于这些经验的运用,读者不能生帮硬套,死记硬背,而要消化理解,实事求是,灵活掌握。并逐步做到:在应用中发展,在发展中应用。

[查看全文]