PostgreSQL实例参考

 

陈景峰(netkiller)

前言

经过三个月的努力《PostgreSQL 实用实例参考》正式版终于推出了。因为最近换了工作,新公司的工作也很忙所以文档进展很慢,从最初几十页写到现在200页的文档,每天写文档的时间越来越少,有时一周也就只写2页,甚至一周一字未对。

正式版推出了,然后就是不断的修正。可能这段时间《PostgreSQL 实用实例参考》更新会更慢些。因为我还有其它文档要写:《OpenLDAP 文档》、《PHP + Corba + Python文档》、《JBuilder + Weblogic + PostgreSQL 开发EJB》。。。。。

 

文档中所有例子,都是在工作总结出来的,如有错误请指正。本人爱写错别字(哈哈)如果你发现了有错字,请发邮件给我netkiller(at)9812(dot)net修正文档。

 

300页之后不再推出HTML格式的文档了,之后的文档以PDFPSPostScript)格式为主,我是使用Microsoft Word写文档,处理300页的文档很困难,在保存文档或将doc文件转成其它格式的文件时经常会出现无响应。我也考虑过使用docbook / latex,或Page Maker。前者非所见即所得,要用户使用XML撰写,通过make一类的命令可以生成多种格式的文档,docbook也是UNIX手册的标准格式。后者Page Maker不用说了,Adobe出品,生成PDF更好些。

这是我第一次写一篇如此长的文档,没有经验,写的不好,不敢称为“书”,所以我叫它“文档”。

1.1    本文档的读者对象

文档面向有一定数据库基础用户。在这里我假设你对数据有一定认识,能够使用create创建数据与表,能够使用selectinsertupdate等语句操作数据库记录。

       不管是谁,我希望这本文档都能对你有所帮助。

1.2    本文档主要内容

第一章    主要介绍PostgreSQL

第二章    是开发中遇到的一些问题

 

附录中一些SQL脚本文件,可供用户参考。

1.3    怎样使用本文档

边看、边做、边试验,然后总结,多动脑。有问题先查查这本文档,如果文档中没有提到,再考虑其它方式,或与我联系。

作者简介

作者信息:

陈景峰,昵称:netkiller, UNIX like爱好者,研究方向群集系统、网络安全、数据仓库与数据挖掘、LDAPJ2EECorba,企业解决方案。

主页地址:

http://www.9812.net/

 

ICQ:101888222

Yahoo:snetkiller

AIM:xnetkiller

网易泡泡:openunix@163.com

E-Mail: openunix@163.com

 

有问题最好给我发Email或去下面的Newsgroup里讨论

news://news.cdut.edu.cn/cn.lang.java

news://news.cdut.edu.cn/cn.lang.python

 

Web Newsgroup:

http://202.103.190.130:8080/news

 

我常去的BBS

http://www.pgsqldb.org

http://www.chinaunix.com

http://www.linuxforum.net

 


目录

前言... 2

1.1          本文档的读者对象... 2

1.2          本文档主要内容... 2

1.3          怎样使用本文档... 3

作者简介... 3

目录... 5

第一章 PostgreSQL. 10

1     简介... 10

1.4          关于性能... 10

1.5          为什么说postgresql是最先进的开源数据库?... 10

1.6          PostgreSQLSQL99的支持... 11

2     PostgreSQL 数据库... 12

2.1          PostgreSQL分区... 12

2.2          RPM包安装... 13

2.3          APT 安装... 17

2.4          PostgreSQL 8.0 beta for windows版本安装... 19

2.4.1       运行pgAdmin III 20

2.4.2       psql控制台:... 20

2.4.3       ODBC. 21

2.4.4       Unix/Linux 登录到Windows. 23

2.4.5       Windows 登录到 Unix/Linux. 24

2.5          数据库备份方案... 24

2.5.1       备份数据库脚本... 24

2.5.2       下载备份脚本... 25

2.5.3       保证备份数据的安全-PGP/GPG加密... 26

2.6          备份计划... 41

2.6.1       服务器端计划... 41

2.6.2       客户端计划... 42

2.7          数据恢复... 42

2.8          性能提升... 43

2.8.1       共享内存... 43

2.8.2       最大连接... 44

2.8.3       vacuumdb. 50

2.8.4       数据库操作与性能... 50

2.8.5       硬件方面... 51

2.8.6       磁盘性能... 53

2.9          安全的TCP/IP联接... 56

2.9.1       使用SSL进行安全的TCP/IP联接... 56

2.9.2       使用SSH进行安全TCP/IP联接... 69

2.10        连接ipv6主机... 71

3     数据定义(DDL... 74

3.1          日期时间常量... 74

3.1.1       当前日期... 74

3.1.2       当前时间... 74

3.1.3       当前日期时间... 75

3.1.4       除去时区... 75

3.1.5       计算时间差... 75

3.1.6       计算时间和... 76

3.1.7       date_part 76

3.2          汉字做字段名... 77

3.3          “::”数据转换... 79

3.3.1       text to varchar 79

3.4          序列... 81

3.4.1       等差列... 81

3.4.2       “123456789…”. 82

3.4.3       “13579…”. 83

3.4.4       “246810…”. 84

3.4.5       n1+n2 85

3.5          约束... 85

3.6          检查约束... 85

3.7          非空约束... 87

3.8          唯一约束... 87

3.8.1       单字段约束... 87

3.8.2       多个字段组合约束... 87

3.8.3       唯一约束的注意事项... 89

3.9          主键/外键... 91

3.9.1       主键... 91

3.9.2       外键约束... 92

3.9.3       PostgreSQL 7.3.x 新增功能... 92

3.9.4       层次递归-分类目录... 93

3.9.5       总结... 101

3.10        模式... 101

3.10.1     创建模式... 101

3.10.2     删除模式... 101

3.10.3     模式搜索路径... 101

4     实体关系(Entity-Relation... 103

4.1          E-R图(Entity-Relation... 104

4.2          一对多关系... 105

4.3          多对多关系... 107

4.4          一对一关系... 109

4.5          引用完整性... 110

5     查询SQLDML... 111

5.1          子查询... 111

5.2          substring()函数截取部分汉字... 113

5.3          sum()使用技巧... 115

5.4          集合查询 (合并n个表)... 116

6     视图... 119

6.1          VIEW本使用实例... 119

6.2          使用HTML格式化VIEW的实例... 120

6.3          view中使用汉字做字段名... 124

6.4          取出字符如果超过20个在后尾加“…”... 125

6.5          视图中使用子查询... 126

7     过程与函数... 127

7.1          基本使用实例... 127

7.2          过程中使用Select Into. 128

7.3          返回integer 130

7.4          返回void. 130

7.5          返回结果集record. 131

7.6          例子... 132

7.7          shell 过程语言... 133

8     规则... 134

8.1          规则实例... 134

9     触发器... 137

9.1          一般用法... 137

9.2          多个触发器使用同一个过程... 137

9.3          时间调度触发器... 140

9.3.1       定时触发器... 141

9.3.2       周期触发器... 141

9.4          其它例子... 142

10           游标... 145

10.1        游标结果集... 146

10.2        例子... 147

11           事务处理... 148

11.1        批量插入、更新、删除... 148

11.1.1     批量插入操作-1. 148

11.2        保持数据完整-2. 149

12           用户权限... 150

12.1.1     ... 150

12.1.1.1    创建组... 150

12.1.1.2    删除组... 151

12.1.2     用户... 151

12.1.2.1    创建用户... 151

12.1.2.2    删除用户... 152

12.1.2.3    修改密码... 152

12.1.3     创建数据... 153

12.1.4     用户认证... 153

12.1.4.1    本地连接... 153

12.1.4.2    允许任何IP连接主机... 154

12.1.5     脚本例子... 154

12.1.6     权限... 155

13           其它技巧例子... 155

第二章 开发篇... 155

13.1        汉字编码问题... 155

13.2        JDBC. 155

13.2.1     Jsp/Java. 156

13.2.2     toChinese() 方法... 156

13.2.3     Unicode (UTF-8) 完全解决方案... 156

13.2.3.1   setCharacterEncoding() 方案... 156

13.2.3.2   Web.xml Filter过滤方案:... 159

13.2.3.3   Jdbc url charSet方案... 165

13.3        Tomcat JNDI Datasource 配置... 165

13.4        JDBC通过SSL安全连接数据库... 168

13.5        开发相关... 168

13.5.1     Create Java Entity Bean (not EJB CMP) 168

13.5.2     连接数据库... 169

13.5.3     处理SQL 语句... 180

13.5.4     处理HTML表格... 185

13.5.5     什么时候应该把文件存在数据库中... 213

14           PHP. 215

14.1        PHP 连接PostgreSQL. 215

14.2        set CLIENT_ENCODING TO 'GB18030';方案... 215

14.3        convert()方案... 225

14.4        PHP iconv() 函数方案... 225

14.5        在标准I/O上使用 Linux iconv 命令方案... 226

15           开发工具/开发环境... 231

15.1        Macromedia Dreamweaver MX 2004 JSP开发环境的配置... 231

15.2        Jcreator 240

15.3        Eclipse. 241

15.4        JBuilder + Weblogic + PostgreSQL开发环境... 242

15.5        GUI数据库管理与设计(建模)工具... 273

15.5.1     phpPgAdmin. 273

15.5.2     PgAdmin III 275

15.5.3     Case Studio 2. 276

15.5.4     PostgreSQL Manager 284

15.5.5     DeZign for Databases. 289

15.5.6     GUI工具比较... 291

16           FAQ.. 291

16.1        关于“”与null 291

16.2        Postgresql与其它数据库... 291

16.3        Putty. 294

16.3.1     Putty密钥认证... 294

16.3.2     中输入汉字的问题... 299

16.4        控制台下输入汉字... 303

16.5        PostgreSQL RPM 包安装后,为何没有5432端口... 303

16.6        PostgreSQL 7.4.2 rhel3(高级服务器版,俗称AS3) 306

16.7        Pureftpd pgsql认证模块... 306

16.8        Vsftpd pgsql认证... 306

16.9        OpenLDAP-PostgreSQL HOWTO.. 307

16.10      PostgreSQL 成功案例与解决方案... 307

17           附录... 307

17.1        实例... 307

17.2        实例... 315

17.3        安装脚本... 337

17.3.1     setenv.sh. 337

17.3.2     install.sh. 338

17.4        附件... 342

17.5        其它... 342

18           参考资料... 343

19           版本、声明... 343

 


 

第一章 PostgreSQL

PostgreSQL Wins Linux Journal Editors Choice Award
Posted on 2004-08-02
Posted by press at postgresql.org

PostgreSQL has won the 2004 Linux Journal Editors' Choice Award for the best DBMS!

Linux Journal's Editors' Choice Awards are well-known as the premiere forum recognizing outstanding product developments and achievements in the Linux market, and winners of the sixth annual awards are featured in the August 2004 issue of Linux Journal.

Check out
the full article.

1       简介

我接触PostgreSQL2000年,但项目中使用PostgreSQL2003年,2000当时应该是5.x6.x版本我并没有深入地研究这个数据库,还是主要使用MS Sql Server 7/2000 Oracle 8

因为很多企业难以支付MS Sql Server 7/2000 Oracle 8这笔费用,所以Free Database是最佳选择。但大多免费的数据库,功能有限、性能也差,跟本不能满足我们的需求。

1.4    关于性能

有一段时间里我们使用MySQL,实在不好用,功能太少,它只实现了SQL92 中不到30%的功能。除了selectinsertupdatedelete还有什么功能?一味强调速度快,真的是这样吗?MySQL数据量增加很大时,速度下划很快。

几万条记录时速度最快,几十万记录时速度不同了,几百万时就开始慢了。PostgreSQL 随着数据量增大时,速度变化差距不象MySQL那么大。

有些朋友在网上说(触发器、游标、外键、视图)影响性能。这里要说明一下如果适当的使用视图、子查询、触发器、游标……会让你开发更轻松。

注:关于游标,很多SQL书中这样写“游标就是指向一行的指针”在PostgreSQL有些不同,它是返回一个结果集,对结果集next 操作返回一行。

 

Phpbuilder上有一篇文章是写PostgreSQL MySQL 大家可以去看看。

1.5    为什么说postgresql是最先进的开源数据库?

1.         技术领先:
很多新技术都是它提出的
如:pl过程语言.在其它数据系统中都有自己的专用PL语言。而PostgreSQL中支持很多种PL语言(pl/tcl,pl/python,pl/perl,pl/php,pl/shell/pl/pgsql,pl/java.......
还有面象对象(ORDBMS)他实现的也很早.
他的数据类型支持很全.如几何型,数组...在其它RDBMS中是没有的.
总是有新的技术、思想加入其中

2.         在开源ORDBMSPostgreSQL功能最强.也最完善

1.6    PostgreSQLSQL99的支持

SQL-3/SQL99

PRIMARY KEY主键

FOREIGN KEY外键

Schema 模式

TOAST大对象

View视图

正则表达式

subquery子查询

TRIGGER触发器

RULE规则

FUNCTION过程/函数

CURSOR游标

PLSQL 过程语言

PL/pgSQL,PL/Tcl,PL/Perl,PL/Python,plPHP等等)

OLTP表的锁定、事务隔离

权限

√(用户、组)

Object对象支持

ORDBMS

 

 

其它:

连接

进程方式

SSL

群集(HA,数据同步复制。。。)

ODBC

JDBC

裸设备

目前不支持

下面是一些限制:

一行,一个表,一个库的最大尺寸是多少?

一个数据库最大尺寸?

无限制(存在 32TB 的数据库)

一个表的最大尺寸?

32TB

一行的最大尺寸?

1.6TB

一个字段的最大尺寸?

1GB

一个表里最大行数?

无限制

一个表里最大列数?

跟列类型有关,250-1600

一个表里的最大索引数量?

无限制

      

当然,实际上没有真正的无限制,还是要受可用磁盘空间、可用内存/交换区的制约。表的最大尺寸 32 TB 不需要操作系统对大文件的支持。大表用多个 1 GB 的文件存储,因此文件系统尺寸的限制是不重要的。如果缺省的块大小增长到 32K ,最大的表尺寸和最大列数可以增加。

这里引用http://www.pgsqldb.org/postgres-faq.html4.5详细请登录网站查看。

2       PostgreSQL 数据库

2.1    PostgreSQL分区

PostgreSQL 最好自己单独一个分区,如果你有两块硬盘建议你给它单独一块硬盘。

[chen@linux chen]$ df

Filesystem           1K-blocks      Used Available Use% Mounted on

/dev/sda9              1004024     99892    853128  11% /

/dev/sda1               101089      9498     86372  10% /boot

/dev/sda2            120952116   7648124 107159936   7% /home

none                    515400         0    515400   0% /dev/shm

/dev/sda10             2522048     33260   2360672   2% /tmp

/dev/sda7              5036284   2238244   2542208  47% /usr

/dev/sda6              5036284   1919140   2861312  41% /var

/dev/sda5             40313964     99444  38166636   1% /var/lib/pgsql

/dev/sda3             60476068    212532  57191508   1% /cvsroot

[chen@linux chen]$

 

[chen@linux chen]$ df -m

Filesystem           1M-blocks      Used Available Use% Mounted on

/dev/sda9                  980        98       833  11% /

/dev/sda1                   99        10        84  10% /boot

/dev/sda2               118117      7469    104648   7% /home

none                       503         0       503   0% /dev/shm

/dev/sda10                2463        33      2305   2% /tmp

/dev/sda7                 4918      2186      2482  47% /usr

/dev/sda6                 4918      1875      2794  41% /var

/dev/sda5                39369        98     37272   1% /var/lib/pgsql

/dev/sda3                59059       208     55851   1% /cvsroot

[chen@linux chen]$

2.2    RPM包安装

[root@linux software]# ls -1

postgresql-7.3.4-1PGDG.i386.rpm

postgresql-contrib-7.3.4-1PGDG.i386.rpm

postgresql-debuginfo-7.3.4-1PGDG.i386.rpm

postgresql-devel-7.3.4-1PGDG.i386.rpm

postgresql-docs-7.3.4-1PGDG.i386.rpm

postgresql-jdbc-7.3.4-1PGDG.i386.rpm

postgresql-libs-7.3.4-1PGDG.i386.rpm

postgresql-pl-7.3.4-1PGDG.i386.rpm

postgresql-python-7.3.4-1PGDG.i386.rpm

postgresql-server-7.3.4-1PGDG.i386.rpm

postgresql-tcl-7.3.4-1PGDG.i386.rpm

postgresql-test-7.3.4-1PGDG.i386.rpm

[root@linux software]# rpm -Uvh --nodeps `ls -1`

Preparing...                ########################################### [100%]

   1:postgresql-test        ########################################### [  8%]

   2:postgresql             ########################################### [ 17%]

   3:postgresql-contrib     ########################################### [ 25%]

   4:postgresql-debuginfo   ########################################### [ 33%]

   5:postgresql-devel       ########################################### [ 42%]

   6:postgresql-docs        ########################################### [ 50%]

   7:postgresql-jdbc        ########################################### [ 58%]

   8:postgresql-libs        ########################################### [ 67%]

   9:postgresql-pl          ########################################### [ 75%]

  10:postgresql-python      ########################################### [ 83%]

  11:postgresql-server      ########################################### [ 92%]

  12:postgresql-tcl         ########################################### [100%]

[root@linux software]# rpm -qa|grep postgre

postgresql-devel-7.3.4-1PGDG

postgresql-7.3.4-1PGDG

postgresql-python-7.3.4-1PGDG

postgresql-contrib-7.3.4-1PGDG

postgresql-jdbc-7.3.4-1PGDG

postgresql-server-7.3.4-1PGDG

postgresql-debuginfo-7.3.4-1PGDG

postgresql-libs-7.3.4-1PGDG

postgresql-tcl-7.3.4-1PGDG

postgresql-test-7.3.4-1PGDG

postgresql-pl-7.3.4-1PGDG

postgresql-docs-7.3.4-1PGDG

[root@linux software]#

[root@linux software]# service postgresql start

Starting postgresql service:                               [  OK  ]

[root@linux software]# su postgres

bash-2.05b$ createdb

CREATE DATABASE

bash-2.05b$ psql

Welcome to psql 7.3.4, the PostgreSQL interactive terminal.

 

Type:  \copyright for distribution terms

       \h for help with SQL commands

       \? for help on internal slash commands

       \g or terminate with semicolon to execute query

       \q to quit

 

postgres=# \q

bash-2.05b$

bash-2.05b$ vi /var/lib/pgsql/data/postgresql.conf

#========================================================================

 

 

#

#       Connection Parameters

#

#tcpip_socket = false

tcpip_socket = true

#ssl = false

 

#max_connections = 32

max_connections = 128

#superuser_reserved_connections = 2

 

#port = 5432

#hostname_lookup = false

#show_source_port = false

 

#unix_socket_directory = ''

#unix_socket_group = ''

#unix_socket_permissions = 0777 # octal

 

#virtual_host = ''

 

#krb_server_keyfile = ''

 

 

#

#       Shared Memory Size

#

#shared_buffers = 64            # min max_connections*2 or 16, 8KB each

shared_buffers = 256            # min max_connections*2 or 16, 8KB each

#max_fsm_relations = 1000       # min 10, fsm is free space map, ~40 bytes

#max_fsm_pages = 10000          # min 1000, fsm is free space map, ~6 bytes

#max_locks_per_transaction = 64 # min 10

#wal_buffers = 8                # min 4, typically 8KB each

 

bash-2.05b$ vi /var/lib/pgsql/data/pg_hba.conf

host   all      all         127.0.0.1         255.255.255.255   md5

 

bash-2.05b$ psql

Welcome to psql 7.3.4, the PostgreSQL interactive terminal.

 

Type:  \copyright for distribution terms

       \h for help with SQL commands

       \? for help on internal slash commands

       \g or terminate with semicolon to execute query

       \q to quit

 

postgres=# CREATE USER netkiller WITH PASSWORD 'chen';

CREATE USER

postgres=# CREATE DATABASE netkiller WITH OWNER = netkiller TEMPLATE = template0 ENCODING = 'UNICODE';

CREATE DATABASE

postgres=# \du

              List of database users

 User name | User ID |         Attributes

-----------+---------+----------------------------

 netkiller |     100 |

 postgres  |       1 | superuser, create database

(2 rows)

 

postgres=# \l

         List of databases

   Name    |   Owner   | Encoding

-----------+-----------+-----------

 netkiller | netkiller | UNICODE

 postgres  | postgres  | SQL_ASCII

 template0 | postgres  | SQL_ASCII

 template1 | postgres  | SQL_ASCII

(4 rows)

 

postgres=# \q

bash-2.05b$

bash-2.05b$ createlang plpgsql netkiller

bash-2.05b$

 

bash-2.05b$ exit

exit

[root@linux software]#  service postgresql restart

                                                           [  OK  ]

Starting postgresql service:                               [  OK  ]

[root@linux software]#

[root@linux software]# psql -h127.0.0.1 -Unetkiller netkiller

Password:

Welcome to psql 7.3.4, the PostgreSQL interactive terminal.

 

Type:  \copyright for distribution terms

       \h for help with SQL commands

       \? for help on internal slash commands

       \g or terminate with semicolon to execute query

       \q to quit

 

netkiller=>

 

注意:

1.         程序安装我使用了一个小技巧。(我懒哈哈)rpm -Uvh --nodeps `ls -1`
安装一定要加—nodepsls -1 这里是减号,阿拉伯数字1,不是英文字母“l (L)

2.         postgres只能用于UNIX Domain Socket方式登陆(/tmp/.s.PGSQL.5432),不能在TCP/IP Socket模式下登陆。

[root@linux software]# ls -la /tmp

total 68

drwxrwxrwt   11 root     root         4096 Nov 11 16:29 .

drwxr-xr-x   22 root     root         4096 Nov  5 14:49 ..

srwx------    1 root     nobody          0 Nov  5 11:34 .fam_socket

drwxrwxrwt    2 xfs      xfs          4096 Nov  5 14:49 .font-unix

drwx------    2 root     root         4096 Nov  5 19:06 .gconfd

srw-rw-rw-    1 root     root            0 Nov  5 14:49 .gdm_socket

drwxrwxrwx    2 bin      bin          4096 Nov  5 14:49 .iroha_unix

drwx------    2 root     root         4096 Nov  5 19:14 kde-root

drwx------    2 root     root        16384 Nov  5 18:46 lost+found

drwxr-xr-x    2 root     root         4096 Nov  5 18:55 .mozilla

drwx------    2 root     root         4096 Nov  5 11:38 orbit-root

drwxr-xr-x    2 root     root         4096 Nov  5 19:14 .qt

-rw-------    1 root     root         1024 Nov  5 18:52 .rnd

srwxrwxrwx    1 postgres postgres        0 Nov 11 16:29 .s.PGSQL.5432

-rw-------    1 postgres postgres       26 Nov 11 16:29 .s.PGSQL.5432.lock

-r--r--r--    1 root     root           11 Nov  5 14:49 .X0-lock

drwxrwxrwt    2 root     root         4096 Nov  5 14:49 .X11-unix

[root@linux software]# file /tmp/.s.PGSQL.5432

/tmp/.s.PGSQL.5432: socket

使用file命令可以查看文件类型,所以/tmp/.s.PGSQL.5432显示类型为/tmp/.s.PGSQL.5432: socket

[root@linux software]# psql -h127.0.0.1 –Upostgres db会提示

Password:

psql: FATAL:  Password authentication failed for user "postgres"

[root@linux software]# psql -h127.0.0.1 -Upostgres netkiller

Password:

Password:

Password:

Password:

Password:

Password:

Password:

psql: FATAL:  Password authentication failed for user "postgres"

              解决方法是创建一个用户。

3.         登陆提示
[root@linux software]# psql -h127.0.0.1 -Unetkiller netkiller

psql: FATAL:  No pg_hba.conf entry for host 127.0.0.1, user netkiller, database netkiller

编辑/var/lib/pgsql/data/pg_hba.conf文件加入

host   all      all         127.0.0.1         255.255.255.255   md5

 

2.3    APT 安装

Apt Debian Linux安装风格

去下而网站可以找到APT软件包

http://www.rpmfind.net/

输入:apt 搜索即可

 

http://www.rpmfind.net/linux/rpm2html/search.php?query=apt

 

[root@linux root]# cd /usr/local/src/

[root@linux src]# wget ftp://194.199.20.114/linux/freshrpms/redhat/9/apt/apt-0.5.5cnc6-fr1.i386.rpm

[root@linux src]# rpm -ivh apt-0.5.5cnc6-fr1.i386.rpm

warning: apt-0.5.5cnc6-fr1.i386.rpm: V3 DSA signature: NOKEY, key ID e42d547b

Preparing...                ########################################### [100%]

   1:apt                    ########################################### [100%]

[root@linux src]# apt-get update

Get:1 http://ayo.freshrpms.net redhat/9/i386 release [1171B]

Fetched 1171B in 6s (170B/s)

Get:1 http://ayo.freshrpms.net redhat/9/i386/os pkglist [1357kB]

Get:2 http://ayo.freshrpms.net redhat/9/i386/os release [140B]

Get:3 http://ayo.freshrpms.net redhat/9/i386/updates pkglist [487kB]

Get:4 http://ayo.freshrpms.net redhat/9/i386/updates release [153B]

Get:5 http://ayo.freshrpms.net redhat/9/i386/freshrpms pkglist [151kB]

Get:6 http://ayo.freshrpms.net redhat/9/i386/freshrpms release [157B]

Fetched 1995kB in 2m41s (12.3kB/s)

Reading Package Lists... Done

Building Dependency Tree... Done

[root@linux src]#                                 

[root@linux src]# apt-get check

Reading Package Lists... Done

Building Dependency Tree... Done

You might want to run `apt-get -f install' to correct these.

The following packages have unmet dependencies:

  postgresql-python: Depends: mx but it is not installed

E: Unmet dependencies. Try using -f.

[root@linux src]#

[root@linux src]# apt-get -f install

Reading Package Lists... Done

Building Dependency Tree... Done

Correcting dependencies... Done

The following extra packages will be installed:

  mx

The following NEW packages will be installed:

  mx

0 packages upgraded, 1 newly installed, 0 removed and 146 not upgraded.

Need to get 609kB of archives.

After unpacking 2266kB of additional disk space will be used.

Do you want to continue? [Y/n]

Get:1 http://ayo.freshrpms.net redhat/9/i386/os mx 2.0.3-8 [609kB]

Fetched 609kB in 2m49s (3596B/s)

Executing RPM (-Uvh)...

Preparing...                ########################################### [100%]

   1:mx                     ########################################### [100%]

[root@linux src]#

[root@linux src]# apt-get install postgresql-server

 

如果是Debian Linux 系统直接

[root@linux src]# apt-get install postgresql-server

 

2.4    PostgreSQL 8.0 beta for windows版本安装

PostgreSQL 8.0 betawindows版本安装包下载地址:

http://laser.dyndns.zhengmai.net.cn/download/postgresql-8.0-beta1.msi

下载后双击postgresql开始安装,只下一步,下一步,即可。

 

配置D:\PostgreSQL\8.0-beta1\data\pg_hba.conf 文件,建议使用UltraEdit工具。

host    all         all         192.168.0.1       255.255.255.255   md5

 

 

注:我的环境是Windows XP SP2

启动PostgreSQL 8.0服务器:

Ø         开始à所有程序àPostgreSQL 8.0-beta1à Start service

停止PostgreSQL 8.0服务器:

Ø         开始à所有程序àPostgreSQL 8.0-beta1à Stop service

进入psql控制台:

Ø         开始à所有程序àPostgreSQL 8.0-beta1à psql to template1

2.4.1   运行pgAdmin III

Ø         开始à所有程序àPostgreSQL 8.0-beta1àpgAdmin III

 

pgAdmin III的一般操作顺序是:

1.         新建一个用户(用于tcp/ip socketPostgreSQL帐号,而非系统用户postgres是一个系统帐号,不能用于tcp/ip连接,它是用来管理数据的用户)

2.         新建一个表空间,用于存放数据

3.         新建一个数据库实例

4.         新建一个PL过程语言(一般是pl/pgsql

5.         新建一个模式(Schema)

6.         创建表,视图,触发器等等

 

2.4.2   psql控制台:

网上有很多朋友问我,PostgreSQL 8.0psql在那,他默认打开template1数据库,如何打开其它数据等等问题。

步骤,开始à所有程序àPostgreSQL 8.0-beta1à psql to template1进入PostgreSQL 8.0 psql控制台,输入postgres用户的密码登录。

使用“\l”列出数据

使用“\c”连接到其它数据库。
\c
数据库 数据库所有者,接提示输入密码即可。

 

Password:

Welcome to psql.exe 8.0.0beta1, the PostgreSQL interactive terminal.

 

Type:  \copyright for distribution terms

       \h for help with SQL commands

       \? for help with psql commands

       \g or terminate with semicolon to execute query

       \q to quit

 

template1=# \l

        List of databases

   Name    |  Owner   | Encoding

-----------+----------+----------

 netkiller | chen     | UNICODE

 template0 | postgres | UNICODE

 template1 | postgres | UNICODE

(3 rows)

 

template1=# \c netkiller chen

Password:

You are now connected to database "netkiller" as user "chen".

netkiller=#

 

2.4.3   ODBC

1.         开始à控制面板à管理工具à数据源 (ODBC)

2.         单击“添加”按钮

3.         列表中选择PostgreSQLà单击“完成”按钮

4.         单击Save保存

5.         单击“确定”按钮

2.4.4   Unix/Linux 登录到Windows

[root@linux root]# psql -h 192.168.0.254 -U chen netkiller

Password:

Welcome to psql 7.3.4, the PostgreSQL interactive terminal.

 

Type:  \copyright for distribution terms

       \h for help with SQL commands

       \? for help on internal slash commands

       \g or terminate with semicolon to execute query

       \q to quit

 

netkiller=#

2.4.5   Windows 登录到 Unix/Linux

D:\PostgreSQL\8.0-beta1\bin>psql.exe -h 192.168.0.1 -U netkiller netkiller

Password:

Welcome to psql.exe 8.0.0beta1, the PostgreSQL interactive terminal.

 

Type:  \copyright for distribution terms

       \h for help with SQL commands

       \? for help with psql commands

       \g or terminate with semicolon to execute query

       \q to quit

 

netkiller=>

 

2.5    数据库备份方案

2.5.1   备份数据库脚本

脚本功能是,首先备份数据库、然后打包、压缩为tar.gz、最后上传到指定位置并删除临时文件。

[root@linux root]# cat backup.sh

#!/bin/bash

 

FTPHOST=ftp.9812.net

USER=netkiller

PASSWD=xxx

 

echo "Starting Backup PostgreSQL ... "

#big5 gb2312 gb18030 …

export PGCLIENTENCODING=gb18030

su - postgres -c pg_dumpall > pgsql-backup.`date +%Y-%m-%d.%H:%M:%S`.dmp

tar zcvf pgsql-backup.`date +%Y-%m-%d`.tar.gz *.dmp

 

echo "Upload File ..."

ftp -n ${FTPHOST} <<!

user ${USER} ${PASSWD}

binary

prompt

mkdir backup

cd backup

mput *.tar.gz

close

bye

!

echo "Remove temp file ..."

rm -rf pgsql-backup.*.dmp

rm -rf pgsql-backup.????-??-??.tar.gz

[root@linux root]#

 

 

如果您没有一台专用于备份数据的机器(有静态IP的机器)。上面的备份脚本可更改为:

[root@linux root]# cat backup.sh

#!/bin/bash

 

echo "Starting Backup PostgreSQL ... "

su - postgres -c pg_dumpall > pgsql-backup.`date +%Y-%m-%d.%H:%M:%S`.dmp

tar zcvf pgsql-backup.`date +%Y-%m-%d`.tar.gz *.dmp

 

echo "Remove temp file ..."

rm -rf pgsql-backup.*.dmp

[root@linux root]#

2.5.2   下载备份脚本

 

[root@linux root]# cat getbackup.sh

#!/bin/bash

 

FTPHOST=ftp.9812.net

USER=netkiller

PASSWD=xxx

 

wget ftp://${USER}:${PASSWD}@${FTPHOST}/backup/*

 

ftp -n ${FTPHOST} <<!

user ${USER} ${PASSWD}

binary

prompt

cd backup

mdelete *

close

bye

!

[root@linux root]#

2.5.3   保证备份数据的安全-PGP/GPG加密

数据库中的内容有些是不能提供给用户的,如其它用户的资料,密码。在数据库中的数据,你可以通过权限来限制用户操作。将数据库备份(导出)到本地SQL文本文件中(xxxx.sql包括DDLDML) ,一但备份落入他手,后果不可设想,他很容易得用你的数据,因为你备份的数据是文本文件,没有任何加密措施。

这里介绍GnuPG 以下简称GPGGPGPGP兼容。由于PGP使用了许多专利算法,属于美国加密出口限制之列。而GnuPGGPL软件。

GPG使用非对称加密算法,安全程度很高。所谓非对称加密算法,就是每一个用户都拥有一对密钥:公钥和私钥。其中,私钥由用户保存,公钥提供给internet上的用户。

设:

       陈景峰的帐号:chen

       小明的帐号:ming

 

以下为chen 帐号的操作:

1.         查看当前文件夹

[chen@linux chen]$ ls -la

total 56

drwx------    4 chen     chen         4096 Dec 12 20:38 .

drwxr-xr-x    7 root     root         4096 Nov 12 11:47 ..

-rw-------    1 chen     chen         4953 Dec 10 14:05 .bash_history

-rw-r--r--    1 chen     chen           24 Feb 11  2003 .bash_logout

-rw-r--r--    1 chen     chen          191 Feb 11  2003 .bash_profile

-rw-r--r--    1 chen     chen          124 Feb 11  2003 .bashrc

-rw-r--r--    1 chen     chen         5531 Feb  4  2003 .canna

-rw-r--r--    1 chen     chen          847 Feb 20  2003 .emacs

-rw-r--r--    1 chen     chen          120 Feb 27  2003 .gtkrc

drwxr-xr-x    3 chen     chen         4096 Aug 12  2002 .kde

-rw-------    1 chen     chen          594 Dec 10 09:38 .viminfo

drwxr-xr-x    2 chen     chen         4096 Nov  5 19:16 .xemacs

[chen@linux chen]$

 

2.         生成密钥(公钥、私钥)

使用GPG之前必须生成密钥(公钥、私钥)操作步骤。
# gpg --gen-key

[chen@linux chen]$ gpg --gen-key

gpg (GnuPG) 1.2.1; Copyright (C) 2002 Free Software Foundation, Inc.

This program comes with ABSOLUTELY NO WARRANTY.

This is free software, and you are welcome to redistribute it

under certain conditions. See the file COPYING for details.

 

gpg: WARNING: using insecure memory!

gpg: please see http://www.gnupg.org/faq.html for more information

gpg: /home/chen/.gnupg: directory created

gpg: new configuration file `/home/chen/.gnupg/gpg.conf' created

gpg: keyblock resource `/home/chen/.gnupg/secring.gpg': file open error

gpg: keyring `/home/chen/.gnupg/pubring.gpg' created

Please select what kind of key you want:

   (1) DSA and ElGamal (default)

   (2) DSA (sign only)

   (5) RSA (sign only)

Your selection? 回车

DSA keypair will have 1024 bits.

About to generate a new ELG-E keypair.

              minimum keysize is  768 bits

              default keysize is 1024 bits

    highest suggested keysize is 2048 bits

What keysize do you want? (1024) 回车

Requested keysize is 1024 bits

Please specify how long the key should be valid.

         0 = key does not expire

      <n>  = key expires in n days

      <n>w = key expires in n weeks

      <n>m = key expires in n months

      <n>y = key expires in n years

Key is valid for? (0) 回车

Key does not expire at all

Is this correct (y/n)? y

 

You need a User-ID to identify your key; the software constructs the user id

from Real Name, Comment and Email Address in this form:

    "Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"

 

Real name: netkiller

Email address: openunix@163.com

Comment: 陈景峰的密钥  (注:输入中文终端要支持UTF-8

You are using the `utf-8' character set.

You selected this USER-ID:

    "netkiller (陈景峰的密钥) <openunix@163.com>"

 

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit?o

 

Enter passphrase:输入密钥口令

Repeat passphrase:输入密钥口令

You need a Passphrase to protect your secret key.

 

We need to generate a lot of random bytes. It is a good idea to perform

some other action (type on the keyboard, move the mouse, utilize the

disks) during the prime generation; this gives the random number

generator a better chance to gain enough entropy.

+++++++++++++++.+++++++++++++++.+++++++++++++++.+++++++++++++++.+++++++++++++++.++++++++++++++++++++++++++++++++++++++++.++++++++++++++++++++.....>+++++..................+++++

 

Not enough random bytes available.  Please do some other work to give

the OS a chance to collect more entropy! (Need 290 more bytes)

We need to generate a lot of random bytes. It is a good idea to perform

some other action (type on the keyboard, move the mouse, utilize the

disks) during the prime generation; this gives the random number

generator a better chance to gain enough entropy.

..+++++.+++++.++++++++++.+++++++++++++++.+++++++++++++++++++++++++..+++++++++++++++.++++++++++++++++++++.+++++.+++++++++++++++.+++++...++++++++++>+++++............................................................>+++++.............>.+++++.....<+++++............+++++^^^

gpg: /home/chen/.gnupg/trustdb.gpg: trustdb created

public and secret key created and signed.

key marked as ultimately trusted.

 

pub  1024D/B00847C5 2003-12-12 netkiller (陈景峰的密钥) <openunix@163.com>

     Key fingerprint = 0058 5847 7598 556F AAFD  81A5 AC07 C873 B008 47C5

sub  1024g/0B70F0CB 2003-12-12

 

[chen@linux chen]$

 

3.         查看生成密钥

[chen@linux chen]$ ls -la

total 52

drwx------    5 chen     chen         4096 Dec 12 20:47 .

drwxr-xr-x    7 root     root         4096 Dec 12 20:44 ..

-rw-r--r--    1 chen     chen           24 Dec 12 20:44 .bash_logout

-rw-r--r--    1 chen     chen          191 Dec 12 20:44 .bash_profile

-rw-r--r--    1 chen     chen          124 Dec 12 20:44 .bashrc

-rw-r--r--    1 chen     chen         5531 Dec 12 20:44 .canna

-rw-r--r--    1 chen     chen          847 Dec 12 20:44 .emacs

drwx------    2 chen     chen         4096 Dec 12 20:52 .gnupg

-rw-r--r--    1 chen     chen          120 Dec 12 20:44 .gtkrc

drwxr-xr-x    3 chen     chen         4096 Dec 12 20:44 .kde

-rw-------    1 chen     chen           61 Dec 12 20:45 .Xauthority

drwxr-xr-x    2 chen     chen         4096 Dec 12 20:44 .xemacs

[chen@linux chen]$ ls .gnupg/

gpg.conf  pubring.gpg  pubring.gpg~  random_seed  secring.gpg  trustdb.gpg

 

 

4.         证书的回收

当您的密钥(gpg --gen-key)生成之后,建议您立即做一个公钥回收证书,如果您忘记了您的私钥口令或者您的私钥丢失或者被盗,您可以发布这个证书来声明以前的公钥不再有效。

gpg --output revoke.asc --gen-revoke netkiller netkiller 你在生成密钥时输入的Real name:

gpg --output revoke.asc --gen-revoke openunix@163.com (使用邮件地址也可以)

[chen@linux chen]$ gpg --output revoke.asc --gen-revoke netkiller

gpg: WARNING: using insecure memory!

gpg: please see http://www.gnupg.org/faq.html for more information

 

sec  1024D/B00847C5 2003-12-12   netkiller (陈景峰的密钥) <openunix@163.com>

 

Create a revocation certificate for this key? y

Please select the reason for the revocation:

  0 = No reason specified

  1 = Key has been compromised

  2 = Key is superseded

  3 = Key is no longer used

  Q = Cancel

(Probably you want to select 1 here)

Your decision?

Enter an optional description; end it with an empty line:

> :( cancel

> 

Reason for revocation: Key has been compromised

:( cancel

Is this okay?

Please select the reason for the revocation:

  0 = No reason specified

  1 = Key has been compromised

  2 = Key is superseded

  3 = Key is no longer used

  Q = Cancel

(Probably you want to select 1 here)

Enter an optional description; end it with an empty line:

> :( cancel

> 

Is this okay? y

 

You need a passphrase to unlock the secret key for

user: "netkiller (陈景峰的密钥) <openunix@163.com>"

1024-bit DSA key, ID B00847C5, created 2003-12-12

 

ASCII armored output forced.

Revocation certificate created.

 

Please move it to a medium which you can hide away; if Mallory gets

access to this certificate he can use it to make your key unusable.

It is smart to print this certificate and store it away, just in case

your media become unreadable.  But have some caution:  The print system of

your machine might store the data and make it available to others!

[chen@linux chen]$ ls

revoke.asc

[chen@linux chen]$ cat revoke.asc

-----BEGIN PGP PUBLIC KEY BLOCK-----

Version: GnuPG v1.2.1 (GNU/Linux)

Comment: A revocation certificate should follow

 

iFIEIBECABIFAj/Zv08LHQI6KCBjYW5jZWwACgkQrAfIc7AIR8X3agCcDBjqRkFx

QUzcZ/1Gyf1/jjFis04An2rYQz2XrCode08Y78Fj63RVNKD9

=ovDh

-----END PGP PUBLIC KEY BLOCK-----

[chen@linux chen]$

 

5.         密钥列表

gpg --list-key

[chen@linux chen]$ gpg --list-key

gpg: WARNING: using insecure memory!

gpg: please see http://www.gnupg.org/faq.html for more information

/home/chen/.gnupg/pubring.gpg

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

pub  1024D/B00847C5 2003-12-12 netkiller (陈景峰的密钥) <openunix@163.com>

sub  1024g/0B70F0CB 2003-12-12

 

[chen@linux chen]$

 

6.         输出公钥

ASCII字符格式输出公钥:gpg --output netkiller.gpg --armor --export netkiller

以二进制格式输出公钥:gpg --output netkiller.gpg --export netkiller

下面是以ASCII字符格式输出(其实就是做了一下BASE64编码):

[chen@linux chen]$ gpg --output netkiller.gpg --armor --export netkiller

gpg: WARNING: using insecure memory!

gpg: please see http://www.gnupg.org/faq.html for more information

[chen@linux chen]$ ls

netkiller.gpg  revoke.asc

[chen@linux chen]$ cat netkiller.gpg

-----BEGIN PGP PUBLIC KEY BLOCK-----

Version: GnuPG v1.2.1 (GNU/Linux)

 

mQGiBD/ZuhgRBACBRuWYRtJ8+8VmnYUgNy7TS/nVl0sHrsGD2kgIWVUuZYgKSUoM

vT4MUHWdd52yesovAV61qsVCfUz+O76ovhQrUzv4jp+bkIOKcc7E07Z2MZmc1BqR

+Gavb3gsJM6DmOLcRiU0m3fqod1KCGFf8K6ZLQUhRJYWDI80KEgJqliG4wCgo2xn

5WS1CIGnvGDFUiGY6VhdamsD/jdiqSIcwFt2x6VMjzeWkHHM5wNYHuBJnp9DPd9g

rn3uEq+tSex8ZXRyzHGj+N4SKezhEYal1D762kDxjGYltk5Xce5dXQBn9fulEDhD

OzOp78GvIvJ/m33D/J6xECbXUz8XsFFhxJ6QnVh/RURY+EvHE1Tmz/fRG69Rc1Uc

JBqCA/0faHEkyDv+FWEsmFKjflDNqN5NHtdWzJZQZKD1Vb64oJ5CK6r2l+vmxbBr

fVpfk5OVXnfMSpLKc7aGA9X+mUMuNrGRNzzzsmVK6urWQovL/BfeukMgDBZXkLd8

fO7aA53XeBhmVC49atFPH8hsOeMdd0mombrzcvKczjMp0ThP9rQzbmV0a2lsbGVy

ICjpmYjmma/ls7DnmoTlr4bpkqUpIDxuZXRraWxsZXJAOTgxMi5uZXQ+iFkEExEC

ABkFAj/ZuhgECwcDAgMVAgMDFgIBAh4BAheAAAoJEKwHyHOwCEfFBqMAn0HoK9Xc

zvzVkFODVZPWUskzwAhqAJ4rbgYEjSN1/CrdUBzTMtecGu9P+7kBDQQ/2boaEAQA

zhoIDY866/GWUUpuarpVKcN1ijn+5M1Pr42vm2Z42ns4PZW3cagHJeIOuJ5R2Aw1

6V4zZwP5PcBScYxQpM0m0bVmTGp/suZmZ6/u3+ADgvJYSxAXdpzP0cL9rVRKqaPa

MKh+HOanAJ9tWcSy6KW83JKG2NS/0U6OSGGDSoNLElMAAwUD/iGBjPfXD5jsepg+

Z9J1RefM5/R1nnBEeOROnWyaczIU1okswlyluAthi+2+ijpEULaqSQ+ZjtuBjcMp

kE5UKKql6yBAk2CqJMVkVLlDbPFqbidkAqGp5riKWKc487jR6iZjIAhHvXL0xPIQ

erBmEpi4UT7RlaCAmYwvZ1nxGP3eiEYEGBECAAYFAj/ZuhoACgkQrAfIc7AIR8U0

xACfT5pZ+0YjSp9z0/9jPwDfhw7J1bcAnjqxP+uKfkuDHnXRyYFErTN+7iHE

=CII0

-----END PGP PUBLIC KEY BLOCK-----

[chen@linux chen]$

二进制格式输出:

[chen@linux chen]$ gpg --output bin-netkiller.gpg --export netkiller

gpg: WARNING: using insecure memory!

gpg: please see http://www.gnupg.org/faq.html for more information

[chen@linux chen]$ ls

bin-netkiller.gpg  netkiller.gpg  revoke.asc

[chen@linux chen]$

 

7.         使用file命令识别文件

[chen@linux chen]$ ls

bin-netkiller.gpg  netkiller.gpg  revoke.asc

[chen@linux chen]$ file bin-netkiller.gpg

bin-netkiller.gpg: data

[chen@linux chen]$ file netkiller.gpg

netkiller.gpg: PGP armored data public key block

[chen@linux chen]$ file revoke.asc

revoke.asc: PGP armored data public key block

[chen@linux chen]$

 

8.         发布公钥

你可以将你的公钥放在主页上下载,也可以mail给别人。

[chen@linux chen]$ pine

  PINE 4.44   MAIN MENU                             Folder: INBOX  No Messages

 

 

          ?     HELP               -  Get help using Pine

 

          C     COMPOSE MESSAGE    -  Compose and send a message

 

          I     MESSAGE INDEX      -  View messages in current folder

 

          L     FOLDER LIST        -  Select a folder to view

 

          A     ADDRESS BOOK       -  Update address book

 

          S     SETUP              -  Configure Pine Options

 

          Q     QUIT               -  Leave the Pine program

 

 

 

 

   Copyright 1989-2002.  PINE is a trademark of the University of Washington.

                    [Folder "INBOX" opened with 0 messages]

? Help                     P PrevCmd                 R RelNotes

O OTHER CMDS > [ListFldrs] N NextCmd                 K KBLock

 

  PINE 4.44   COMPOSE MESSAGE                       Folder: INBOX  No Messages

 

To      : openunix@163.com

Cc      :

Attchmnt:

Subject : 这是我的证书

----- Message Text -----

 

Attchmnt

 

 

 

 

 

^G Get Help  ^X Send      ^R Rich Hdr  ^Y PrvPg/Top ^K Cut Line  ^O Postpone

^C Cancel    ^D Del Char  ^J Attach    ^V NxtPg/End ^U UnDel Line^T To Files

光标至于Attchmnt:上按^J -> 再按 ^T

File to attach:

^G Get Help  ^T  To Files

^C Cancel    TAB Complete

 

   PINE 4.44                BROWSER    Dir: /home/chen

 

..             (parent dir)  .gnupg                (dir)

.kde                  (dir)  mail                  (dir)

.xemacs               (dir)  .addressbook           0  B

.addressbook.lu      2.3 KB  .bash_logout          24  B

.bash_profile        191  B  .bashrc              124  B

bin-netkiller.gpg    909  B  .canna               5.5 KB

.emacs               847  B  .gtkrc               120  B

netkiller.gpg        1.3 KB  .pinerc               14 KB

revoke.asc           275  B  .Xauthority           61  B

 

 

 

 

 

 

 

 

 

 

                        [ Searched to end of directory ]

? Get Help   E Exit Brwsr              -   Prev Pg  D Delete     C Copy

             S [Select]   W Where is   Spc Next Pg  R Rename     A Add

选择netkiller.gpg 回车

Attachment comment: my netkiller.gpg file

^G Get Help

^C Cancel

输入注释信息

  PINE 4.44   COMPOSE MESSAGE                       Folder: INBOX  No Messages

 

To      : openunix@163.com

Cc      :

Attchmnt: 1. /home/chen/netkiller.gpg (1.3 KB) "my netkiller.gpg file"

Subject : my netkiller.gpg file

----- Message Text -----

 

http://linux.9812.net

email:openunix@163.com

 

 

 

          [File /home/chen/netkiller.gpg attached as type TEXT/PLAIN]

^G Get Help  ^X Send      ^R Rich Hdr  ^Y PrvPg/Top ^K Cut Line  ^O Postpone

^C Cancel    ^D Del Char  ^J Attach    ^V NxtPg/End ^U UnDel Line^T To Files

 

Send message?y

 ? Help      Y [Yes]

^C Cancel    N No

选择y回车

  PINE 4.44   MAIN MENU                             Folder: INBOX  No Messages

 

 

  PINE 4.44   COMPOSE MESSAGE                       Folder: INBOX  No Messages

 

To      : openunix@163.com

Cc      :

Attchmnt: 1. /home/chen/netkiller.gpg (1.3 KB) "my netkiller.gpg file"

Subject : 这是我的证书

----- Message Text -----

 

Attchmnt

 

 

 

 

 

 

 

                          [Sending mail |     0%   |]

 

 

发送成功

  PINE 4.44   MAIN MENU                             Folder: INBOX  No Messages

 

 

          ?     HELP               -  Get help using Pine

 

          C     COMPOSE MESSAGE    -  Compose and send a message

 

          I     MESSAGE INDEX      -  View messages in current folder

 

          L     FOLDER LIST        -  Select a folder to view

 

          A     ADDRESS BOOK       -  Update address book

 

          S     SETUP              -  Configure Pine Options

 

          Q     QUIT               -  Leave the Pine program

 

 

 

 

   Copyright 1989-2002.  PINE is a trademark of the University of Washington.

                   [Message sent and copied to "sent-mail".]

? Help                     P PrevCmd                 R RelNotes

O OTHER CMDS > [ListFldrs] N NextCmd                 K KBLock

 

 

9.         将公钥给其它用户

[chen@linux chen]$ cp netkiller.gpg /tmp

 

以下是ming帐号的操作:

 

10.     获得公钥

[ming@linux ming]$ cp /tmp/netkiller.gpg .

[ming@linux ming]$ ls

netkiller.gpg

[ming@linux ming]$

 

11.     导入公钥

[ming@linux ming]$ gpg --import netkiller.gpg

gpg: WARNING: using insecure memory!

gpg: please see http://www.gnupg.org/faq.html for more information

gpg: /home/ming/.gnupg: directory created

gpg: new configuration file `/home/ming/.gnupg/gpg.conf' created

gpg: keyblock resource `/home/ming/.gnupg/secring.gpg': file open error

gpg: keyring `/home/ming/.gnupg/pubring.gpg' created

gpg: /home/ming/.gnupg/trustdb.gpg: trustdb created

gpg: key B00847C5: public key "netkiller (▒\x9\x8▒\x9▒▒\x9\x8▒\x8▒\x9▒) <openunix@163.com>" imported

gpg: Total number processed: 1

gpg:               imported: 1

[ming@linux ming]$ gpg --list-key

gpg: WARNING: using insecure memory!

gpg: please see http://www.gnupg.org/faq.html for more information

/home/ming/.gnupg/pubring.gpg

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

pub  1024D/B00847C5 2003-12-12 netkiller (陈景峰的密钥) <openunix@163.com>

sub  1024g/0B70F0CB 2003-12-12

 

[ming@linux ming]$

 

12.     确认密钥

导入密钥以后,使用数字签名来验证此证书是否合法。

[ming@linux ming]$ gpg --fingerprint netkiller

gpg: WARNING: using insecure memory!

gpg: please see http://www.gnupg.org/faq.html for more information

pub  1024D/B00847C5 2003-12-12 netkiller (陈景峰的密钥) <openunix@163.com>

     Key fingerprint = 0058 5847 7598 556F AAFD  81A5 AC07 C873 B008 47C5

sub  1024g/0B70F0CB 2003-12-12

 

[ming@linux ming]$

 

13.     密钥签名

导入密钥之后,可以使用(gpg -—sign-key netkiller) 进行签名,签名的主要目的是证明您完全信任这个证书的合法性。

[ming@linux ming]$ gpg --gen-key

gpg (GnuPG) 1.2.1; Copyright (C) 2002 Free Software Foundation, Inc.

This program comes with ABSOLUTELY NO WARRANTY.

This is free software, and you are welcome to redistribute it

under certain conditions. See the file COPYING for details.

 

gpg: WARNING: using insecure memory!

gpg: please see http://www.gnupg.org/faq.html for more information

Please select what kind of key you want:

   (1) DSA and ElGamal (default)

   (2) DSA (sign only)

   (5) RSA (sign only)

Your selection?

DSA keypair will have 1024 bits.

About to generate a new ELG-E keypair.

              minimum keysize is  768 bits

              default keysize is 1024 bits

    highest suggested keysize is 2048 bits

What keysize do you want? (1024)

Requested keysize is 1024 bits

Please specify how long the key should be valid.

         0 = key does not expire

      <n>  = key expires in n days

      <n>w = key expires in n weeks

      <n>m = key expires in n months

      <n>y = key expires in n years

Key is valid for? (0)

Key does not expire at all

Is this correct (y/n)? y

 

You need a User-ID to identify your key; the software constructs the user id

from Real Name, Comment and Email Address in this form:

    "Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"

 

Real name: ming

Name must be at least 5 characters long

Real name: mings

Email address: mings@9812.net

Comment: I am ming

You selected this USER-ID:

    "mings (I am ming) <mings@9812.net>"

 

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o

You need a Passphrase to protect your secret key.

Enter passphrase:

 

passphrase not correctly repeated; try again.

We need to generate a lot of random bytes. It is a good idea to perform

some other action (type on the keyboard, move the mouse, utilize the

disks) during the prime generation; this gives the random number

generator a better chance to gain enough entropy.

+++++++++++++++.++++++++++++++++++++++++++++++.++++++++++....++++++++++.++++++++++++++++++++.+++++++++++++++..+++++++++++++++++++++++++.++++++++++.....>..+++++...........................+++++

We need to generate a lot of random bytes. It is a good idea to perform

some other action (type on the keyboard, move the mouse, utilize the

disks) during the prime generation; this gives the random number

generator a better chance to gain enough entropy.

+++++++++++++++++++++++++..++++++++++++++++++++.+++++++++++++++++++++++++++++++++++..+++++++++++++++...+++++++++++++++++++++++++++++++++++>+++++..................+++++^^^^^^^^^^^^^^^

public and secret key created and signed.

key marked as ultimately trusted.

 

pub  1024D/3D9CE6DF 2003-12-12 mings (I am ming) <mings@9812.net>

     Key fingerprint = 51C5 A223 98B8 A65F 4BF4  B610 4B80 D812 3D9C E6DF

sub  1024g/510C2A18 2003-12-12

[ming@linux ming]$ gpg --sign-key netkiller

gpg: WARNING: using insecure memory!

gpg: please see http://www.gnupg.org/faq.html for more information

 

pub  1024D/B00847C5  created: 2003-12-12 expires: never      trust: -/-

sub  1024g/0B70F0CB  created: 2003-12-12 expires: never

(1). netkiller (陈景峰的密钥) <openunix@163.com>

 

 

pub  1024D/B00847C5  created: 2003-12-12 expires: never      trust: -/-

 Primary key fingerprint: 0058 5847 7598 556F AAFD  81A5 AC07 C873 B008 47C5

 

     netkiller (陈景峰的密钥) <openunix@163.com>

 

How carefully have you verified the key you are about to sign actually belongs

to the person named above?  If you don't know what to answer, enter "0".

 

   (0) I will not answer. (default)

   (1) I have not checked at all.

   (2) I have done casual checking.

   (3) I have done very careful checking.

 

Your selection? 3

Are you really sure that you want to sign this key

with your key: "mings (I am ming) <mings@9812.net>"

 

I have checked this key very carefully.

 

Really sign? y

 

You need a passphrase to unlock the secret key for

user: "mings (I am ming) <mings@9812.net>"

1024-bit DSA key, ID 3D9CE6DF, created 2003-12-12

 

Enter passphrase: 注这里输入mings的口令

 

[ming@linux ming]$

[ming@linux ming]$ gpg --list-key

gpg: WARNING: using insecure memory!

gpg: please see http://www.gnupg.org/faq.html for more information

/home/ming/.gnupg/pubring.gpg

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

pub  1024D/B00847C5 2003-12-12 netkiller (陈景峰的密钥) <openunix@163.com>

sub  1024g/0B70F0CB 2003-12-12

 

pub  1024D/3D9CE6DF 2003-12-12 mings (I am ming) <mings@9812.net>

sub  1024g/510C2A18 2003-12-12

 

[ming@linux ming]$

 

14.     检查签名

[chen@linux chen]$ gpg --check-sigs netkiller

gpg: WARNING: using insecure memory!

gpg: please see http://www.gnupg.org/faq.html for more information

pub  1024D/B00847C5 2003-12-12 netkiller (陈景峰的密钥) <openunix@163.com>

sig!3       B00847C5 2003-12-12   netkiller (陈景峰的密钥) <openunix@163.com>

sub  1024g/0B70F0CB 2003-12-12

sig!        B00847C5 2003-12-12   netkiller (陈景峰的密钥) <openunix@163.com>

[ming@linux ming]$ gpg --check-sigs netkiller

gpg: WARNING: using insecure memory!

gpg: please see http://www.gnupg.org/faq.html for more information

pub  1024D/B00847C5 2003-12-12 netkiller (陈景峰的密钥) <openunix@163.com>

sig!3       B00847C5 2003-12-12   netkiller (陈景峰的密钥) <openunix@163.com>

sig!        79F1102B 2003-12-12   mings (I am mings) <mings@9812.net>

sub  1024g/0B70F0CB 2003-12-12

sig!        B00847C5 2003-12-12   netkiller (陈景峰的密钥) <openunix@163.com>

 

[ming@linux ming]$

[chen@linux chen]$

 

[ming@linux ming]$ gpg --check-sigs netkiller

gpg: WARNING: using insecure memory!

gpg: please see http://www.gnupg.org/faq.html for more information

pub  1024D/B00847C5 2003-12-12 netkiller (陈景峰的密钥) <openunix@163.com>

sig!3       B00847C5 2003-12-12   netkiller (陈景峰的密钥) <openunix@163.com>

sub  1024g/0B70F0CB 2003-12-12

sig!        B00847C5 2003-12-12   netkiller (陈景峰的密钥) <openunix@163.com>

 

[ming@linux ming]$

 

15.     加密和解密

加密:

[ming@linux ming]$ pg_dump -Unetkiller -h127.0.0.1 >pgsql-dump.sql

Password:

[ming@linux ming]$

 

加签名:

[ming@linux ming]$ gpg -sear netkiller pgsql-dump.sql

gpg: WARNING: using insecure memory!

gpg: please see http://www.gnupg.org/faq.html for more information

 

You need a passphrase to unlock the secret key for

user: "mings (I am mings) <mings@9812.net>"

1024-bit DSA key, ID 79F1102B, created 2003-12-12

 

gpg: checking the trustdb

gpg: checking at depth 0 signed=1 ot(-/q/n/m/f/u)=0/0/0/0/0/1

gpg: checking at depth 1 signed=0 ot(-/q/n/m/f/u)=1/0/0/0/0/0

[ming@linux ming]$

 

不加签名:

[ming@linux ming]$ gpg -ear netkiller pgsql-dump.sql

gpg: WARNING: using insecure memory!

gpg: please see http://www.gnupg.org/faq.html for more information

[ming@linux ming]$ ls

netkiller.gpg  pgsql-dump.sql  pgsql-dump.sql.asc

[ming@linux ming]$

 

加密完成,将文件pgsql-dump.sql.asc发给chen (邮件,WEB/FTP下载。。。都可以,不用担心被其它人得到对你不利,现在这个文件已经加密了。)

以下为chen帐号解密操作:

[chen@linux chen]$ gpg -d pgsql-dump.sql.asc > pgsql-dump.sql

gpg: WARNING: using insecure memory!

gpg: please see http://www.gnupg.org/faq.html for more information

 

You need a passphrase to unlock the secret key for

user: "netkiller (陈景峰的密钥) <openunix@163.com>"

1024-bit ELG-E key, ID 0B70F0CB, created 2003-12-12 (main key ID B00847C5)

 

Enter passphrase:

gpg: encrypted with 1024-bit ELG-E key, ID 0B70F0CB, created 2003-12-12

      "netkiller (陈景峰的密钥) <openunix@163.com>"

[chen@linux chen]$

 

 

2.6    备份计划

2.6.1   服务器端计划

因为每天凌晨1:00-5:00这段时间访问的人比较少,所以我选择服务器端每天凌晨300开始备份,您也可以在其它时间段备份,根据您的需求而定。

[root@linux etc]# cat crontab

SHELL=/bin/bash

PATH=/sbin:/bin:/usr/sbin:/usr/bin

MAILTO=root

HOME=/

 

# run-parts

01 * * * * root run-parts /etc/cron.hourly

02 4 * * * root run-parts /etc/cron.daily

22 4 * * 0 root run-parts /etc/cron.weekly

42 4 1 * * root run-parts /etc/cron.monthly

0 3 * * * root /usr/local/backup/backup.sh

2.6.2   客户端计划

客户端每天零晨400点开始下载备份数据。为什么是400下载呢?因为服务器备份要一段时间,如果服务器还没有备份完成,这边是不能下载的。所以计划在3:00服务器开始备份,400时客户端开始下载已经备份好的数据。

[root@linux etc]# cat crontab

SHELL=/bin/bash

PATH=/sbin:/bin:/usr/sbin:/usr/bin

MAILTO=root

HOME=/

 

# run-parts

01 * * * * root run-parts /etc/cron.hourly

02 4 * * * root run-parts /etc/cron.daily

22 4 * * 0 root run-parts /etc/cron.weekly

42 4 1 * * root run-parts /etc/cron.monthly

0 4 * * * root /usr/local/backup/getbackup.sh

2.7    数据恢复

[root@linux root]# su postgres

bash-2.05b$ psql member -f pgsql-backup.xxxx-xx-xx.xx:xx:xx.dmp

 

2.8    性能提升

2.8.1   共享内存

2.2 内核里缺省的共享内存限制( SHMMAX SHMALL)都是 32 MB,但是你可以在 proc 文件系统里修改这些值(不用重起). 比如,要允许 128 MB

方法1

# echo 134217728 >/proc/sys/kernel/shmall

# echo 134217728 >/proc/sys/kernel/shmmax

[root@linux root]# cat /proc/sys/kernel/shmall

2097152

[root@linux root]# cat /proc/sys/kernel/shmmax

33554432

[root@linux root]# echo 134217728 >/proc/sys/kernel/shmall

[root@linux root]# echo 134217728 >/proc/sys/kernel/shmmax

[root@linux root]# cat /proc/sys/kernel/shmall

134217728

[root@linux root]# cat /proc/sys/kernel/shmmax

134217728

 

你可以把这些命令放到一个引导时运行的脚本中. rc.local文件

[root@linux root]# cat /etc/rc.d/rc.local

#!/bin/sh

#

# This script will be executed *after* all the other init scripts.

# You can put your own initialization stuff in here if you don't

# want to do the full Sys V style init stuff.

 

touch /var/lock/subsys/local

/usr/local/jakarta-tomcat/bin/startup.sh

/usr/local/apache/bin/apachectl start

echo 134217728 >/proc/sys/kernel/shmall

echo 134217728 >/proc/sys/kernel/shmmax

 

方法2,使用 sysctl 命令来控制这些参数.

[root@linux root]# sysctl -w kernel.shmall=134217728

kernel.shmall = 134217728

[root@linux root]# sysctl -w kernel.shmmax=134217728

kernel.shmmax = 134217728

[root@linux root]#

 

方法3,你可以在一个叫 /etc/sysctl.conf 的文件里面加下面这样的两行:

kernel.shmall = 134217728

kernel.shmmax = 134217728

[root@linux root]# cat /etc/sysctl.conf

# Kernel sysctl configuration file for Red Hat Linux

#

# For binary values, 0 is disabled, 1 is enabled.  See sysctl(8) and

# sysctl.conf(5) for more details.

 

# Controls IP packet forwarding

net.ipv4.ip_forward = 0

 

# Controls source route verification

net.ipv4.conf.default.rp_filter = 1

 

# Controls the System Request debugging functionality of the kernel

kernel.sysrq = 0

 

# Controls whether core dumps will append the PID to the core filename.

# Useful for debugging multi-threaded applications.

kernel.core_uses_pid = 1

kernel.shmall = 134217728

kernel.shmmax = 134217728

通常在引导的时候会处理这个文件,但你也可以稍后明确调用sysctl

2.8.2   最大连接

跟据你的需要来配置最大连接数,系统默认是32,配置需要修改两处。

max_connections = 100

shared_buffers = 200

shared_buffers = max_connections*2

[root@linux data]# cat postgresql.conf

#

# PostgreSQL configuration file

# -----------------------------

#

# This file consists of lines of the form:

#

#   name = value

#

# (The '=' is optional.) White space may be used. Comments are introduced

# with '#' anywhere on a line. The complete list of option names and

# allowed values can be found in the PostgreSQL documentation. The

# commented-out settings shown in this file represent the default values.

#

# Any option can also be given as a command line switch to the

# postmaster, e.g. 'postmaster -c log_connections=on'. Some options

# can be changed at run-time with the 'SET' SQL command.

#

# This file is read on postmaster startup and when the postmaster

# receives a SIGHUP. If you edit the file on a running system, you have

# to SIGHUP the postmaster for the changes to take effect, or use

# "pg_ctl reload".

 

 

#========================================================================

 

 

#

#       Connection Parameters

#

#tcpip_socket = false

 

tcpip_socket = true

 

#ssl = false

#ssl = true

 

#max_connections = 32

max_connections = 100

#superuser_reserved_connections = 2

 

#port = 5432

#hostname_lookup = false

#show_source_port = false

 

#unix_socket_directory = ''

#unix_socket_group = ''

#unix_socket_permissions = 0777 # octal

 

#virtual_host = ''

 

#krb_server_keyfile = ''

 

 

#

#       Shared Memory Size

#

#shared_buffers = 64            # min max_connections*2 or 16, 8KB each

shared_buffers = 200            # min max_connections*2 or 16, 8KB each

#max_fsm_relations = 1000       # min 10, fsm is free space map, ~40 bytes

#max_fsm_pages = 10000          # min 1000, fsm is free space map, ~6 bytes

#max_locks_per_transaction = 64 # min 10

#wal_buffers = 8                # min 4, typically 8KB each

 

#

#       Non-shared Memory Sizes

#

#sort_mem = 1024                # min 64, size in KB

#vacuum_mem = 8192              # min 1024, size in KB

 

 

#

#       Write-ahead log (WAL)

#

#checkpoint_segments = 3        # in logfile segments, min 1, 16MB each

#checkpoint_timeout = 300       # range 30-3600, in seconds

#

#commit_delay = 0               # range 0-100000, in microseconds

#commit_siblings = 5            # range 1-1000

#

#fsync = true

#wal_sync_method = fsync        # the default varies across platforms:

#                               # fsync, fdatasync, open_sync, or open_datasync

#wal_debug = 0                  # range 0-16

 

 

#

#       Optimizer Parameters

#

#enable_seqscan = true

#enable_indexscan = true

#enable_tidscan = true

#enable_sort = true

#enable_nestloop = true

#enable_mergejoin = true

#enable_hashjoin = true

 

#effective_cache_size = 1000    # typically 8KB each

#random_page_cost = 4           # units are one sequential page fetch cost

#cpu_tuple_cost = 0.01          # (same)

#cpu_index_tuple_cost = 0.001   # (same)

#cpu_operator_cost = 0.0025     # (same)

 

#default_statistics_target = 10 # range 1-1000

 

#

#       GEQO Optimizer Parameters

#

#geqo = true

#geqo_selection_bias = 2.0      # range 1.5-2.0

#geqo_threshold = 11

#geqo_pool_size = 0             # default based on tables in statement,

                                # range 128-1024

#geqo_effort = 1

#geqo_generations = 0

#geqo_random_seed = -1          # auto-compute seed

 

 

#

#       Message display

#

#server_min_messages = notice   # Values, in order of decreasing detail:

                                #   debug5, debug4, debug3, debug2, debug1,

                                #   info, notice, warning, error, log, fatal,

                                #   panic

#client_min_messages = notice   # Values, in order of decreasing detail:

                                #   debug5, debug4, debug3, debug2, debug1,

                                #   log, info, notice, warning, error

#silent_mode = false

 

#log_connections = false

#log_pid = false

#log_statement = false

#log_duration = false

#log_timestamp = false

 

#log_min_error_statement = panic # Values in order of increasing severity:

                                 #   debug5, debug4, debug3, debug2, debug1,

                                 #   info, notice, warning, error, panic(off)

 

#debug_print_parse = false

#debug_print_rewritten = false

#debug_print_plan = false

#debug_pretty_print = false

 

#explain_pretty_print = true

 

# requires USE_ASSERT_CHECKING

#debug_assertions = true

 

 

#

#       Syslog

#

#syslog = 0                     # range 0-2

#syslog_facility = 'LOCAL0'

#syslog_ident = 'postgres'

 

 

#

#       Statistics

#

#show_parser_stats = false

#show_planner_stats = false

#show_executor_stats = false

#show_statement_stats = false

 

# requires BTREE_BUILD_STATS

#show_btree_build_stats = false

 

 

#

#       Access statistics collection

#

#stats_start_collector = true

#stats_reset_on_server_start = true

#stats_command_string = false

#stats_row_level = false

#stats_block_level = false

 

 

#

#       Lock Tracing

#

#trace_notify = false

 

# requires LOCK_DEBUG

#trace_locks = false

#trace_userlocks = false

#trace_lwlocks = false

#debug_deadlocks = false

#trace_lock_oidmin = 16384

#trace_lock_table = 0

 

 

#

#       Misc

#

#autocommit = true

#dynamic_library_path = '$libdir'

#search_path = '$user,public'

#datestyle = 'iso, us'

#timezone = unknown             # actually, defaults to TZ environment setting

#australian_timezones = false

#client_encoding = sql_ascii    # actually, defaults to database encoding

#authentication_timeout = 60    # 1-600, in seconds

#deadlock_timeout = 1000        # in milliseconds

#default_transaction_isolation = 'read committed'

#max_expr_depth = 10000         # min 10

#max_files_per_process = 1000   # min 25

#password_encryption = true

#sql_inheritance = true

#transform_null_equals = false

#statement_timeout = 0          # 0 is disabled, in milliseconds

#db_user_namespace = false

 

 

 

#

#       Locale settings

#

# (initialized by initdb -- may be changed)

LC_MESSAGES = 'en_US.UTF-8'

LC_MONETARY = 'en_US.UTF-8'

LC_NUMERIC = 'en_US.UTF-8'

LC_TIME = 'en_US.UTF-8'

 

 

重新启动数据:

[root@linux data]# service postgresql restart

                                                     [  OK  ]

Starting postgresql service:                               [  OK  ]

 

查看配置是否正确:

[root@linux root]# psql -Uchen member

Welcome to psql 7.3.3, the PostgreSQL interactive terminal.

 

Type:  \copyright for distribution terms

       \h for help with SQL commands

       \? for help on internal slash commands

       \g or terminate with semicolon to execute query

       \q to quit

 

member=> show max_connections;

 max_connections

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

 100

(1 row)

2.8.3   vacuumdb

数据库200优化、300备份、400下载备份数据

[root@linux etc]# cat crontab

SHELL=/bin/bash

PATH=/sbin:/bin:/usr/sbin:/usr/bin

MAILTO=root

HOME=/

 

# run-parts

01 * * * * root run-parts /etc/cron.hourly

02 4 * * * root run-parts /etc/cron.daily

22 4 * * 0 root run-parts /etc/cron.weekly

42 4 1 * * root run-parts /etc/cron.monthly

0 2 * * * root /usr/local/pgsql/optimize.sh

 

数据库vacuumdb优化脚本

[root@linux pgsql]# cat optimize.sh

#!/bin/bash

vacuumdb -hlocalhost -p5432 -Upostgres -a -f -z

[root@linux pgsql]#

2.8.4   数据库操作与性能

1.         分组插入数据

向数据库做大量Insert 操作时(注:非导入,在某些特殊环境中要做大量的插入操作,而   不是导入数据),如你有10000条记录要插入到数据库中,建议你将10000记录分组插入

第一组

 

begin;

insert into ……

insert into ……

insert into ……

…….

1000insert into

…….

insert into ……

commit;

第二组

begin;

insert into ……

…….

1000insert into

…….

insert into ……

commit;

第十组

begin;

insert into ……

…….

1000insert into

…….

insert into ……

commit;

 

2.         通过copy from插入数据

pg_copy_from

(PHP 4 >= 4.2.0)

 

pg_copy_from --  根据数组将记录插入表中

说明

bool pg_copy_from ( resource connection, string table_name, array rows [, string delimiter [, string null_as]])

pg_copy_from() 将数组 rows 的内容作为记录插入表中。它在内部使用了 COPY FROM SQL 命令来插入记录。如果成功则返回 TRUE,失败则返回 FALSE

                      

参见 pg_copy_to()

3.         操作之后使用重建索引
vacuumdb -hlocalhost -p5432 -Upostgres -a -f -z

2.8.5   硬件方面

1.         一般服务器

PC服务器有条件建议使用SATA(串行)硬盘。

没有条件可以买时下最快的ATA硬盘(也不是越快越好,还要稳定)

正常情况下几块ATA 66 (5400rpm)硬盘做RAID 0,要比一块ATA100(7200rpm)还要快。

RAID 是解决服务器硬盘瓶颈最佳方案。建议使用RAID0,RAID0速度最快,不安全,但速度诱人,只要做好备份,是没有问题的。
目前PC上ATA只能做RAID0(条带)和RAID1(镜像)。SATA可以做RAID0,1,5,10,50。不过我还没见过STAT 的RAID卡,深圳赛格也没得卖。

2.         高档服务器

高档服务器中主流使用SCSI硬盘,公司也出得起¥¥¥买。所以干脆一次就配置5块SCSI硬盘。4块盘做RAID5,剩余1块做热交换hotswap

因为SCSI性能稳定,如果不满足RAID5速度,可以做RAID0。

 

附表1

RAID级别

RAID 0

RAID 1

RAID 3

RAID 5

名称

条带

镜像

专用校验条带

分散校验条带

允许故障

冗余类型

副本

校验

校验

热备用操作

不可

可以

可以

可以

硬盘数量

一个以上

两个

三个以上

三个以上

可用容量

最大

最小

中间

中间

减少容量

50%

一个磁盘

一个磁盘

读性能

高(盘的数量决定)

中间

随机写性能

最高

中间

最低

连续写性能

最高

中间

最低

典型应用

无故障的迅速读写

允许故障的小檔、随机数据写入

允许故障的大檔、连续数据传输

允许故障的小檔、随机数据传输

可用容量

总的磁盘的容量

只能用磁盘容量的50%

n-1/n的磁盘容量。其中n为磁盘数

n-1/n的总磁盘容量。其中n为磁盘数

  附表2

RAID级别

RAID 10

RAID 30

RAID 50

名称

跨越镜像数组

跨越专用校验数组

跨越分散校验数组

允许故障

冗余类型

副本

校验

校验

热备用操作

可以

可以

可以

磁盘数量

 

 

 

跨越2个数组

4

6,8,10,12,1416

6,8,10,12,1416

跨越3个数组

6

9,1215

9,1215

跨越4个数组

8

1216

1216

可用容量

最小

中间

中间

减少容量

50%

每个数组中一个磁盘

每个数组中一个磁盘

读性能

中间

随机写性能

中间

最低

连续写性能

中间

最低

典型应用

允许故障高速度小文件、随机数据写入

允许故障高速度大文件、连续数据传输

允许故障高速度小文件、随机数据传输

可用容量

磁盘容量的50%

n-2/2的磁盘容量。其中n为磁盘数目

n-2/n的磁盘容量。其中n为磁盘数

 

3.         网络,光纤存储我没使用过,这里也不谈了。

2.8.6   磁盘性能

注:hdparm 有些参考只支持ATA硬盘。

[root@linux root]# hdparm

 

hdparm - get/set hard disk parameters - version v5.2

 

Usage:  hdparm  [options] [device] ..

 

Options:

 -a   get/set fs readahead

 -A   set drive read-lookahead flag (0/1)

 -b   get/set bus state (0 == off, 1 == on, 2 == tristate)

 -B   set Advanced Power Management setting (1-255)

 -c   get/set IDE 32-bit IO setting

 -C   check IDE power mode status

 -d   get/set using_dma flag

 -D   enable/disable drive defect-mgmt

 -E   set cd-rom drive speed

 -f   flush buffer cache for device on exit

 -g   display drive geometry

 -h   display terse usage information

 -i   display drive identification

 -I   detailed/current information directly from drive

 -Istdin  similar to -I, but wants /proc/ide/*/hd?/identify as input

 -k   get/set keep_settings_over_reset flag (0/1)

 -K   set drive keep_features_over_reset flag (0/1)

 -L   set drive doorlock (0/1) (removable harddisks only)

 -M   get/set acoustic management (0-254, 128: quiet, 254: fast) (EXPERIMENTAL)

 -m   get/set multiple sector count

 -n   get/set ignore-write-errors flag (0/1)

 -p   set PIO mode on IDE interface chipset (0,1,2,3,4,...)

 -P   set drive prefetch count

 -q   change next setting quietly

 -Q   get/set DMA tagged-queuing depth (if supported)

 -r   get/set readonly flag (DANGEROUS to set)

 -R   register an IDE interface (DANGEROUS)

 -S   set standby (spindown) timeout

 -t   perform device read timings

 -T   perform cache read timings

 -u   get/set unmaskirq flag (0/1)

 -U   un-register an IDE interface (DANGEROUS)

 -v   defaults; same as -mcudkrag for IDE drives

 -V   display program version and exit immediately

 -w   perform device reset (DANGEROUS)

 -W   set drive write-caching flag (0/1) (DANGEROUS)

 -x   tristate device for hotswap (0/1) (DANGEROUS)

 -X   set IDE xfer mode (DANGEROUS)

 -y   put IDE drive in standby mode

 -Y   put IDE drive to sleep

 -Z   disable Seagate auto-powersaving mode

 -z   re-read partition table

 

测试 /dev/hda 这块硬盘的cache与实际效能:

[root@linux root]# hdparm -Tt /dev/hda

 

/dev/hda:

 Timing buffer-cache reads:   128 MB in  0.26 seconds =492.31 MB/sec

 Timing buffered disk reads:  64 MB in  2.28 seconds = 28.07 MB/sec

[root@linux root]#

 

关闭 DMA 模式!

[root@linux root]# hdparm -d0 /dev/hda

 

/dev/hda:

 setting using_dma to 0 (off)

 using_dma    =  0 (off)

[root@linux root]#

 

开启 DMA 模式在 DMA 66 ,并且开启 32 位存取模式

[root@linux root]# hdparm -d1 -c3 -X66 /dev/hda

 

/dev/hda:

 setting 32-bit IO_support flag to 3

 setting using_dma to 1 (on)

 setting xfermode to 66 (UltraDMA mode2)

 IO_support   =  3 (32-bit w/sync)

 using_dma    =  1 (on)

[root@linux root]#

因为可能这个程序比较早,没有后续版本,所以他只支持到66

[root@linux root]# hdparm -d1 -c3 -X100 /dev/hda

 

/dev/hda:

 setting 32-bit IO_support flag to 3

 setting using_dma to 1 (on)

 setting xfermode to 100 (unknown, probably not valid)

 HDIO_DRIVE_CMD(setxfermode) failed: Input/output error

 IO_support   =  3 (32-bit w/sync)

 using_dma    =  1 (on)

[root@linux root]#

 

这是我的PC服务器A

       CPUP4 2.6G
      
内存:512MB

       硬盘:70GB ATA133

[root@linux root]# hdparm -d1 -Tt -c3 /dev/hda                                 

/dev/hda:

 setting 32-bit IO_support flag to 3

 setting using_dma to 1 (on)

 IO_support   =  3 (32-bit w/sync)

 using_dma    =  1 (on)

 Timing buffer-cache reads:   128 MB in  0.25 seconds =512.00 MB/sec

 Timing buffered disk reads:  64 MB in  2.28 seconds = 28.07 MB/sec

[root@linux root]#

这是一台深圳产的宝德PC服务器B

       CPUP4 2.4G

       内存:1GB

       ATA RAID 0 120GATA100*2

[root@linux root]# hdparm -d1 -Tt -c3 /dev/sda

 

/dev/sda:

 operation not supported on SCSI disks

[root@linux root]#

 

[root@linux root]# hdparm -Tt /dev/sda

 

/dev/sda:

 Timing buffer-cache reads:   128 MB in  0.33 seconds =392.46 MB/sec

 Timing buffered disk reads:  64 MB in  1.00 seconds = 63.87 MB/sec

[root@linux root]# hdparm -Tt /dev/sda

 

/dev/sda:

 Timing buffer-cache reads:   128 MB in  0.33 seconds =392.46 MB/sec

 Timing buffered disk reads:  64 MB in  1.02 seconds = 62.77 MB/sec

[root@linux root]#

 

上面两台PC服务器,A最近配置的,B是半年前配置的,从对比可以看出两块ATA100RAID0,与单块ATA133。前者慢,但我想如果用4块硬盘做RAID 0 性能一定会超过A

2.9    安全的TCP/IP联接

2.9.1   使用SSL进行安全的TCP/IP联接

1.         设置用户信息:

[root@linux8 root]# su - postgres

-bash-2.05b$ ls

data  initdb.i18n

-bash-2.05b$ cd data/

-bash-2.05b$ ls

base    pg_clog      pg_ident.conf  pg_xlog          postmaster.opts

global  pg_hba.conf  PG_VERSION     postgresql.conf  postmaster.pid

-bash-2.05b$ openssl req -new -text -out server.req

Using configuration from /usr/share/ssl/openssl.cnf

Generating a 1024 bit RSA private key

....++++++

............................................................++++++

writing new private key to 'privkey.pem'

Enter PEM pass phrase:

Verifying password - Enter PEM pass phrase:

-----

You are about to be asked to enter information that will be incorporated

into your certificate request.

What you are about to enter is what is called a Distinguished Name or a DN.

There are quite a few fields but you can leave some blank

For some fields there will be a default value,

If you enter '.', the field will be left blank.

-----

Country Name (2 letter code) [GB]:CN

State or Province Name (full name) [Berkshire]:Guang Zhou

Locality Name (eg, city) [Newbury]:Shen Zhen

Organization Name (eg, company) [My Company Ltd]:Open Source Organization

Organizational Unit Name (eg, section) []:technical

Common Name (eg, your name or your server's hostname) []:www.9812.net

Email Address []:openunix@163.com

 

Please enter the following 'extra' attributes

to be sent with your certificate request

A challenge password []:chen

An optional company name []:netkiller

-bash-2.05b$ ls

base    pg_clog      pg_ident.conf  pg_xlog          postmaster.opts  privkey.pem

global  pg_hba.conf  PG_VERSION     postgresql.conf  postmaster.pid   server.req

-bash-2.05b$

 

注意上面的server.req文件,我们来看看它的内容:

-bash-2.05b$ cat server.req

Certificate Request:

    Data:

        Version: 0 (0x0)

        Subject: C=CN, ST=Guang Zhou, L=Shen Zhen, O=Open Source Organization, OU=technical, CN=www.9812.net/Email=openunix@163.com

        Subject Public Key Info:

            Public Key Algorithm: rsaEncryption

            RSA Public Key: (1024 bit)

                Modulus (1024 bit):

                    00:a5:30:9a:ef:75:9f:40:40:ee:90:4e:06:f7:f7:

                    0b:de:97:d0:1a:2e:48:ef:4c:7b:c2:cd:f2:f4:30:

                    1b:f4:c7:9d:65:7a:53:d7:d7:7c:ea:25:8f:be:b0:

                    57:f5:89:91:2e:80:4c:ff:f1:96:1e:42:06:01:64:

                    9f:98:69:24:c1:7f:e6:0c:a5:ae:b9:9c:4c:29:db:

                    a3:a3:3d:76:da:89:c0:33:29:c5:a5:8b:7a:e1:e5:

                    f4:3b:f3:7d:54:d4:65:fa:c8:c0:1c:11:07:1c:24:

                    03:8e:f0:61:d9:70:cf:fa:dd:e2:04:4a:31:c2:63:

                    2a:5f:44:ec:48:68:30:44:8d

                Exponent: 65537 (0x10001)

        Attributes:

            challengePassword        :chen

            unstructuredName         :netkiller

    Signature Algorithm: md5WithRSAEncryption

        09:4a:1c:e5:87:7a:9c:6f:69:ed:cd:11:8d:b6:bc:da:e0:4a:

        f5:7a:33:70:0d:5f:28:63:82:79:39:6b:a5:ae:02:7b:87:cb:

        86:74:2e:2b:eb:ec:23:3b:dc:02:25:29:02:74:e7:92:76:ed:

        34:e1:63:e9:ef:dc:12:33:31:84:31:ce:b3:d4:f2:49:92:a5:

        2c:5e:0a:3d:73:f8:1f:95:8f:71:f9:2d:ee:eb:4a:9c:8c:13:

        a5:26:a2:d2:49:c3:7e:69:c7:1b:73:bb:59:8d:9c:bf:dd:ac:

        4b:c4:41:02:b1:3c:a6:c9:c9:eb:00:b3:75:2d:e2:ab:29:b3:

        85:75

-----BEGIN CERTIFICATE REQUEST-----

MIICFzCCAYACAQAwgacxCzAJBgNVBAYTAkNOMRMwEQYDVQQIEwpHdWFuZyBaaG91

MRIwEAYDVQQHEwlTaGVuIFpoZW4xITAfBgNVBAoTGE9wZW4gU291cmNlIE9yZ2Fu

aXphdGlvbjESMBAGA1UECxMJdGVjaG5pY2FsMRUwEwYDVQQDEwx3d3cuOTgxMi5u

ZXQxITAfBgkqhkiG9w0BCQEWEm5ldGtpbGxlckA5ODEyLm5ldDCBnzANBgkqhkiG

9w0BAQEFAAOBjQAwgYkCgYEApTCa73WfQEDukE4G9/cL3pfQGi5I70x7ws3y9DAb

9MedZXpT19d86iWPvrBX9YmRLoBM//GWHkIGAWSfmGkkwX/mDKWuuZxMKdujoz12

2onAMynFpYt64eX0O/N9VNRl+sjAHBEHHCQDjvBh2XDP+t3iBEoxwmMqX0TsSGgw

RI0CAwEAAaAvMBMGCSqGSIb3DQEJBzEGEwRjaGVuMBgGCSqGSIb3DQEJAjELEwlu

ZXRraWxsZXIwDQYJKoZIhvcNAQEEBQADgYEACUoc5Yd6nG9p7c0Rjba82uBK9Xoz

cA1fKGOCeTlrpa4Ce4fLhnQuK+vsIzvcAiUpAnTnknbtNOFj6e/cEjMxhDHOs9Ty

SZKlLF4KPXP4H5WPcfkt7utKnIwTpSai0knDfmnHG3O7WY2cv92sS8RBArE8psnJ

6wCzdS3iqymzhXU=

-----END CERTIFICATE REQUEST-----

 

2.         生产秘钥文件:

-bash-2.05b$ openssl rsa -in privkey.pem -out server.key

read RSA key

Enter PEM pass phrase:

writing RSA key

-bash-2.05b$ ls

base    pg_clog      pg_ident.conf  pg_xlog          postmaster.opts  privkey.pem  server.req

global  pg_hba.conf  PG_VERSION     postgresql.conf  postmaster.pid   server.key

-bash-2.05b$

 

注意上面的privkey.pem server.key文件,我们来看看它们的内容:

-bash-2.05b$ cat privkey.pem

-----BEGIN RSA PRIVATE KEY-----

Proc-Type: 4,ENCRYPTED

DEK-Info: DES-EDE3-CBC,EE59B06E786A2FCA

 

C8RnlMX5tF7CRdx/jxHk/2D4SUu+PVNfphwDbsytmUJIx5qMQAHxCy+NdIDZX9L/

AWIwaShdwFOaP6CMwrzBav54DW1/IlbF688X3DA6xUY1+ZvV4RU4t1O6EhEPINth

1KBqgtSw8lnu6HQa6aIFvZ4f/Wqluk04ylGe4CLLW1xPQ36ntw3tFXPm3eIFl3wQ

lNxYjNTxSjA9x5IBzyJpaJJk27f+/WJARDkFKOwUn9J71lPC5yYybv6IG65xFg6/

kpLqfzx/wAaJxReB/EP95jLVkEmzyi6rqzsBLLgAl6mxGGN5kT34lfK4v9xuRWRz

J2AlBJnloq8NTE48N2g7N1UqHl0r3nNkLdfYEeq6th7d12hiSAcGECvSfhlWirsx

sFYcrAhBGCK+4OXjn717AYeAYw+/JPrX0ZuDVFogVKNB9x/S15+y8yh2AgIUjpJ/

BOZ3LCxXyFznu4yBvxNoTOJT2xWuAXVk5AI3UftOfBAvRZdayAwh6LdoNG77ead1

hNwIAvS5LUiLG8KeAbQHlJuh51YCpmEBCsTqrZybMNoEAiCg0Gn/5tE5cfVmH3Ei

LjhCTtRJ6oGx6dsYaY4A1Jt1+B8DMNnRTez8NN5D2+4wasr4dTYwsRXRyqMCPZJH

+z8m6zautVoHlhGQhRxO4ZcBunyJrdW5XQBGfAcUbp1xORCvqP+SW8Z4wDyu2Sk+

MlxPL1T4P3xEANG7hOlsabBiQ2kyCq1iiJCHBlfXxIm86c1ffRYTrdB+PoFyyaII

ErS68kMbv+Y5Tr+X3Ml1AMNEEU5YAn/O1wSoL5Cz0nIpKeknKAl/vA==

-----END RSA PRIVATE KEY-----

 

-bash-2.05b$ cat server.key

-----BEGIN RSA PRIVATE KEY-----

MIICXAIBAAKBgQClMJrvdZ9AQO6QTgb39wvel9AaLkjvTHvCzfL0MBv0x51lelPX

13zqJY++sFf1iZEugEz/8ZYeQgYBZJ+YaSTBf+YMpa65nEwp26OjPXbaicAzKcWl

i3rh5fQ7831U1GX6yMAcEQccJAOO8GHZcM/63eIESjHCYypfROxIaDBEjQIDAQAB

AoGABMbGBByLkUkPXN7UtsDO+A29t7QU6c51Wamo18S4WjiXZYLG/9u8Qez6HhJt

SK1EpGqTT2dF5vQTxmCJeNe5d078YIFCbIQckgG2hLSsRyV8QclSguJLC5Tgvzua

tTFdVH50UbyAtkifiR3wt5qBuIjtxz/v0ePJ2EdhcdCAqQUCQQDUarpjOof/hTKb

wwOyJIVDycQs27dF+LiGD6YxD97WC6iZR5u7YukqzJk+GXi9EbjdQzybkp1oxDuF

LQAFXJoDAkEAxxVCo1MgYiKtc2lqSr/q2j1R//sPQq5ajv7pvU1WGhx3xS2iZt9l

/jzNx6ZUG7hxd5gi6G6I3UFAFoOLq06qLwJAPT7InvOxYqs0/FQuLJ77DaCPP5/a

KAKesYixklPRHEYgRpGvBUhvkjeLt6wAdAM4GhPY1cJgQGTUBIIFD4azoQJAVjap

xgrwoi78SFelVTupW9tkUGOL50eUJgrUdEsyd1pOr9AkXUJva9svDj/EesC0OqNi

sp9zm8VvGJDdAlGttwJBAMEnnl9ZGglIBRbS7srVLHhXFYs+xkQgTW6bvcQ+aW+G

MW/vpVcsFzSuaAtlBVoZ1ltCRGPSbVgQkp14yqGITQg=

-----END RSA PRIVATE KEY-----

 

上面的privkey.pem server.key文件内容一看就知道是BASE64编码的,我对它的内容也很好奇,将它解码看看内容是什么:

0?\[1][1]?u@N ?.H{峦螋0羟漞zS|?従痒鯄?€L‑Bdi$??ギ箿L)?v?)钮娲徨?T詄?$


a赏销葩
J1
*_Dh0D?
[1]



I\拊独硒椒?uY啄窜8梕偲A‑mH璂揙gE芵墄坠wN黗丅l??秳船G%|A蒖傗K ?1]T~tQ紑禜焿鸱殎笀砬?镅闵溪aq?[1]A詊篶:??
?
匔赡,E?? Gb?>x?C<洅汉??\?[1]A?B b"ijJ?Q?B罂廅榻MVw?沓?颓w?镴堓A@儖玁?[1]@=>葹蟊b?.,烕爮?([1]灡埍扴?F FHo?t
8
卣耟@d???@V6 .W;踕PcG? K2wZN$]Bok?
?胶来:矡so[1]Q[1]A?Y H翌收,xW? Mn?io?oW,4 eZ諿BDcXx省圡

看来是二制的,哈哈。

3.         产生证书文件:

-bash-2.05b$ openssl req -x509 -in server.req -text -key server.key -out server. crt

Using configuration from /usr/share/ssl/openssl.cnf

-bash-2.05b$

-bash-2.05b$ cat server.crt

Certificate:

    Data:

        Version: 3 (0x2)

        Serial Number: 0 (0x0)

        Signature Algorithm: md5WithRSAEncryption

        Issuer: C=CN, ST=Guang Zhou, L=Shen Zhen, O=Open Source Organization, OU=technical, CN=www.9812.net/Email=openunix@163.com

        Validity

            Not Before: Oct 25 01:13:05 2003 GMT

            Not After : Nov 24 01:13:05 2003 GMT

        Subject: C=CN, ST=Guang Zhou, L=Shen Zhen, O=Open Source Organization, OU=technical, CN=www.9812.net/Email=openunix@163.com

        Subject Public Key Info:

            Public Key Algorithm: rsaEncryption

            RSA Public Key: (1024 bit)

                Modulus (1024 bit):

                    00:a5:30:9a:ef:75:9f:40:40:ee:90:4e:06:f7:f7:

                    0b:de:97:d0:1a:2e:48:ef:4c:7b:c2:cd:f2:f4:30:

                    1b:f4:c7:9d:65:7a:53:d7:d7:7c:ea:25:8f:be:b0:

                    57:f5:89:91:2e:80:4c:ff:f1:96:1e:42:06:01:64:

                    9f:98:69:24:c1:7f:e6:0c:a5:ae:b9:9c:4c:29:db:

                    a3:a3:3d:76:da:89:c0:33:29:c5:a5:8b:7a:e1:e5:

                    f4:3b:f3:7d:54:d4:65:fa:c8:c0:1c:11:07:1c:24:

                    03:8e:f0:61:d9:70:cf:fa:dd:e2:04:4a:31:c2:63:

                    2a:5f:44:ec:48:68:30:44:8d

                Exponent: 65537 (0x10001)

        X509v3 extensions:

            X509v3 Subject Key Identifier:

                93:4F:D5:41:4A:CA:A2:83:19:C3:5D:BE:58:E6:45:70:7E:95:A5:0A

            X509v3 Authority Key Identifier:

                keyid:93:4F:D5:41:4A:CA:A2:83:19:C3:5D:BE:58:E6:45:70:7E:95:A5:0A

                DirName:/C=CN/ST=Guang Zhou/L=Shen Zhen/O=Open Source Organization/OU=technical/CN=www.9812.net/Email=openunix@163.com

                serial:00

 

            X509v3 Basic Constraints:

                CA:TRUE

    Signature Algorithm: md5WithRSAEncryption

        3f:f1:99:89:37:ec:1b:80:e2:c6:3a:8e:ed:e8:94:b8:70:10:

        34:1c:9a:ef:f7:be:b7:05:51:f4:a2:cb:03:4e:f4:dd:6f:73:

        51:49:d2:91:fc:eb:40:3c:30:54:b6:f0:aa:a1:e8:d4:33:b2:

        9b:d0:0e:0d:b4:4b:65:c5:ae:bf:ed:fa:ff:1c:e6:1d:aa:41:

        4f:da:76:7a:57:7d:8d:f5:1b:17:65:fc:63:4f:db:dd:45:33:

        3d:e7:c9:dd:e8:d6:8d:6f:a5:d7:97:da:7f:cf:09:15:ab:2f:

        0a:f3:70:e0:d0:d3:50:90:05:78:92:ac:8a:17:78:23:b7:66:

        c6:55

-----BEGIN CERTIFICATE-----

MIID0DCCAzmgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBpzELMAkGA1UEBhMCQ04x

EzARBgNVBAgTCkd1YW5nIFpob3UxEjAQBgNVBAcTCVNoZW4gWmhlbjEhMB8GA1UE

ChMYT3BlbiBTb3VyY2UgT3JnYW5pemF0aW9uMRIwEAYDVQQLEwl0ZWNobmljYWwx

FTATBgNVBAMTDHd3dy45ODEyLm5ldDEhMB8GCSqGSIb3DQEJARYSbmV0a2lsbGVy

QDk4MTIubmV0MB4XDTAzMTAyNTAxMTMwNVoXDTAzMTEyNDAxMTMwNVowgacxCzAJ

BgNVBAYTAkNOMRMwEQYDVQQIEwpHdWFuZyBaaG91MRIwEAYDVQQHEwlTaGVuIFpo

ZW4xITAfBgNVBAoTGE9wZW4gU291cmNlIE9yZ2FuaXphdGlvbjESMBAGA1UECxMJ

dGVjaG5pY2FsMRUwEwYDVQQDEwx3d3cuOTgxMi5uZXQxITAfBgkqhkiG9w0BCQEW

Em5ldGtpbGxlckA5ODEyLm5ldDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA

pTCa73WfQEDukE4G9/cL3pfQGi5I70x7ws3y9DAb9MedZXpT19d86iWPvrBX9YmR

LoBM//GWHkIGAWSfmGkkwX/mDKWuuZxMKdujoz122onAMynFpYt64eX0O/N9VNRl

+sjAHBEHHCQDjvBh2XDP+t3iBEoxwmMqX0TsSGgwRI0CAwEAAaOCAQgwggEEMB0G

A1UdDgQWBBSTT9VBSsqigxnDXb5Y5kVwfpWlCjCB1AYDVR0jBIHMMIHJgBSTT9VB

SsqigxnDXb5Y5kVwfpWlCqGBraSBqjCBpzELMAkGA1UEBhMCQ04xEzARBgNVBAgT

Ckd1YW5nIFpob3UxEjAQBgNVBAcTCVNoZW4gWmhlbjEhMB8GA1UEChMYT3BlbiBT

b3VyY2UgT3JnYW5pemF0aW9uMRIwEAYDVQQLEwl0ZWNobmljYWwxFTATBgNVBAMT

DHd3dy45ODEyLm5ldDEhMB8GCSqGSIb3DQEJARYSbmV0a2lsbGVyQDk4MTIubmV0

ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAP/GZiTfsG4DixjqO

7eiUuHAQNBya7/e+twVR9KLLA0703W9zUUnSkfzrQDwwVLbwqqHo1DOym9AODbRL

ZcWuv+36/xzmHapBT9p2eld9jfUbF2X8Y0/b3UUzPefJ3ejWjW+l15faf88JFasv

CvNw4NDTUJAFeJKsihd4I7dmxlU=

-----END CERTIFICATE-----

-bash-2.05b$

 

4.         权限方面:

删除rm privkey.pem文件,server.key权限设为600

-bash-2.05b$ rm privkey.pem

-bash-2.05b$ chmod og-rwx server.key

-bash-2.05b$ ls -l

total 56

drwx------   10 postgres postgres     4096 Oct 23 12:03 base

drwx------    2 postgres postgres     4096 Oct 25 08:35 global

drwx------    2 postgres postgres     4096 Jul  8 17:01 pg_clog

-rw-------    1 postgres postgres     2714 Jul  8 17:57 pg_hba.conf

-rw-------    1 postgres postgres     1441 Jul  8 17:01 pg_ident.conf

-rw-------    1 postgres postgres        4 Jul  8 17:01 PG_VERSION

drwx------    2 postgres postgres     4096 Oct 15 01:03 pg_xlog

-rw-------    1 postgres postgres     5336 Oct 24 17:01 postgresql.conf

-rw-------    1 postgres postgres       32 Oct 25 08:35 postmaster.opts

-rw-------    1 postgres postgres       44 Oct 25 08:35 postmaster.pid

-rw-r--r--    1 postgres postgres     3670 Oct 25 09:13 server.crt

-rw-------    1 postgres postgres      887 Oct 25 09:04 server.key

-rw-r--r--    1 postgres postgres     2377 Oct 25 08:59 server.req

-bash-2.05b$

 

5.         配置postgresql.conf文件:

开启SSL。将#ssl = false改为ssl = true

-bash-2.05b$ vi postgresql.conf

ssl = true

 

我的postgresql.conf文件:

-bash-2.05b$ cat postgresql.conf

#

# PostgreSQL configuration file

# -----------------------------

#

# This file consists of lines of the form:

#

#   name = value

#

# (The '=' is optional.) White space may be used. Comments are introduced

# with '#' anywhere on a line. The complete list of option names and

# allowed values can be found in the PostgreSQL documentation. The

# commented-out settings shown in this file represent the default values.

#

# Any option can also be given as a command line switch to the

# postmaster, e.g. 'postmaster -c log_connections=on'. Some options

# can be changed at run-time with the 'SET' SQL command.

#

# This file is read on postmaster startup and when the postmaster

# receives a SIGHUP. If you edit the file on a running system, you have

# to SIGHUP the postmaster for the changes to take effect, or use

# "pg_ctl reload".

 

 

#========================================================================

 

 

#

#       Connection Parameters

#

#tcpip_socket = false

 

tcpip_socket = true

 

#ssl = false

ssl = true

 

#max_connections = 32

max_connections = 100

#superuser_reserved_connections = 2

 

#port = 5432

#hostname_lookup = false

#show_source_port = false

 

#unix_socket_directory = ''

#unix_socket_group = ''

#unix_socket_permissions = 0777 # octal

 

#virtual_host = ''

 

#krb_server_keyfile = ''

 

 

#

#       Shared Memory Size

#

#shared_buffers = 64            # min max_connections*2 or 16, 8KB each

shared_buffers = 200            # min max_connections*2 or 16, 8KB each

#max_fsm_relations = 1000       # min 10, fsm is free space map, ~40 bytes

#max_fsm_pages = 10000          # min 1000, fsm is free space map, ~6 bytes

#max_locks_per_transaction = 64 # min 10

#wal_buffers = 8                # min 4, typically 8KB each

 

#

#       Non-shared Memory Sizes

#

#sort_mem = 1024                # min 64, size in KB

#vacuum_mem = 8192              # min 1024, size in KB

 

 

#

#       Write-ahead log (WAL)

#

#checkpoint_segments = 3        # in logfile segments, min 1, 16MB each

#checkpoint_timeout = 300       # range 30-3600, in seconds

#

#commit_delay = 0               # range 0-100000, in microseconds

#commit_siblings = 5            # range 1-1000

#

#fsync = true

#wal_sync_method = fsync        # the default varies across platforms:

#                               # fsync, fdatasync, open_sync, or open_datasync

#wal_debug = 0                  # range 0-16

 

 

#

#       Optimizer Parameters

#

#enable_seqscan = true

#enable_indexscan = true

#enable_tidscan = true

#enable_sort = true

#enable_nestloop = true

#enable_mergejoin = true

#enable_hashjoin = true

 

#effective_cache_size = 1000    # typically 8KB each

#random_page_cost = 4           # units are one sequential page fetch cost

#cpu_tuple_cost = 0.01          # (same)

#cpu_index_tuple_cost = 0.001   # (same)

#cpu_operator_cost = 0.0025     # (same)

 

#default_statistics_target = 10 # range 1-1000

 

#

#       GEQO Optimizer Parameters

#

#geqo = true

#geqo_selection_bias = 2.0      # range 1.5-2.0

#geqo_threshold = 11

#geqo_pool_size = 0             # default based on tables in statement,

                                # range 128-1024

#geqo_effort = 1

#geqo_generations = 0

#geqo_random_seed = -1          # auto-compute seed

 

 

#

#       Message display

#

#server_min_messages = notice   # Values, in order of decreasing detail:

                                #   debug5, debug4, debug3, debug2, debug1,

                                #   info, notice, warning, error, log, fatal,

                                #   panic

#client_min_messages = notice   # Values, in order of decreasing detail:

                                #   debug5, debug4, debug3, debug2, debug1,

                                #   log, info, notice, warning, error

#silent_mode = false

 

#log_connections = false

#log_pid = false

#log_statement = false

#log_duration = false

#log_timestamp = false

 

#log_min_error_statement = panic # Values in order of increasing severity:

                                 #   debug5, debug4, debug3, debug2, debug1,

                                 #   info, notice, warning, error, panic(off)

 

#debug_print_parse = false

#debug_print_rewritten = false

#debug_print_plan = false

#debug_pretty_print = false

 

#explain_pretty_print = true

 

# requires USE_ASSERT_CHECKING

#debug_assertions = true

 

 

#

#       Syslog

#

#syslog = 0                     # range 0-2

#syslog_facility = 'LOCAL0'

#syslog_ident = 'postgres'

 

 

#

#       Statistics

#

#show_parser_stats = false

#show_planner_stats = false

#show_executor_stats = false

#show_statement_stats = false

 

# requires BTREE_BUILD_STATS

#show_btree_build_stats = false

 

 

#

#       Access statistics collection

#

#stats_start_collector = true

#stats_reset_on_server_start = true

#stats_command_string = false

#stats_row_level = false

#stats_block_level = false

 

 

#

#       Lock Tracing

#

#trace_notify = false

 

# requires LOCK_DEBUG

#trace_locks = false

#trace_userlocks = false

#trace_lwlocks = false

#debug_deadlocks = false

#trace_lock_oidmin = 16384

#trace_lock_table = 0

 

 

#

#       Misc

#

#autocommit = true

#dynamic_library_path = '$libdir'

#search_path = '$user,public'

#datestyle = 'iso, us'

#timezone = unknown             # actually, defaults to TZ environment setting

#australian_timezones = false

#client_encoding = sql_ascii    # actually, defaults to database encoding

#authentication_timeout = 60    # 1-600, in seconds

#deadlock_timeout = 1000        # in milliseconds

#default_transaction_isolation = 'read committed'

#max_expr_depth = 10000         # min 10

#max_files_per_process = 1000   # min 25

#password_encryption = true

#sql_inheritance = true

#transform_null_equals = false

#statement_timeout = 0          # 0 is disabled, in milliseconds

#db_user_namespace = false

 

 

 

#

#       Locale settings

#

# (initialized by initdb -- may be changed)

LC_MESSAGES = 'en_US.UTF-8'

LC_MONETARY = 'en_US.UTF-8'

LC_NUMERIC = 'en_US.UTF-8'

LC_TIME = 'en_US.UTF-8'

 

6.         测试SSL

[root@linux root]# psql -h 127.0.0.1 -Uchen member

Welcome to psql 7.3.3, the PostgreSQL interactive terminal.

 

Type:  \copyright for distribution terms

       \h for help with SQL commands

       \? for help on internal slash commands

       \g or terminate with semicolon to execute query

       \q to quit

 

member=> \q

[root@linux root]# service postgresql restart

                                                     [  OK  ]

Starting postgresql service:                               [  OK  ]

[root@linux root]

[root@linux root]# psql -h 127.0.0.1 -Uchen member

Welcome to psql 7.3.3, the PostgreSQL interactive terminal.

 

Type:  \copyright for distribution terms

       \h for help with SQL commands

       \? for help on internal slash commands

       \g or terminate with semicolon to execute query

       \q to quit

 

SSL connection (cipher: EDH-RSA-DES-CBC3-SHA, bits: 168)

 

member=>

 

登陆后下方显示SSL connection (cipher: EDH-RSA-DES-CBC3-SHA, bits: 168)恭喜你成功了!

 

服务器将在同一个 TCP 端口上同时监听标准的和SSL的联接,并且将与任何正在联接的客户端进行协商,协商是否使用SSL.参阅 Chapter 19 获取如何强制服务器端只使用SSL进行某些联接的信息.这段引用http://www.pgsqldb.org/pgsqldoc-cvs/ssl-tcp.html

 

7.         配置pg_hba.conf强制使用SSL联接:

-bash-2.05b$ vi pg_hba.conf

hostssl    all         all         127.0.0.1         255.255.255.255   md5

 

8.         连接测试:

[root@linux8 root]# service postgresql restart

                                                     [  OK  ]

Starting postgresql service:                               [  OK  ]

[root@linux8 root]# psql -h 127.0.0.1 -Uchen member

Welcome to psql 7.3.3, the PostgreSQL interactive terminal.

 

Type:  \copyright for distribution terms

       \h for help with SQL commands

       \? for help on internal slash commands

       \g or terminate with semicolon to execute query

       \q to quit

 

SSL connection (cipher: EDH-RSA-DES-CBC3-SHA, bits: 168)

 

member=>

 

我的pg_hba.conf文件:

-bash-2.05b$ cat pg_hba.conf

# PostgreSQL Client Authentication Configuration File

# ===================================================

#

# Refer to the PostgreSQL Administrator's Guide, chapter "Client

# Authentication" for a complete description.  A short synopsis

# follows.

#

# This file controls: which hosts are allowed to connect, how clients

# are authenticated, which PostgreSQL user names they can use, which

# databases they can access.  Records take one of three forms:

#

# local    DATABASE  USER  METHOD  [OPTION]

# host     DATABASE  USER  IP-ADDRESS  IP-MASK  METHOD  [OPTION]

# hostssl  DATABASE  USER  IP-ADDRESS  IP-MASK  METHOD  [OPTION]

#

# (The uppercase quantities should be replaced by actual values.)

# DATABASE can be "all", "sameuser", "samegroup", a database name (or

# a comma-separated list thereof), or a file name prefixed with "@".

# USER can be "all", an actual user name or a group name prefixed with

# "+" or a list containing either.  IP-ADDRESS and IP-MASK specify the

# set of hosts the record matches.  METHOD can be "trust", "reject",

# "md5", "crypt", "password", "krb4", "krb5", "ident", or "pam".  Note

# that "password" uses clear-text passwords; "md5" is preferred for

# encrypted passwords.  OPTION is the ident map or the name of the PAM

# service.

#

# This file is read on server startup and when the postmaster receives

# a SIGHUP signal.  If you edit the file on a running system, you have

# to SIGHUP the postmaster for the changes to take effect, or use

# "pg_ctl reload".

 

# Put your actual configuration here

# ----------------------------------

#

# CAUTION: The default configuration allows any local user to connect

# using any PostgreSQL user name, including the superuser, over either

# Unix-domain sockets or TCP/IP.  If you are on a multiple-user

# machine, the default configuration is probably too liberal for you.

# Change it to use something other than "trust" authentication.

#

# If you want to allow non-local connections, you need to add more

# "host" records.  Also, remember TCP/IP connections are only enabled

# if you enable "tcpip_socket" in postgresql.conf.

 

# TYPE  DATABASE    USER        IP-ADDRESS        IP-MASK           METHOD

 

local   all         all                                             trust

host    all         all         127.0.0.1         255.255.255.255   trust

 

# Using sockets credentials for improved security. Not available everywhere,

# but works on Linux, *BSD (and probably some others)

 

#local  all     all             ident   sameuser

#host    all         all         127.0.0.1         255.255.255.255   md5

#local   all         all                                             trust

#host    all         all         0.0.0.0           0.0.0.0           md5

hostssl    all         all         127.0.0.1         255.255.255.255   md5

 

9.         注意事项:

1.         秘钥和证书(server.keyserver.crt)必须放在data目前中,即与postgresql.conf同在一个目录中

2.         server.key权限必须设为600,所有者为postgres,否则会提示你权限或用户、组不正确。

3.         删除privkey.pem文件

2.9.2   使用SSH进行安全TCP/IP联接

SSH帮助信息,注意-L-R两个参数:

[chen@linux chen]$ ssh --help

Usage: ssh [options] host [command]

Options:

  -l user     Log in using this user name.

  -n          Redirect input from /dev/null.

  -F config   Config file (default: ~/.ssh/config).

  -A          Enable authentication agent forwarding.

  -a          Disable authentication agent forwarding (default).

  -X          Enable X11 connection forwarding.

  -x          Disable X11 connection forwarding (default).

  -i file     Identity for public key authentication (default: ~/.ssh/identity)

  -t          Tty; allocate a tty even if command is given.

  -T          Do not allocate a tty.

  -v          Verbose; display verbose debugging messages.

              Multiple -v increases verbosity.

  -V          Display version number only.

  -P          Don't allocate a privileged port.

  -q          Quiet; don't display any warning messages.

  -f          Fork into background after authentication.

  -e char     Set escape character; ``none'' = disable (default: ~).

  -c cipher   Select encryption algorithm

  -m macs     Specify MAC algorithms for protocol version 2.

  -p port     Connect to this port.  Server must be on the same port.

  -L listen-port:host:port   Forward local port to remote address

  -R listen-port:host:port   Forward remote port to local address

              These cause ssh to listen for connections on a port, and

              forward them to the other side by connecting to host:port.

  -D port     Enable dynamic application-level port forwarding.

  -C          Enable compression.

  -N          Do not execute a shell or command.

  -g          Allow remote hosts to connect to forwarded ports.

  -1          Force protocol version 1.

  -2          Force protocol version 2.

  -4          Use IPv4 only.

  -6          Use IPv6 only.

  -o 'option' Process the option as if it was read from a configuration file.

  -s          Invoke command (mandatory) as SSH2 subsystem.

  -b addr     Local IP address.

 

说明:

  -L listen-port:host:port   转发本地端口到远程地址

  -R listen-port:host:port   转发远程端口到本地地址

使用方法:

ssh –L 本地端口:连接PostgreSQLhost:5432 登录用户@要转发的远程主机

[root@linux8 root]# ssh –L 3333:localhost:5432 root@127.0.0.1

root@127.0.0.1’s password:

Last login: Sat Oct 25 09:27:30 2003 from 192.168.1.2

[root@linux8 root]# psql –p3333 –Uchen

psql: could not connect to server: No such file or directory

        Is the server running locally and accepting

        Connections on Unix domain socket “/tmp/.s.PGSQL.3333”?

[root@linux8 root]# psql –p3333 –Uchen member

psql: could not connect to server: No such file or directory

        Is the server running locally and accepting

        Connections on Unix domain socket “/tmp/.s.PGSQL.3333”?

[root@linux8 root]# psql –h 127.0.0.1 –p3333 –Uchen member

Welcome to psql 7.3.3, the PostgreSQL interactive terminal.

 

Type:  \copyright for distribution terms

       \h for help with SQL commands

       \? For help on internal slash commands

       \g or terminate with semicolon to execute query

       \q to quit

 

SSL connection (cipher: EDH-RSA-DES-CBC3-SHA, bits: 168)

 

Member=>

注意:我上面用了SSH+SSL。服务器àSSHàSSL-------Fast Ethernet------ SSLàSSHà客户端

 

实例:

请看上面图片,现在假设server1应用服务器,server2是数据库数据服务器。现在要从server1连接通过SSH连接server2

server1环境:

       IP192.168.0.1

       域名:client.9812.net

server2环境:

       IP192.168.0.2

       域名:server.9812.net

SSH命令:

       登陆server1输入命令

       server1$ ssh -f –n –L 8000:server.9812.net:5432 server.9812.net

       server1$ psql –h 127.0.0.1 –p 8000 –Unetkiller mydb

2.10       连接ipv6主机

控制台1

login as: root

Sent username "root"

root@192.168.1.4's password:

Last login: Sun Dec 28 13:07:40 2003 from 192.168.1.3

[root@linux9 root]# ifconfig

eth0      Link encap:Ethernet  HWaddr 00:0C:29:09:0B:60

          inet addr:192.168.1.4  Bcast:192.168.1.255  Mask:255.255.255.0

          inet6 addr: fe80::20c:29ff:fe09:b60/64 Scope:Link

          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

          RX packets:34364 errors:0 dropped:0 overruns:0 frame:0

          TX packets:29074 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:100

          RX bytes:22502007 (21.4 Mb)  TX bytes:3561608 (3.3 Mb)

          Interrupt:10 Base address:0x10e0

 

lo        Link encap:Local Loopback

          inet addr:127.0.0.1  Mask:255.0.0.0

          inet6 addr: ::1/128 Scope:Host

          UP LOOPBACK RUNNING  MTU:16436  Metric:1

          RX packets:114 errors:0 dropped:0 overruns:0 frame:0

          TX packets:114 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:0

          RX bytes:10918 (10.6 Kb)  TX bytes:10918 (10.6 Kb)

 

[root@linux9 root]# ifconfig eth0 inet6 add 3ffe:ffff:0:f101::1/64

[root@linux9 root]# ifconfig

eth0      Link encap:Ethernet  HWaddr 00:0C:29:09:0B:60

          inet addr:192.168.1.4  Bcast:192.168.1.255  Mask:255.255.255.0

          inet6 addr: 3ffe:ffff:0:f101::1/64 Scope:Global

          inet6 addr: fe80::20c:29ff:fe09:b60/64 Scope:Link

          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

          RX packets:34392 errors:0 dropped:0 overruns:0 frame:0

          TX packets:29106 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:100

          RX bytes:22503903 (21.4 Mb)  TX bytes:3565060 (3.3 Mb)

          Interrupt:10 Base address:0x10e0

 

lo        Link encap:Local Loopback

          inet addr:127.0.0.1  Mask:255.0.0.0

          inet6 addr: ::1/128 Scope:Host

          UP LOOPBACK RUNNING  MTU:16436  Metric:1

          RX packets:114 errors:0 dropped:0 overruns:0 frame:0

          TX packets:114 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:0

          RX bytes:10918 (10.6 Kb)  TX bytes:10918 (10.6 Kb)

 

[root@linux9 root]#

[root@linux9 root]# ping6 3ffe:ffff:0:f101::1

PING 3ffe:ffff:0:f101::1(3ffe:ffff:0:f101::1) 56 data bytes

64 bytes from 3ffe:ffff:0:f101::1: icmp_seq=1 ttl=64 time=0.863 ms

64 bytes from 3ffe:ffff:0:f101::1: icmp_seq=2 ttl=64 time=0.099 ms

64 bytes from 3ffe:ffff:0:f101::1: icmp_seq=3 ttl=64 time=0.086 ms

64 bytes from 3ffe:ffff:0:f101::1: icmp_seq=4 ttl=64 time=0.080 ms

64 bytes from 3ffe:ffff:0:f101::1: icmp_seq=5 ttl=64 time=0.124 ms

 

--- 3ffe:ffff:0:f101::1 ping statistics ---

5 packets transmitted, 5 received, 0% packet loss, time 4011ms

rtt min/avg/max/mdev = 0.080/0.250/0.863/0.307 ms

[root@linux9 root]#

 

测试

[root@linux classes]# ssh -6 chen@::1

chen@::1's password:

[chen@linux chen]$

 

 

控制台2

[root@linux9 root]# service postgresql start

Initializing database:                                     [  OK  ]

Starting postgresql service:                               [  OK  ]

[root@linux9 root]# su postgres

bash-2.05b$ createdb -E unicode

CREATE DATABASE

bash-2.05b$ psql -l

        List of databases

   Name    |  Owner   | Encoding

-----------+----------+-----------

 postgres  | postgres | UNICODE

 template0 | postgres | SQL_ASCII

 template1 | postgres | SQL_ASCII

(3 rows)

 

bash-2.05b$ psql

Welcome to psql 7.3.2, the PostgreSQL interactive terminal.

 

Type:  \copyright for distribution terms

       \h for help with SQL commands

       \? for help on internal slash commands

       \g or terminate with semicolon to execute query

       \q to quit

 

postgres=# \q

 

配置pg_hba.conf

 

bash-2.05b$ vi /var/lib/pgsql/data/pg_hba.conf

local  all      all             ident   sameuser

host   all      all     3ffe:ffff:0:f101::1/64   trust

 

 

3       数据定义(DDL

3.1    日期时间常量

3.1.1   当前日期

current_date

netkiller=> select current_date;

    date

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

 2003-11-28

(1 row)

 

netkiller=>

 

3.1.2   当前时间

current_time

netkiller=> select current_time;

       timetz

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

 19:38:47.270235+08

(1 row)

 

netkiller=>

 

3.1.3   当前日期时间

current_timestamp

netkiller=> select current_timestamp;

          timestamptz

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

 2003-11-28 19:39:25.548505+08

(1 row)

 

netkiller=>

3.1.4   除去时区

1.         current_timestamp::timestamp (0)

2.         current_timestamp::timestamp (0) without time zone;

netkiller=> select current_timestamp::timestamp (0);

      timestamp

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

 2003-11-28 19:44:33

(1 row)

 

netkiller=>

netkiller=> select current_timestamp::timestamp (0) without time zone;

      timestamp

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

 2003-11-28 19:40:10

(1 row)

 

netkiller=>

3.1.5   计算时间差

netkiller=> select to_date('2003-12-2','YYYY-MM-DD')-to_date('2003-12-1','YYYY-MM-DD');

?column?

----------

1

(1 row)

 

netkiller=>

netkiller=> select to_date('2003-12-2','YYYY-MM-DD')-to_date('2003-10-2','YYYY-MM-DD');

?column?

----------

61

(1 row)

3.1.6   计算时间和

netkiller=> select to_date('2003-12-6','yyyy-mm-dd')+12 ;
?column?
------------
2003-12-18
(1 row)

netkiller=> select to_date('2003-12-6','yyyy-mm-dd')+20 ;
?column?
------------
2003-12-26
(1 row)

3.1.7   date_part

netkiller=> select date_part('epoch', '2003-12-3 10:20:30' - timestamp '2003-12-1 02:00:00') ;

 date_part

-----------

    202830

(1 row)

 

netkiller=> select date_part('day', '2003-12-3 10:20:30' - timestamp '2003-12-1 02:00:00') ;

 date_part

-----------

         2

(1 row)

 

netkiller=> select date_part('hour', '2003-12-3 10:20:30' - timestamp '2003-12-1 02:00:00') ;

date_part

-----------

         8

(1 row)

 

netkiller=>

详细使用方法请参考http://www.pgsqldb.org上的文档。

3.2    汉字做字段名

PostgreSQL是支持“区域”,“字符集支持”的,允许你使用本区域的字符集做为字段名。但要注意,你的终端要支持该字符集支持。我这里使用UNICODEEUC_CN也适用。

 

Create table ""(

       "序号" Serial NOT NULL UNIQUE,

       "组名" Varchar(20) NOT NULL,

       "描述" Varchar(255),

       UNIQUE ("组名"),

      PRIMARY KEY ("序号")

);

 

创建表:

member=> Create table ""(

member(> "序号" Serial NOT NULL UNIQUE,

member(> "组名" Varchar(20) NOT NULL,

member(> "描述" Varchar(255),

member(> UNIQUE ("组名"),

member(>  PRIMARY KEY ("序号")

member(> );

NOTICE:  CREATE TABLE will create implicit sequence '_序号_seq' for SERIAL column '.序号'

NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index '_pkey' for table ''

NOTICE:  CREATE TABLE / UNIQUE will create implicit index '_组名_key' for table ''

CREATE TABLE

member=> \d

               List of relations

 Schema |        Name        |   Type   | Owner

--------+--------------------+----------+-------

 public | group              | table    | chen

 public | group_id_seq       | sequence | chen

 public | groupmember        | table    | chen

 public | groupmember_id_seq | sequence | chen

 public | role               | table    | chen

 public | role_id_seq        | sequence | chen

 public | rolemember         | table    | chen

 public | rolemember_id_seq  | sequence | chen

 public | system_log         | table    | chen

 public | system_log_id_seq  | sequence | chen

 public | trust              | table    | chen

 public | trust_id_seq       | sequence | chen

 public | user               | table    | chen

 public | user_id_seq        | sequence | chen

 public | user_log           | table    | chen

 public | user_log_id_seq    | sequence | chen

 public | userinfo           | table    | chen

 public | userinfo_id_seq    | sequence | chen

 public | vgroup             | view     | chen

 public | vgroupmember       | view     | chen

 public | vsystem_log        | view     | chen

 public | vuser              | view     | chen

 public |                 | table    | chen

 public | _序号_seq     | sequence | chen

(24 rows)

 

查看表结构:

 

member=> \d

                                     Table "public."

 Column |          Type          |                         Modifiers           

--------+------------------------+-----------------------------------------------------------

 序号 | integer                | not null default nextval('public."_序号_seq"'::text)

 组名 | character varying(20)  | not null

 描述 | character varying(255) |

Indexes: _pkey primary key btree ("序号"),

         _组名_key unique btree ("组名")

 

插入数据:

member=> insert into (组名,描述) values('域用户','9812.net域内用户');

INSERT 110971 1

member=> insert into ""("组名","描述") values('域用户','9812.net域内用户');

ERROR:  Cannot insert a duplicate key into unique index _组名_key

member=> insert into ""("组名","描述") values('计算机维护组','维护计算机的用户用户');

INSERT 110973 1

 

查看数据:

member=> select * from ;

 序号 |       组名       |             描述

--------+--------------------+--------------------------------

      1 | 域用户          | 9812.net域内用户

      3 | 计算机维护组 | 维护计算机的用户用户

(2 rows)

member=> select * from "";

 序号 |       组名       |             描述

--------+--------------------+--------------------------------

      1 | 域用户          | 9812.net域内用户

      3 | 计算机维护组 | 维护计算机的用户用户

(2 rows)

 

注:在操作非英文字段的表时。建议最好前,后加上“"”,“"”符号。并非所有API支持非英文的编码。

3.3    “::”数据转换

PostgreSQL 数据之间的转换可以使用“::”操作符。

3.3.1   text to varchar

vperson gender字段为布尔型(boolean)在视图中要显示为true显示为“先生”,false显示为“女士”CASE WHEN 表达式应该是:

CASE WHEN p.gender = true THEN '先生' ELSE '女士' END as gender,

直接使用'先生', '女士' PostgreSQL认为' '中间的字符为text类型,请看下面:

 

postgres=# CREATE OR REPLACE VIEW vperson AS

postgres-#     SELECT p.uid,p.name,

postgres-#     CASE WHEN p.gender = true THEN '先生' ELSE '女士' END as gender,

postgres-#     p.nickname,p.mobile,p.tel,p.fax,p.email,p.province,p.city,p.addre

ss,p.postalcode

postgres-#     FROM "person" p

postgres-#     Order By p.uid;

CREATE VIEW

postgres=# \dv vperson

         List of relations

 Schema |  Name   | Type |  Owner

--------+---------+------+----------

 public | vperson | view | postgres

(1 row)

 

postgres=# \d person

                    Table "public.person"

   Column    |          Type          |      Modifiers

-------------+------------------------+----------------------

 uid         | integer                | not null default 0

 name        | character varying(20)  | not null

 gender      | boolean                | not null default 'F'

 nickname    | character varying(20)  |

 mobile      | character varying(13)  |

 tel         | character varying(20)  | not null

 fax         | character varying(20)  |

 email       | character varying(60)  |

 province    | character varying(10)  | not null

 city        | character varying(10)  | not null

 address     | character varying(255) | not null

 postalcode  | character varying(6)   | not null

 rate        | character varying(20)  | default '0'

 bank        | character varying(20)  | not null default ''

 bankaccount | character varying(20)  | not null default ''

Indexes: person_pkey primary key btree (uid)

Check constraints: "person_rate" ((((((rate = '0'::character varying) OR (rate = '1'::character varying)) OR (rate = '2'::character varying)) OR (rate = '3'::character varying)) OR (rate = '4'::character varying)) OR (rate = '5'::character varying))

 

postgres=#

postgres=# \d vperson

              View "public.vperson"

   Column   |          Type          | Modifiers

------------+------------------------+-----------

 uid        | integer                |

 name       | character varying(20)  |

 gender     | text                   |

 nickname   | character varying(20)  |

 mobile     | character varying(13)  |

 tel        | character varying(20)  |

 fax        | character varying(20)  |

 email      | character varying(60)  |

 province   | character varying(10)  |

 city       | character varying(10)  |

 address    | character varying(255) |

 postalcode | character varying(6)   |

View definition: SELECT p.uid, p.name, CASE WHEN (p.gender = true) THEN '先生'::

text ELSE '女士'::text END AS gender, p.nickname, p.mobile, p.tel, p.fax, p.emai

l, p.province, p.city, p.address, p.postalcode FROM person p ORDER BY p.uid;

 

 

使用“::”将test 转为varchar

CASE WHEN p.gender = true THEN '先生'::varchar(2) ELSE '女士'::varchar(2) END as gender,

例:

CREATE OR REPLACE VIEW vperson AS

    SELECT p.uid,p.name,

           CASE WHEN p.gender = true THEN '先生'::varchar(2) ELSE '女士'::varchar(2) END as gender,

           p.nickname,p.mobile,p.tel,p.fax,p.email,p.province,p.city,p.address,p.postalcode

    FROM "person" p

    Order By p.uid;

postgres=# drop view vperson ;

DROP VIEW

postgres=# CREATE OR REPLACE VIEW vperson AS

postgres-#     SELECT p.uid,p.name,

postgres-#     CASE WHEN p.gender = true THEN '先生'::varchar(2) ELSE '女士'::varchar(2) END as gender,

postgres-#     p.nickname,p.mobile,p.tel,p.fax,p.email,p.province,p.city,p.address,p.postalcode

postgres-#     FROM "person" p

postgres-#     Order By p.uid;

CREATE VIEW

postgres=# \d vperson

              View "public.vperson"

   Column   |          Type          | Modifiers

------------+------------------------+-----------

 uid        | integer                |

 name       | character varying(20)  |

 gender     | character varying(2)   |

 nickname   | character varying(20)  |

 mobile     | character varying(13)  |

 tel        | character varying(20)  |

 fax        | character varying(20)  |

 email      | character varying(60)  |

 province   | character varying(10)  |

 city       | character varying(10)  |

 address    | character varying(255) |

 postalcode | character varying(6)   |

View definition: SELECT p.uid, p.name, CASE WHEN (p.gender = true) THEN ('先生'::character varying)::character varying(2) ELSE ('女士'::character varying)::character varying(2) END AS gender, p.nickname, p.mobile, p.tel, p.fax, p.email, p.province, p.city, p.address, p.postalcode FROM person p ORDER BY p.uid;

 

postgres=#

 

 

3.4    序列

3.4.1   等差列

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

--  'Region' 

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

DROP TABLE region;

DROP SEQUENCE       region_id_seq;

DROP INDEX              region_id_index;

DROP VIEW vregion;

 

CREATE TABLE region (

    id                   integer DEFAULT nextval('region_id_seq') NOT NULL,

    region      varchar(20) DEFAULT '' NOT NULL,

    description  text ,

    note        text ,

    remark           text ,

     create_date  timestamp DEFAULT now() , 

     modify_date  timestamp DEFAULT now() ,  

    PRIMARY KEY (id),

    UNIQUE (id,region)

);

CREATE SEQUENCE   region_id_seq;

CREATE INDEX          region_id_index ON region (id);

 

CREATE VIEW vregion AS

    SELECT pv.id,pv.region,pv.description,pv.note,pv.remark,to_char(pv.create_date,'YYYY-MM-DD HH:MI:SS') as date

        FROM region pv

        ORDER BY pv.id;   

3.4.2   “123456789…”

DROP SEQUENCE       region_id_seq;

CREATE SEQUENCE   region_id_seq;

 

member=> insert into region(region) values('广西');

INSERT 111264 1

member=>

member=> insert into region(region) values('贵州');

INSERT 111265 1

member=>

member=> insert into region(region) values('海南');

INSERT 111266 1

member=>

member=> insert into region(region) values('河北');

INSERT 111267 1

member=>

member=> insert into region(region) values('河南');

INSERT 111268 1

member=>

member=> insert into region(region) values('黑龙江');

INSERT 111269 1

member=> select * from vregion ;

 id | region | description | note | remark |        date

----+--------+-------------+------+--------+---------------------

  1 | 安徽   |             |      |        | 2003-11-01 10:44:26

  2 | 北京   |             |      |        | 2003-11-01 10:44:26

  3 | 重庆   |             |      |        | 2003-11-01 10:44:26

  4 | 福建   |             |      |        | 2003-11-01 10:44:26

  5 | 甘肃   |             |      |        | 2003-11-01 10:44:26

  6 | 广东   |             |      |        | 2003-11-01 10:44:26

  7 | 广西   |             |      |        | 2003-11-01 10:44:26

  8 | 贵州   |             |      |        | 2003-11-01 10:44:26

  9 | 海南   |             |      |        | 2003-11-01 10:44:26

 10 | 河北   |             |      |        | 2003-11-01 10:44:26

 11 | 河南   |             |      |        | 2003-11-01 10:44:26

 12 | 黑龙江 |             |      |        | 2003-11-01 10:44:26

(12 rows)

 

3.4.3   “13579…”

DROP SEQUENCE       region_id_seq;

Delete from region;

CREATE SEQUENCE region_id_seq INCREMENT 2 START 1;

 

member=> DROP SEQUENCE region_id_seq;

DROP SEQUENCE

member=> Delete from region;

DELETE 15

member=>

member=> CREATE SEQUENCE region_id_seq INCREMENT 2 START 1;

CREATE SEQUENCE

member=> insert into region(region) values('广东');

INSERT 111282 1

member=>

member=> insert into region(region) values('广西');

INSERT 111283 1

member=>

member=> insert into region(region) values('贵州');

INSERT 111284 1

member=>

member=> insert into region(region) values('海南');

INSERT 111285 1

member=>

member=> insert into region(region) values('河北');

INSERT 111286 1

member=>

member=> insert into region(region) values('河南');

INSERT 111287 1

member=>

member=> insert into region(region) values('黑龙江');

INSERT 111288 1

member=> select * from region ;

 id | region | description | note | remark |        create_date         |        modify_date

----+--------+-------------+------+--------+----------------------------+----------------------------

  1 | 安徽   |             |      |        | 2003-11-01 11:49:58.004475 | 2003-11-01 11:49:58.004475

  3 | 北京   |             |      |        | 2003-11-01 11:49:58.093188 | 2003-11-01 11:49:58.093188

  5 | 重庆   |             |      |        | 2003-11-01 11:49:58.138582 | 2003-11-01 11:49:58.138582

  7 | 福建   |             |      |        | 2003-11-01 11:49:58.166903 | 2003-11-01 11:49:58.166903

  9 | 甘肃   |             |      |        | 2003-11-01 11:49:58.195132 | 2003-11-01 11:49:58.195132

 11 | 广东   |             |      |        | 2003-11-01 11:49:58.239133 | 2003-11-01 11:49:58.239133

 13 | 广西   |             |      |        | 2003-11-01 11:49:58.267372 | 2003-11-01 11:49:58.267372

 15 | 贵州   |             |      |        | 2003-11-01 11:49:58.295643 | 2003-11-01 11:49:58.295643

 17 | 海南   |             |      |        | 2003-11-01 11:49:58.324202 | 2003-11-01 11:49:58.324202

 19 | 河北   |             |      |        | 2003-11-01 11:49:58.352543 | 2003-11-01 11:49:58.352543

 21 | 河南   |             |      |        | 2003-11-01 11:49:58.381273 | 2003-11-01 11:49:58.381273

 23 | 黑龙江 |             |      |        | 2003-11-01 11:49:58.415112 | 2003-11-01 11:49:58.415112

(12 rows)

 

3.4.4   “246810…”

DROP SEQUENCE       region_id_seq;

Delete from region;

CREATE SEQUENCE region_id_seq INCREMENT 2 START 2;

member=> DROP SEQUENCE region_id_seq;

ERROR:  sequence "region_id_seq" does not exist

member=> Delete from region;

DELETE 0

member=> CREATE SEQUENCE region_id_seq INCREMENT 2 START 2;

CREATE SEQUENCE

member=> insert into region(region) values('安徽');

INSERT 111303 1

member=> insert into region(region) values('北京');

INSERT 111304 1

……

……

member=> insert into region(region) values('海南');

INSERT 111311 1

member=> insert into region(region) values('河北');

INSERT 111312 1

member=> select * from vregion;

 id | region | description | note | remark |        date

----+--------+-------------+------+--------+---------------------

  2 | 安徽   |             |      |        | 2003-11-01 12:00:28

  4 | 北京   |             |      |        | 2003-11-01 12:00:28

  6 | 重庆   |             |      |        | 2003-11-01 12:00:28

  8 | 福建   |             |      |        | 2003-11-01 12:00:28

 10 | 甘肃   |             |      |        | 2003-11-01 12:00:28

 12 | 广东   |             |      |        | 2003-11-01 12:00:28

 14 | 广西   |             |      |        | 2003-11-01 12:00:28

 16 | 贵州   |             |      |        | 2003-11-01 12:00:28

 18 | 海南   |             |      |        | 2003-11-01 12:00:28

 20 | 河北   |             |      |        | 2003-11-01 12:00:28

(10 rows)

 

3.4.5   n1+n2

CREATE SEQUENCE region_id_seq INCREMENT n2 START n1;

3.5    约束

3.6    检查约束

例子1

有这样一个需求,在很多电子商务网站上都要对用户进行诚信评估,诚信分为五级(五个星),这样就要求某字段插入的数据012345。“0”表示该用户没用评估。

-- ======================================================

--  'trust'

-- ======================================================

Create table "trust"

(

       "id" Serial NOT NULL UNIQUE,

       "uid" integer NOT NULL Default 0,

       "rate" Varchar(20) Default '0' Check (rate in ('0','1','2','3','4','5')),

      primary key ("id")

);

Alter table "trust" add  foreign key ("uid") references "user" ("id") on update restrict on delete restrict;

member=> Insert into trust (uid) values((select id from "user" where userid='netkiller'));

INSERT 111237 1

member=> Insert into trust (uid,rate) values((select id from "user" where userid='netkiller'),5);

INSERT 111220 1

member=> Insert into trust (uid,rate) values((select id from "user" where userid='netkiller'),2);

INSERT 111236 1

member=> Insert into trust (uid,rate) values((select id from "user" where userid='netkiller'),6);

ERROR:  ExecInsert: rejected due to CHECK constraint "trust_rate" on "trust"

member=> Insert into trust (uid,rate) values((select id from "user" where userid='netkiller'),10);

ERROR:  ExecInsert: rejected due to CHECK constraint "trust_rate" on "trust"

member=> select * from trust;

 id | uid | rate

----+-----+------

  1 | 257 | 2

  4 | 257 | 0

  5 | 257 | 5

(3 rows)

 

当插入数据不在枚举的范围内,提示ERROR:  ExecInsert: rejected due to CHECK constraint "trust_rate" on "trust"

 

例子2

检查某字段,不允许出现数值,使用not in 来完成。

DROP TABLE ctoc.bid CASCADE;

CREATE TABLE ctoc.bid(

       id Serial NOT NULL UNIQUE,

    salesroom_id integer DEFAULT '1' NOT NULL,  -- foreign key

    bidder integer  DEFAULT '1' NOT NULL,  -- foreign key

       price       numeric(8,2) DEFAULT '0.00' NOT NULL,

       quantity Integer DEFAULT '1' NOT NULL Check (quantity not in ('0')),

    created  timestamp DEFAULT current_timestamp::timestamp (0) without time zone,

    status boolean DEFAULT true,

    PRIMARY KEY (id),

    FOREIGN KEY (salesroom_id) REFERENCES ctoc.salesroom (id) ON UPDATE CASCADE ON DELETE CASCADE,

    FOREIGN KEY (bidder) REFERENCES person (uid) ON UPDATE CASCADE ON DELETE CASCADE

);

netkiller=> insert into ctoc.bid(salesroom_id,bidder,price,quantity,status) values(1,8,100,0,true);

ERROR:  ExecInsert: rejected due to CHECK constraint "bid_quantity" on "bid"

 

3.7    非空约束

显示的有note字段为空的记录:

member=> select * from vregion where note is null;

3.8    唯一约束

3.8.1   单字段约束

这个例子对groupname字段做唯一操作。

-- ======================================================

--  'group'

-- ======================================================

Create table "group"

(

       "id" Serial NOT NULL UNIQUE,

       "groupname" Varchar(20) NOT NULL,

       "description" Varchar(255),

       UNIQUE (groupname),

      PRIMARY KEY ("id")

);

测试:

member=> insert into "group"(groupname,description) values('Admin','xxxxxxxxxxxxxxxxxx');

INSERT 110497 1

member=> insert into "group"(groupname,description) values('Admin','xxxxxxxxxxxxxxxxxx');

ERROR:  Cannot insert a duplicate key into unique index group_groupname_key

member=> insert into "group"(groupname,description) values('Admin','xxxxxxxxxxxxxxxxxx');

ERROR:  Cannot insert a duplicate key into unique index group_groupname_key

Psql 命令行返回ERROR:  Cannot insert a duplicate key into unique index group_groupname_key唯一约束成功。

3.8.2   多个字段组合约束

UNIQUE (rid,uid)中有多个参数,是对rid,uid组合约束。

例如:

11

12

是正确的

 

11

21

也是正确的

 

21

11

22

12

11

不正确的不允许插入数据“11”,数据“11”出现了两次,所以要同时满足rid,uid两个条件。

 

三个字段以上组合:

1,1,1

1,1,2

1,2,1

2,1,2

2,1,1

2,2,2

正确可以插入数据

 

121

212

221

112

221

221,“221出现两次,违反约束条件,所以不能再次插入数据“221

 

-- ======================================================

--  'rolemember' 

-- ======================================================

-- drop table rolemember CASCADE ;

Create table "rolemember"

(

       "id" Serial NOT NULL UNIQUE,

       "rid" integer NOT NULL Default 0,

       "uid" integer NOT NULL Default 0,

       UNIQUE (rid,uid),

 primary key ("id")

);

member=> insert into rolemember(rid,uid) values((select id from role where rolename ='System'),(select id from vuser where userid='sysop'));

INSERT 110954 1

member=> insert into rolemember(rid,uid) values((select id from role where rolename ='System'),(select id from vuser where userid='sysop'));

ERROR:  Cannot insert a duplicate key into unique index rolemember_rid_key

member=> insert into rolemember(rid,uid) values((select id from role where rolename ='System'),(select id from vuser where userid='admin'));

ERROR:  More than one tuple returned by a subselect used as an expression.

member=> insert into rolemember(rid,uid) values((select id from role where rolename ='System'),(select id from vuser where userid='test'));

INSERT 110956 1

member=> insert into rolemember(rid,uid) values((select id from role where rolename ='System'),(select id from vuser where userid='test'));

ERROR:  Cannot insert a duplicate key into unique index rolemember_rid_key

3.8.3   唯一约束的注意事项

这个例子对groupname字段做唯一操作。

-- ======================================================

--  'group'

-- ======================================================

Create table "group"

(

       "id" Serial NOT NULL UNIQUE,

       "groupname" Varchar(20) NOT NULL,

       "description" Varchar(255),

       UNIQUE (id,groupname),

      PRIMARY KEY ("id")

);

仔细看这个例子没有错。

运行结果:

postgres=# Create table "group"

postgres-# (

postgres(# "id" Serial NOT NULL UNIQUE,

postgres(# "groupname" Varchar(20) NOT NULL,

postgres(# "description" Varchar(255),

postgres(# UNIQUE (id,groupname),

postgres(#  PRIMARY KEY ("id")

postgres(# );

NOTICE:  CREATE TABLE will create implicit sequence 'group_id_seq' for SERIAL column 'group.id'

NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index 'group_pkey' for table 'group'

NOTICE:  CREATE TABLE / UNIQUE will create implicit index 'group_id_key' for table 'group'

CREATE TABLE

 

运行结果也没有错,现在插入数据。

insert into "group"(groupname,description) values('Admin','xxxxxxxxxxxxxxxxxx');

insert into "group"(groupname,description) values('Guest','xxxxxxxxxxxxxxxxxx');

insert into "group"(groupname,description) values('Domain','xxxxxxxxxxxxxxxxxx');

postgres=# insert into "group"(groupname,description) values('Admin','xxxxxxxxxxxxxxxxxx');

INSERT 110466 1

postgres=# insert into "group"(groupname,description) values('Guest','xxxxxxxxxxxxxxxxxx');

INSERT 110467 1

postgres=# insert into "group"(groupname,description) values('Domain','xxxxxxxxxxxxxxxxxx');

INSERT 110468 1

postgres=#

postgres=# insert into "group"(groupname,description) values('Admin','xxxxxxxxxxxxxxxxxx');

INSERT 110469 1

postgres=# insert into "group"(groupname,description) values('Guest','xxxxxxxxxxxxxxxxxx');

INSERT 110470 1

postgres=# insert into "group"(groupname,description) values('Domain','xxxxxxxxxxxxxxxxxx');

INSERT 110471 1

postgres=# insert into "group"(groupname,description) values('Admin','xxxxxxxxxxxxxxxxxx');

INSERT 110472 1

postgres=# insert into "group"(groupname,description) values('Guest','xxxxxxxxxxxxxxxxxx');

INSERT 110473 1

postgres=# insert into "group"(groupname,description) values('Domain','xxxxxxxxxxxxxxxxxx');

INSERT 110474 1

postgres=# insert into "group"(groupname,description) values('Admin','xxxxxxxxxxxxxxxxxx');

INSERT 110475 1

postgres=# insert into "group"(groupname,description) values('Guest','xxxxxxxxxxxxxxxxxx');

INSERT 110476 1

postgres=# insert into "group"(groupname,description) values('Domain','xxxxxxxxxxxxxxxxxx');

INSERT 110477 1

postgres=# insert into "group"(groupname,description) values('Admin','xxxxxxxxxxxxxxxxxx');

INSERT 110478 1

postgres=# insert into "group"(groupname,description) values('Guest','xxxxxxxxxxxxxxxxxx');

INSERT 110479 1

postgres=# insert into "group"(groupname,description) values('Domain','xxxxxxxxxxxxxxxxxx');

INSERT 110480 1

postgres=# select * from "group";

 id | groupname |    description

----+-----------+--------------------

  1 | Admin     | xxxxxxxxxxxxxxxxxx

  2 | Guest     | xxxxxxxxxxxxxxxxxx

  3 | Domain    | xxxxxxxxxxxxxxxxxx

  4 | Admin     | xxxxxxxxxxxxxxxxxx

  5 | Guest     | xxxxxxxxxxxxxxxxxx

  6 | Domain    | xxxxxxxxxxxxxxxxxx

  7 | Admin     | xxxxxxxxxxxxxxxxxx

  8 | Guest     | xxxxxxxxxxxxxxxxxx

  9 | Domain    | xxxxxxxxxxxxxxxxxx

 10 | Admin     | xxxxxxxxxxxxxxxxxx

 11 | Guest     | xxxxxxxxxxxxxxxxxx

 12 | Domain    | xxxxxxxxxxxxxxxxxx

 13 | Admin     | xxxxxxxxxxxxxxxxxx

 14 | Guest     | xxxxxxxxxxxxxxxxxx

 15 | Domain    | xxxxxxxxxxxxxxxxxx

(15 rows)

 

但你会发现对groupname字段的唯一约束不起使用。失效原因:

"id" Serial NOT NULL UNIQUE, (唯一约束)

UNIQUE (id,groupname), (id字段又做了一次唯一约束)

这就是它失效的原因。正确的脚本写法是:

Create table "group"

(

       "id" Serial NOT NULL UNIQUE,

       "groupname" Varchar(20) NOT NULL,

       "description" Varchar(255),

       UNIQUE (groupname),

      PRIMARY KEY ("id")

);

member=> insert into "group"(groupname,description) values('Admin','xxxxxxxxxxxxxxxxxx');

INSERT 110497 1

member=> insert into "group"(groupname,description) values('Admin','xxxxxxxxxxxxxxxxxx');

ERROR:  Cannot insert a duplicate key into unique index group_groupname_key

member=> insert into "group"(groupname,description) values('Admin','xxxxxxxxxxxxxxxxxx');

ERROR:  Cannot insert a duplicate key into unique index group_groupname_key

Psql 命令行返回ERROR:  Cannot insert a duplicate key into unique index group_groupname_key
唯一约束成功。

3.9    主键/外键

3.9.1   主键

下面书写方式,推荐第二种,比较清晰。

CREATE TABLE products (

    product_no integer PRIMARY KEY,

    name text,

    price numeric

);

 

CREATE TABLE example (

    a integer,

    b integer,

    c integer,

    PRIMARY KEY (a, c)

);

3.9.2   外键约束

下面第前两种写法不推荐。第三、四种写法较清晰。

1.      第一种书写方式

CREATE TABLE orders (

    order_id integer PRIMARY KEY,

    product_no integer REFERENCES products,

    quantity integer

);

2.      第二种书写方式

CREATE TABLE orders (

    order_id integer PRIMARY KEY,

    product_no integer REFERENCES products (product_no),

    quantity integer

);

3.      第三种书写方式

CREATE TABLE table1 (

  a integer PRIMARY KEY,

  b integer,

  c integer,

  FOREIGN KEY (b, c) REFERENCES other_table (c1, c2)

);

4.      第四种书写方式,在SQL脚本最后面添加外键约束

Alter table "groupmember" add  foreign key ("uid") references "user" ("id") on update restrict on delete restrict;

Alter table "groupmember" add  foreign key ("gid") references "group" ("id") on update restrict on delete restrict;

Alter table "rolemember" add  foreign key ("uid") references "user" ("id") on update restrict on delete restrict;

Alter table "rolemember" add  foreign key ("rid") references "role" ("id") on update restrict on delete restrict;

3.9.3   PostgreSQL 7.3.x 新增功能

CREATE TABLE order_items (

    product_no integer REFERENCES products ON DELETE RESTRICT,

    order_id integer REFERENCES orders ON DELETE CASCADE,

    quantity integer,

    PRIMARY KEY (product_no, order_id)

);

类似 ON DELETE,还有 ON UPDATE 选项,它是在主键被修改(更新)的时候调用的。

以前我们删除其它表中受外键约束的记录,使用规则或触发器来完成。现可以用CASCADE

3.9.4   层次递归-分类目录

实现一个无限向下分类的目录,例如:

计算机与互联网

       免费资源

              软件下载(3431)

壁纸/屏保/桌面(109)

免费电子贺卡(197)

代理服务器(33)

免费电子邮箱(73)

免费主页空间(75)

免费聊天室(11)

免费论坛(36)

软件

       XXXXXXXX

       XXXXXXXX

       XXXXXXXX

       XXXXXXXX

硬件

互联网

编程

 

数据结构定义:

Drop table "directory" CASCADE;

 

Create table "directory"

(

    "id" Serial NOT NULL,

    "root_id" Integer NOT NULL Default 0,

    "name"    Varchar(20)NOT NULL ,

    "status"   boolean Default 'true',

    "created" Timestamp Default current_timestamp,

    "modified" Timestamp Default current_timestamp,

    UNIQUE (id,root_id),

    PRIMARY KEY ("id")

--    FOREIGN KEY (root_id) REFERENCES directory (id) ON DELETE CASCADE

);

INSERT INTO directory (id,root_id,name) VALUES (0,0,'/');

Alter table "directory" add  FOREIGN KEY (root_id) REFERENCES directory (id) ON DELETE CASCADE;

Create index "directory_index" on "directory" using btree ("id","root_id","name");

 

数据存储状态:

Id

Root_id

Name

0

0

/

1

0

计算机

2

1

显示器

3

1

鼠标

4

1

主板

5

2

Samsung 显示器

6

2

LG显示器

7

2

SONY显示器

      

上图是一个分类目录,当删除子目录时如果子目录中有目录或数据,将删除这些数据和目录

 

说明:

       id            目录根

       root_id    REFERENCES id ON DELETE CASCADEpk删除时关联的fk自动删除

       name       目录名

       status      状态true可用,false不可用

       created    创建时间

       modified  修改时间

      

注意:

       因为使用了关联字段,所以不能在create table 中使用
       FOREIGN KEY (root_id) REFERENCES directory (id) ON DELETE CASCADE

       因为插入记录做参考表中的“id”字段,创建表的中没有数据,所以无法插入数据。
      
先创建表,不定义FOREIGN KEY,然后初始化插入第一条数据:

INSERT INTO directory (id,root_id,name) VALUES (0,0,'/');

       再定义外建:

       Alter table "directory" add  FOREIGN KEY (root_id) REFERENCES directory (id) ON DELETE CASCADE;

 

postgres=# Create table "directory"

postgres-# (

postgres(#     "id" Serial NOT NULL,

postgres(#     "root_id" Integer NOT NULL Default 0,

postgres(#     "name" Varchar(20)NOT NULL ,

postgres(#     "status"boolean Default 'true',

postgres(#     "created" Timestamp Default current_timestamp,

postgres(#     "modified" Timestamp Default current_timestamp,

postgres(#     UNIQUE (id,root_id),

postgres(#     PRIMARY KEY ("id")

postgres(# --    FOREIGN KEY (root_id) REFERENCES directory (id) ON DELETE CASCADE

postgres(# );

NOTICE:  CREATE TABLE will create implicit sequence 'directory_id_seq' for SERIAL column 'directory.id'

NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index 'directory_pkey' for table 'directory'

NOTICE:  CREATE TABLE / UNIQUE will create implicit index 'directory_id_key' for table 'directory'

CREATE TABLE

postgres=# INSERT INTO directory (id,root_id,name) VALUES (0,0,'/');

INSERT 17110 1

postgres=# Alter table "directory" add  FOREIGN KEY (root_id) REFERENCES directory (id) ON DELETE CASCADE;

NOTICE:  ALTER TABLE will create implicit trigger(s) for FOREIGN KEY check(s)

ALTER TABLE

postgres=# Create index "directory_index" on "directory" using btree ("id","root_id","name");

CREATE INDEX

postgres=# INSERT INTO directory (root_id,name) VALUES (0,'计算机');

INSERT 17116 1

postgres=# SELECT * from directory ;

 id | root_id |   name    | status |          created           |          modified

----+---------+-----------+--------+----------------------------+----------------------------

  0 |       0 | /         | t      | 2003-11-12 16:55:39.727365 | 2003-11-12 16:55:39.727365

  1 |       0 | 计算机 | t      | 2003-11-12 16:56:39.663584 | 2003-11-12 16:56:39.663584

(2 rows)

 

postgres=# INSERT INTO directory (root_id,name) VALUES (0,'金融');

INSERT 17117 1

postgres=# SELECT * from directory ;

 id | root_id |   name    | status |          created           |          modified

----+---------+-----------+--------+----------------------------+----------------------------

  0 |       0 | /         | t      | 2003-11-12 16:55:39.727365 | 2003-11-12 16:55:39.727365

  1 |       0 | 计算机 | t      | 2003-11-12 16:56:39.663584 | 2003-11-12 16:56:39.663584

  2 |       0 | 金融    | t      | 2003-11-12 16:57:50.509436 | 2003-11-12 16:57:50.509436

(3 rows)

 

postgres=# INSERT INTO directory (root_id,name) VALUES (1,'显示器');

INSERT 17118 1

postgres=# INSERT INTO directory (root_id,name) VALUES (1,'鼠标');

INSERT 17119 1

postgres=# INSERT INTO directory (root_id,name) VALUES (1,'主板');

INSERT 17120 1

postgres=# SELECT * from directory ;

 id | root_id |   name    | status |          created           |          modified

----+---------+-----------+--------+----------------------------+----------------------------

  0 |       0 | /         | t      | 2003-11-12 16:55:39.727365 | 2003-11-12 16:55:39.727365

  1 |       0 | 计算机 | t      | 2003-11-12 16:56:39.663584 | 2003-11-12 16:56:39.663584

  2 |       0 | 金融    | t      | 2003-11-12 16:57:50.509436 | 2003-11-12 16:57:50.509436

  3 |       1 | 显示器 | t      | 2003-11-12 16:59:15.911196 | 2003-11-12 16:59:15.911196

  4 |       1 | 鼠标    | t      | 2003-11-12 16:59:30.646916 | 2003-11-12 16:59:30.646916

  5 |       1 | 主板    | t      | 2003-11-12 16:59:44.400317 | 2003-11-12 16:59:44.400317

(6 rows)

 

postgres=# INSERT INTO directory (root_id,name) VALUES (3,'Samsung 显示器');

INSERT 17121 1

postgres=# INSERT INTO directory (root_id,name) VALUES (3,'LG显示器');

INSERT 17122 1

postgres=# INSERT INTO directory (root_id,name) VALUES (3,'SONY显示器');

INSERT 17123 1

postgres=# SELECT * from directory ;

 id | root_id |       name        | status |          created           |          modified

----+---------+-------------------+--------+----------------------------+----------------------------

  0 |       0 | /                 | t      | 2003-11-12 16:55:39.727365 | 2003-11-12 16:55:39.727365

  1 |       0 | 计算机         | t      | 2003-11-12 16:56:39.663584 | 2003-11-12 16:56:39.663584

  2 |       0 | 金融            | t      | 2003-11-12 16:57:50.509436 | 2003-11-12 16:57:50.509436

  3 |       1 | 显示器         | t      | 2003-11-12 16:59:15.911196 | 2003-11-12 16:59:15.911196

  4 |       1 | 鼠标            | t      | 2003-11-12 16:59:30.646916 | 2003-11-12 16:59:30.646916

  5 |       1 | 主板            | t      | 2003-11-12 16:59:44.400317 | 2003-11-12 16:59:44.400317

  6 |       3 | Samsung 显示器 | t      | 2003-11-12 17:00:45.964053 | 2003-11-12 17:00:45.964053

  7 |       3 | LG显示器       | t      | 2003-11-12 17:01:03.736121 | 2003-11-12 17:01:03.736121

  8|       3 | SONY显示器     | t      | 2003-11-12 17:01:18.257337 | 2003-11-12 17:01:18.257337

(9 rows)

 

postgres=# INSERT INTO directory (root_id,name) VALUES (7,'CRT显示器');

INSERT 17124 1

postgres=# INSERT INTO directory (root_id,name) VALUES (7,'液晶显示器');

INSERT 17125 1

postgres=# INSERT INTO directory (root_id,name) VALUES (8,'液晶显示器');

INSERT 17126 1

postgres=# INSERT INTO directory (root_id,name) VALUES (8,'特利隆显示器');

INSERT 17127 1

postgres=# INSERT INTO directory (root_id,name) VALUES (7,'钻石隆显示器');

INSERT 17128 1

postgres=# SELECT * from directory ;

 id | root_id |        name        | status |          created           |          modified

----+---------+--------------------+--------+----------------------------+----------------------------

  0 |       0 | /                  | t      | 2003-11-12 16:55:39.727365 | 2003-11-12 16:55:39.727365

  1 |       0 | 计算机          | t      | 2003-11-12 16:56:39.663584 | 2003-11-12 16:56:39.663584

  2 |       0 | 金融             | t      | 2003-11-12 16:57:50.509436 | 2003-11-12 16:57:50.509436

  3 |       1 | 显示器          | t      | 2003-11-12 16:59:15.911196 | 2003-11-12 16:59:15.911196

  4 |       1 | 鼠标             | t      | 2003-11-12 16:59:30.646916 | 2003-11-12 16:59:30.646916

  5 |       1 | 主板             | t      | 2003-11-12 16:59:44.400317 | 2003-11-12 16:59:44.400317

  6 |       3 | Samsung 显示器  | t      | 2003-11-12 17:00:45.964053 | 2003-11-12 17:00:45.964053

  7 |       3 | LG显示器        | t      | 2003-11-12 17:01:03.736121 | 2003-11-12 17:01:03.736121

  8 |       3 | SONY显示器      | t      | 2003-11-12 17:01:18.257337 | 2003-11-12 17:01:18.257337

  9 |       7 | CRT显示器       | t      | 2003-11-12 17:03:05.594891 | 2003-11-12 17:03:05.594891

 10 |       7 | 液晶显示器    | t      | 2003-11-12 17:03:21.793674 | 2003-11-12 17:03:21.793674

 11 |       8 | 液晶显示器    | t      | 2003-11-12 17:03:30.688531 | 2003-11-12 17:03:30.688531

 12 |       8 | 特利隆显示器 | t      | 2003-11-12 17:03:57.697321 | 2003-11-12 17:03:57.697321

 13 |       7 | 钻石隆显示器 | t      | 2003-11-12 17:04:28.61153  | 2003-11-12 17:04:28.61153

(14 rows)

 

测试:

1.         删除子目录:计算机/显示器/ LG显示器/ CRT显示器
CRT
显示器的id9
SQL
DELETE FROM directory WHERE id=9;

postgres=# DELETE FROM directory WHERE id=9;

DELETE 1

postgres=# SELECT * from directory ;

 id | root_id |        name        | status |          created           |          modified

----+---------+--------------------+--------+----------------------------+----------------------------

  0 |       0 | /                  | t      | 2003-11-12 16:55:39.727365 | 2003-11-12 16:55:39.727365

  1 |       0 | 计算机          | t      | 2003-11-12 16:56:39.663584 | 2003-11-12 16:56:39.663584

  2 |       0 | 金融             | t      | 2003-11-12 16:57:50.509436 | 2003-11-12 16:57:50.509436

  3 |       1 | 显示器          | t      | 2003-11-12 16:59:15.911196 | 2003-11-12 16:59:15.911196

  4 |       1 | 鼠标             | t      | 2003-11-12 16:59:30.646916 | 2003-11-12 16:59:30.646916

  5 |       1 | 主板             | t      | 2003-11-12 16:59:44.400317 | 2003-11-12 16:59:44.400317

  6 |       3 | Samsung 显示器  | t      | 2003-11-12 17:00:45.964053 | 2003-11-12 17:00:45.964053

  7 |       3 | LG显示器        | t      | 2003-11-12 17:01:03.736121 | 2003-11-12 17:01:03.736121

  8 |       3 | SONY显示器      | t      | 2003-11-12 17:01:18.257337 | 2003-11-12 17:01:18.257337

 10 |       7 | 液晶显示器    | t      | 2003-11-12 17:03:21.793674 | 2003-11-12 17:03:21.793674

 11 |       8 | 液晶显示器    | t      | 2003-11-12 17:03:30.688531 | 2003-11-12 17:03:30.688531

 12 |       8 | 特利隆显示器 | t      | 2003-11-12 17:03:57.697321 | 2003-11-12 17:03:57.697321

 13 |       7 | 钻石隆显示器 | t      | 2003-11-12 17:04:28.61153  | 2003-11-12 17:04:28.61153

(13 rows)

 

postgres=#

2.         删除子目录:计算机/显示器/ LG显示器
LG
显示器目录下的子目录:液晶显示器、钻石隆显示器也将被删除

postgres=# DELETE FROM directory WHERE id=7;

DELETE 1

postgres=# SELECT * from directory ;

 id | root_id |        name        | status |          created           |          modified

----+---------+--------------------+--------+----------------------------+----------------------------

  0 |       0 | /                  | t      | 2003-11-12 16:55:39.727365 | 2003-11-12 16:55:39.727365

  1 |       0 | 计算机          | t      | 2003-11-12 16:56:39.663584 | 2003-11-12 16:56:39.663584

  2 |       0 | 金融             | t      | 2003-11-12 16:57:50.509436 | 2003-11-12 16:57:50.509436

  3 |       1 | 显示器          | t      | 2003-11-12 16:59:15.911196 | 2003-11-12 16:59:15.911196

  4 |       1 | 鼠标             | t      | 2003-11-12 16:59:30.646916 | 2003-11-12 16:59:30.646916

  5 |       1 | 主板             | t      | 2003-11-12 16:59:44.400317 | 2003-11-12 16:59:44.400317

  6 |       3 | Samsung 显示器  | t      | 2003-11-12 17:00:45.964053 | 2003-11-12 17:00:45.964053

  8 |       3 | SONY显示器      | t      | 2003-11-12 17:01:18.257337 | 2003-11-12 17:01:18.257337

 11 |       8 | 液晶显示器    | t      | 2003-11-12 17:03:30.688531 | 2003-11-12 17:03:30.688531

 12 |       8 | 特利隆显示器 | t      | 2003-11-12 17:03:57.697321 | 2003-11-12 17:03:57.697321

(10 rows)

 

3.         再删除:计算机/显示器/ SONY显示器

postgres=# DELETE FROM directory WHERE id=8;

DELETE 1

postgres=# SELECT * from directory ;

 id | root_id |       name        | status |          created           |          modified

----+---------+-------------------+--------+----------------------------+----------------------------

  0 |       0 | /                 | t      | 2003-11-12 16:55:39.727365 | 2003-11-12 16:55:39.727365

  1 |       0 | 计算机         | t      | 2003-11-12 16:56:39.663584 | 2003-11-12 16:56:39.663584

  2 |       0 | 金融            | t      | 2003-11-12 16:57:50.509436 | 2003-11-12 16:57:50.509436

  3 |       1 | 显示器         | t      | 2003-11-12 16:59:15.911196 | 2003-11-12 16:59:15.911196

  4 |       1 | 鼠标            | t      | 2003-11-12 16:59:30.646916 | 2003-11-12 16:59:30.646916

  5 |       1 | 主板            | t      | 2003-11-12 16:59:44.400317 | 2003-11-12 16:59:44.400317

  6 |       3 | Samsung 显示器 | t      | 2003-11-12 17:00:45.964053 | 2003-11-12 17:00:45.964053

(7 rows)

 

 

4.         删除子目录:计算机/显示器
显示器目录下的子目录:
下有目录LG显示器/ CRT显示器、SONY显示器/……、LG显示器/……
删除显示器目录后,下的所有子目录将被删除。

postgres=# INSERT INTO directory (root_id,name) VALUES (3,'LG显示器');

INSERT 17129 1

postgres=# INSERT INTO directory (root_id,name) VALUES (3,'SONY显示器');

INSERT 17130 1

postgres=# INSERT INTO directory (root_id,name) VALUES (6,'CRT显示器');

INSERT 17131 1

postgres=# INSERT INTO directory (root_id,name) VALUES (14,'CRT显示器');

INSERT 17132 1

postgres=# INSERT INTO directory (root_id,name) VALUES (15,'CRT显示器');

INSERT 17133 1

postgres=# INSERT INTO directory (root_id,name) VALUES (15,'特利隆显示器');

INSERT 17134 1

postgres=# INSERT INTO directory (root_id,name) VALUES (15,'钻石隆显示器');

INSERT 17135 1

postgres=# INSERT INTO directory (root_id,name) VALUES (6,'液晶显示器');

INSERT 17136 1

postgres=# INSERT INTO directory (root_id,name) VALUES (14,'液晶显示器');

INSERT 17137 1

postgres=# INSERT INTO directory (root_id,name) VALUES (15,'液晶显示器');

INSERT 17138 1

postgres=# SELECT * from directory ;

 id | root_id |        name        | status |          created           |          modified

----+---------+--------------------+--------+----------------------------+----------------------------

  0 |       0 | /                  | t      | 2003-11-12 16:55:39.727365 | 2003-11-12 16:55:39.727365

  1 |       0 | 计算机          | t      | 2003-11-12 16:56:39.663584 | 2003-11-12 16:56:39.663584

  2 |       0 | 金融             | t      | 2003-11-12 16:57:50.509436 | 2003-11-12 16:57:50.509436

  3 |       1 | 显示器          | t      | 2003-11-12 16:59:15.911196 | 2003-11-12 16:59:15.911196

  4 |       1 | 鼠标             | t      | 2003-11-12 16:59:30.646916 | 2003-11-12 16:59:30.646916

  5 |       1 | 主板             | t      | 2003-11-12 16:59:44.400317 | 2003-11-12 16:59:44.400317

  6 |       3 | Samsung 显示器  | t      | 2003-11-12 17:00:45.964053 | 2003-11-12 17:00:45.964053

 14 |       3 | LG显示器        | t      | 2003-11-12 17:28:03.927651 | 2003-11-12 17:28:03.927651

 15 |       3 | SONY显示器      | t      | 2003-11-12 17:28:15.235316 | 2003-11-12 17:28:15.235316

 16 |       6 | CRT显示器       | t      | 2003-11-12 17:28:49.586084 | 2003-11-12 17:28:49.586084

 17 |      14 | CRT显示器       | t      | 2003-11-12 17:28:55.290861 | 2003-11-12 17:28:55.290861

 18 |      15 | CRT显示器       | t      | 2003-11-12 17:28:59.731191 | 2003-11-12 17:28:59.731191

 19 |      15 | 特利隆显示器 | t      | 2003-11-12 17:29:10.747115 | 2003-11-12 17:29:10.747115

 20 |      15 | 钻石隆显示器 | t      | 2003-11-12 17:29:30.770079 | 2003-11-12 17:29:30.770079

 21 |       6 | 液晶显示器    | t      | 2003-11-12 17:29:47.006177 | 2003-11-12 17:29:47.006177

 22 |      14 | 液晶显示器    | t      | 2003-11-12 17:29:51.904914 | 2003-11-12 17:29:51.904914

 23 |      15 | 液晶显示器    | t      | 2003-11-12 17:29:57.355213 | 2003-11-12 17:29:57.355213

(17 rows)

 

postgres=# DELETE FROM directory WHERE id=3;

DELETE 1

postgres=# SELECT * from directory ;

 id | root_id |   name    | status |          created           |          modified

----+---------+-----------+--------+----------------------------+----------------------------

  0 |       0 | /         | t      | 2003-11-12 16:55:39.727365 | 2003-11-12 16:55:39.727365

  1 |       0 | 计算机 | t      | 2003-11-12 16:56:39.663584 | 2003-11-12 16:56:39.663584

  2 |       0 | 金融    | t      | 2003-11-12 16:57:50.509436 | 2003-11-12 16:57:50.509436

  4 |       1 | 鼠标    | t      | 2003-11-12 16:59:30.646916 | 2003-11-12 16:59:30.646916

  5 |       1 | 主板    | t      | 2003-11-12 16:59:44.400317 | 2003-11-12 16:59:44.400317

(5 rows)

不再举例了,删除id=0将删除计算机包括下面的所有目录被删除。

注意,千万不要删除id=0

3.9.5   总结

分类目录的例子中使用了ON DELETE CASCADE,方便了操作,但也有危险。如果不用ON DELETE CASCADE而用程序来实现,需要使用递归算法,非常麻烦。

3.10       模式

一些用户为了使某些模块的表看起来清晰,一般他们采用“模块名_表名”:

Auth_user

Auth_group

Bbs_topic

Bbs_message

 

PostgreSQL不必这样命名,可以使用Schema(模式)如:

Auth.user

Auth.group

Bbs.topic

Bbs.message

 

3.10.1 创建模式

CREATE SCHEMA your_schema;

例:

CREATE SCHEMA btob;

CREATE SCHEMA auction;

3.10.2 删除模式

DROP SCHEMA your_schema;

删除模式,并且同时删除模式下的(表,视图,触发器,过程……)

DROP SCHEMA your_schema CASCADE;

例:

DROP SCHEMA btob CASCADE;

DROP SCHEMA btob CASCADE;

3.10.3 模式搜索路径

查看当前模式SHOW search_path ;

netkiller=> SHOW search_path ;

 search_path

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

 $user,public

(1 row)

netkiller=> \dt

            List of relations

 Schema |    Name     | Type  |   Owner

--------+-------------+-------+-----------

 public | company     | table | netkiller

 public | group       | table | netkiller

 public | groupmember | table | netkiller

 public | guestbook   | table | netkiller

 public | prodorder   | table | netkiller

 public | role        | table | netkiller

 public | rolemember  | table | netkiller

 public | system_log  | table | netkiller

 public | templates   | table | netkiller

 public | trust       | table | netkiller

 public | user        | table | netkiller

 public | user_log    | table | netkiller

 public | userinfo    | table | netkiller

(13 rows)

如果不设置模式搜索路径,“\dt”只显示public模式下的表。

设置模式SET search_path TO public,btob,auction;

netkiller=> SET search_path TO public,btob,auction;

SET

netkiller=> \dt

              List of relations

 Schema  |     Name      | Type  |   Owner

---------+---------------+-------+-----------

 auction | messages      | table | netkiller

 auction | product       | table | netkiller

 auction | product_order | table | netkiller

 btob    | directory     | table | netkiller

 btob    | trade         | table | netkiller

 btob    | trade_message | table | netkiller

 public  | company       | table | netkiller

 public  | group         | table | netkiller

 public  | groupmember   | table | netkiller

 public  | guestbook     | table | netkiller

 public  | prodorder     | table | netkiller

 public  | role          | table | netkiller

 public  | rolemember    | table | netkiller

 public  | system_log    | table | netkiller

 public  | templates     | table | netkiller

 public  | trust         | table | netkiller

 public  | user          | table | netkiller

 public  | user_log      | table | netkiller

 public  | userinfo      | table | netkiller

(19 rows)

 

netkiller=>

 

-- ======================================================================

-- 'btob.directory'

-- ======================================================================

Drop table btob.directory CASCADE;

 

Create table btob.directory

(

    "id" Serial NOT NULL,

    "root_id" Integer NOT NULL Default 0,

    "name"    Varchar(20)NOT NULL ,

    "status"   boolean Default 'true',

    "created" Timestamp Default current_timestamp,

    "modified" Timestamp Default current_timestamp,

    UNIQUE (id,root_id,name),

    PRIMARY KEY ("id")

--    FOREIGN KEY (root_id) REFERENCES directory (id) ON DELETE CASCADE

);

INSERT INTO btob.directory (id,root_id,name) VALUES (0,0,'/');

Alter table btob.directory add  FOREIGN KEY (root_id) REFERENCES btob.directory (id) ON DELETE CASCADE;

Create index "directory_index" on btob.directory using btree ("id","root_id","name");

 

 

 

 

 

4       实体关系(Entity-Relation

       在关系数据库中,关系能防止冗余的数据。例如,如果正在设计一个数据库来跟踪有关书的信息,而每本书的信息(如书名、出版日期和出版商)都保存在一个名为 titles 的表中。同时还有一些想保存的有关出版商的信息,例如出版商的电话号码、地址和邮政编码。如果将所有这些信息都保存在 titles 表中,则对于某个出版商出版的每本书,出版商的电话号码将是重复的。

       一个更好的解决方案是,单独在一个名为 publishers 的表中只保存一次出版商信息。然后在 titles 表中设置指针,以引用 publishers 表中的项。

       若要确保数据同步,可以在 titles 表和 publishers 表之间强制引用完整性。引用完整性关系能确保某个表中的信息与另一个表中的信息相匹配。例如,titles 表中的每个书名必须和 publishers 表的特定出版商相关联。不能在数据库中添加数据库中不存在的出版商的书名。

 

为更好地理解表关系,请参见:

l         表关系类型

表与表之间存在三种类型的关系。所创建的关系类型取决于相关联的列是如何定义的。

n         一对多关系

n         多对多关系

n         一对一关系

l         引用完整性概述

l         表关系类型

 

关系是通过匹配键列中的数据而工作的,而键列通常是两个表中具有相同名称的列。在大多数情况下,关系将一个表中为每个行提供唯一标识符的主键与另一个表中外键内的项相匹配。例如,通过在 titles 表的 title_id 列(主键)和 sales 表的 title_id 列(外键)之间创建一个关系,可以使销售额与特定的销售书名相关联。

4.1    E-R图(Entity-Relation

       PostgreSQL本身没有GUI(图形用户界面)管理工具,其它GUI工具也没有E-R图功能,如pgAdmin III。这里我给在各位介绍一个很好的数据库设计工具CASE Studio 2

1.         实体关系设计

2.         能过E-R图产生SQLDDL)脚本

3.         已经存在数据库的逆向工程

4.         产生非常详细的HTMLRTF报告

5.         用户定义Add-ins和模板

6.         版本管理,Galery,To-Do列表

7.         数据流程设计

8.         界面见附录。

 

4.2    一对多关系

一对多关系是最常见的关系类型。在这种关系类型中,表 A 中的行可以在表 B 中有许多匹配行,但是表 B 中的行只能在表 A 中有一个匹配行。

例如,publishers 表和 titles 表是一对多的关系:每一个出版商可出版许多书,但每一本书只能有一个出版商。

如果在相关列中只有一列是主键或具有唯一约束,则创建的是一对多关系。

       一对多关系中的主键方由一个键 符号表示。关系中的外键方由一个无穷大 符号表示。

Drop table "groupmember" Restrict;

Drop table "userinfo" Restrict;

Drop table "group" Restrict;

Drop table "user" Restrict;

 

Create table "user"

(

       "id" Serial NOT NULL Default 0 UNIQUE ,

       "user" Varchar(20) NOT NULL UNIQUE ,

       "passwd" Varchar(20),

       "homedir" Varchar(20) NOT NULL Default /home/,

       "shell" Varchar(20) NOT NULL Default /bin/bash,

 primary key ("id")

);

 

Create table "group"

(

       "id" Serial NOT NULL Default 0,

       "groupname" Varchar(20),

       "description" Varchar(20),

 primary key ("id")

);

 

Create table "userinfo"

(

       "id" integer NOT NULL Default 0,

       "tel" Varchar(20),

       "fax" Varchar(20),

       "address" Varchar(255),

       "company" Varchar(20),

       "note" Text,

 primary key ("id")

);

 

Create table "groupmember"

(

       "id" Serial NOT NULL,

       "uid" integer NOT NULL,

       "gid" integer NOT NULL,

 primary key ("id","uid","gid")

);

 

Alter table "userinfo" add  foreign key ("id") references "user" ("id") on update restrict on delete restrict;

Alter table "groupmember" add  foreign key ("uid") references "user" ("id") on update restrict on delete restrict;

Alter table "groupmember" add  foreign key ("gid") references "group" ("id") on update restrict on delete restrict;

 

4.3    多对多关系

在多对多关系中,表 A 中的一行可与表 B 中的多行相匹配,反之亦然。通过定义称为连接表的第三方表创建这样的关系,该连接表的主键包括表 A 和表 B 中的外键。

例如,authors 表和 books 表是多对多关系,该关系通过从这些表中的每个表与 bookauthors 表的一对多关系定义。bookauthors 表的主键由 author_id 列(authors 表的主键)和 book_id 列(books 表的主键)组成。

注意:Case Studio 2 产生的SQLDDL)脚本并不完全正确。所以还要加以修改才可以使用。

Drop table "bookauthors" Restrict;

Drop table "books" Restrict;

Drop table "authors" Restrict;

 

Create table "authors"

(

       "id" Serial NOT NULL UNIQUE ,

       "title_id" integer,

       "name" Varchar(20),

       "sex" Boolean,

       "age" Smallint,

 primary key ("id")

);

 

Create table "books"

(

       "id" Serial NOT NULL UNIQUE ,

       "auther_id" integer,

       "title" Varchar(20),

       "content" Text,

 primary key ("id")

);

 

Create table "bookauthors"

(

       "id" Serial NOT NULL,

       "author_id" integer NOT NULL,

       "book_id" integer NOT NULL,

 primary key ("id","author_id","book_id")

改为

primary key ("id")

 

);

 

 

Alter table "bookauthors" add  foreign key ("author_id") references "authors" ("id") on update restrict on delete restrict;

Alter table "bookauthors" add  foreign key ("book_id") references "books" ("id") on update restrict on delete restrict;

4.4    一对一关系

在一对一关系中,表 A 中的一行最多只能与表 B 中的一行相匹配,反之亦然。如果两个相关列都是主键或具有唯一约束,则创建的是一对一关系。

这种关系不常见,因为这种方式的大部分相关信息都在一个表中。使用一对一关系可以是为了:

l         分割一个含有许多列的表。

l         出于安全考虑而隔离表的某一部分。

l         存储可以很容易删除的临时数据,只需删除表即可删除这些数据。

l         存储只应用于主表子集的信息。

l         一对一关系的主键方由键 符号表示。外键方也由键 符号表示。

 

Drop table "userinfo" Restrict;

Drop table "user" Restrict;

 

Create table "user"

(

       "id" Serial NOT NULL Default 0 UNIQUE ,

       "user" Varchar(20) NOT NULL UNIQUE ,

       "passwd" Varchar(20),

       "homedir" Varchar(20) NOT NULL Default /home/,

       "shell" Varchar(20) NOT NULL Default /bin/bash,

 primary key ("id")

);

 

 

Create table "userinfo"

(

       "id" integer NOT NULL Default 0,

       "tel" Varchar(20),

       "fax" Varchar(20),

       "address" Varchar(255),

       "company" Varchar(20),

       "note" Text,

 primary key ("id")

);

 

Alter table "userinfo" add  foreign key ("id") references "user" ("id") on update restrict on delete restrict;

 

4.5    引用完整性

引用完整性是一种规则系统,这些规则可确保相关表中各行间关系的有效性,并确保不会意外删除或更改相关的数据。

 

在强制引用完整性时必须遵循以下规则:

如果在相关表的主键中不存在某个值,则不能在相关表的外键列中输入该值。但是,可以在外键列中输入空值。例如,在 employee 表中没有包括某职员,则不能指明分配给该职员的工作,但是可在 employee 表的 job_id 列输入空值来指明没有给该职员分配工作。

如果在相关表中存在与某行匹配的行,则不能从主表中删除该行。例如,如果在 employee 表中给多个职员分配了由 jobs 表中某行所代表的工作时,则不能删除该行。

当主表的某行有相关行时,则不能更改主键值。例如,如果将 jobs 表中的一项工作分配给某职员,则不能从 employee 表中删除该职员。

 

当满足下述所有条件时,可以设置引用完整性:

1.         主表中相匹配的列是主键或具有唯一约束

2.         相关列具有相同的数据类型和长度。

3.         两个表属于同一个数据库。

4.         数据库关系图中的已强制关系和未强制关系

在数据库关系图中创建关系线将在相关表上创建外键约束,从而自动强制引用完整性。在数据库关系图中,已强制关系用实线表示。例如:

在关系图中,未强制关系用虚线表示,这种关系的外键约束被禁用。例如:

 

5       查询SQLDML

5.1    子查询

下面是一个子查询的例子表groupmemberrolemember是存储组成员、角色成员的表。

Create table "user"

(

       "id" Serial NOT NULL,

       "userid" Varchar(50) NOT NULL,

       "passwd" Varchar(50),

       "name"    Varchar(20)NOT NULL ,

       "nickname" Varchar(20)NOT NULL ,

       "active" Boolean Default 'F',

       "email"    Varchar(50) NOT NULL,

       "question" Varchar(255) NOT NULL,

       "answer" Varchar(255) NOT NULL,

       "begin_date" Timestamp Default now(),

       "end_date" Timestamp Default now(),

       UNIQUE (userid,email),

 primary key ("id")

);

Create index "user_index" on "user" using btree ("id","userid");

 

Create table "group"

(

       "id" Serial NOT NULL UNIQUE,

       "groupname" Varchar(20) NOT NULL,

       "description" Varchar(255),

       UNIQUE (groupname),

      PRIMARY KEY ("id")

);

Create index "group_index" on "group" using btree ("id","groupname");

 

Create table "groupmember"

(

       "id" Serial NOT NULL UNIQUE,

       "gid" integer NOT NULL Default 0,

       "uid" integer NOT NULL Default 0,

       primary key ("id")

);

 

-- ======================================================

--  'Foreign Key'

-- ======================================================

Alter table "groupmember" add  foreign key ("uid") references "user" ("id") on update restrict on delete restrict;

Alter table "groupmember" add  foreign key ("gid") references "group" ("id") on update restrict on delete restrict;

 

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

--  'vgroupmember'

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

-- DROP VIEW vgroupmember;

CREATE VIEW vgroupmember AS

    SELECT gm.id,gm.gid,g.groupname,gm.uid,u.userid,u.name

           FROM "group" g,"user" u,groupmember gm

        Where u.id = gm.uid and g.id = gm.gid

    ORDER BY gm.id;

 

member=> select * from groupmember ;

 id | gid | uid

----+-----+-----

  1 |   1 | 245

 10 |   7 | 200

 11 |   7 | 201

 12 |   7 | 202

 13 |   3 | 200

 14 |   3 | 201

 15 |   3 | 202

 16 |   3 | 203

 17 |   3 | 204

 18 |   3 | 205

 19 |   6 | 247

 20 |   6 | 201

 21 |   6 | 203

 22 |   6 | 204

 23 |   6 | 205

 24 |   3 | 249

 25 |   3 | 250

 26 |   7 | 251

 27 |   3 | 252

(19 rows)

 

(组ID3的用户列表)

member=> select * from groupmember where gid = 3;

 id | gid | uid

----+-----+-----

 13 |   3 | 200

 14 |   3 | 201

 15 |   3 | 202

 16 |   3 | 203

 17 |   3 | 204

 18 |   3 | 205

 24 |   3 | 249

 25 |   3 | 250

 27 |   3 | 252

(9 rows)

 

 

添加组成员步骤是:

1.         取用户idselect id from vuser where userid='sysop'

2.         取组名idselect id from "group" where groupname ='System'

3.         groupmember 表插入数据,insert into groupmember(gid,uid) values(组ID,用户ID

子查询,SQL语句应该写成:

insert into groupmember(gid,uid) values((select id from "group" where groupname ='System'),(select id from vuser where userid='sysop'));

 

插放数据测试:

member=> insert into groupmember(gid,uid) values((select id from "group" where groupname ='System'),(select id from vuser where userid='sysop'));

INSERT 110940 1

 

member=> select * from vgroupmember where gid = 1;

 id | gid | groupname | uid | userid | name

----+-----+-----------+-----+--------+------

  1 |   1 | System    | 245 | sysop  | chen

 (2 rows)

测试成功,因为数据id号难懂,不易查看,这里使用了一个视图。

5.2    substring()函数截取部分汉字

要截取汉字的首要条件是数据库编码必须是UNICODEUNICODE中英文一个字母=中文一个汉字长度。

如果使用非UNICODE编码的数据,EUC_CN会输出提示你输入加“'”。

pureftpd=> select substring('数据库的编码是用系统表' from 1 for 4);

pureftpd'>

pureftpd'>'

pureftpd(> )

pureftpd-> ;

ERROR:  parser: unterminated quoted identifier at or near ""

)" at character 69

 

       SQL_ASCII还是输出半个汉字。

help=> select substring('数据库的编码是用系统表' from 1 for 4);

 substring

-----------

 

(1 row)

 

查看数据库编码:

member=> \l

         List of databases

    Name    |  Owner   | Encoding

------------+----------+-----------

 help       | postgres | SQL_ASCII

 member     | chen     | UNICODE

 mydatabase | postgres | UNICODE

 postgres   | postgres | SQL_ASCII

 pureftpd   | pureftpd | EUC_CN

 site       | postgres | EUC_CN

 template0  | postgres | SQL_ASCII

 template1  | postgres | SQL_ASCII

(8 rows)

 

测试

member=> select substring('数据库的编码是用系统表' from 1 for 4);

 substring

-----------

 数据库的

(1 row)

 

member=> select substring('数据库的编码是用系统表' from 1 for 2);

 substring

-----------

 数据

(1 row)

 

member=> select * from ;

序号 |     组名     |         描述

------+--------------+----------------------

    1 | 域用户       | 9812.net域内用户

    3 | 计算机维护组 | 维护计算机的用户用户

(2 rows)

 

member=> select 组名,substring(描述 from 1 for 5) as 描述 from ;

     组名     |    描述

--------------+------------

 域用户       | 9812.

 计算机维护组 | 维护计算机

(2 rows)

5.3    sum()使用技巧

如果让你对表中的某一列求和,你可能会想到使用sum()函数。

Select num(field) from table;

Select num(field) from table where field …..;

 

如果我在表中选择一些记录,这记录之间没有规律可循,让你计算出这组数据的的和。

你可能马上想到用一个循环,然后相加结果,而不是使用sum()

例如:我要求id等于141082这几个记录的price字段的和,

Select field from table where id = 1;

Select field from table where id = 4;

…..

Select field from table where id = 2;

然后再将上面每次取得的数据相加。

 

下面我给大家介绍一种很方便的方法,就是使用子查询 in

select sum(price) from diy.part where id in (1,4,10,8,2);

 

netkiller=> select price from diy.part where id =1;

 price

--------

 848.00

(1 row)

 

netkiller=> select price from diy.part where id =2;

 price

--------

 880.00

(1 row)

 

netkiller=> select sum(price) as price from diy.part where id in (1,2);

  price

---------

 1728.00

(1 row)

 

netkiller=>

 

5.4    集合查询 (合并n个表)

在网上很多朋友问我,如何合并两个结构一样的表,答案有2种方法可以完成,第一种方法使用UNION,第二种方法是使用子查询。要注意一点UNION的功能不只合并两个结构一样,还可以合并多个结构不一样的表。

 

方法1

 

UNION

 

SQL Statement 1 UNION [ALL] SQL Statement 2 UNION [ALL] SQL Statement n

 

 

例子:

netkiller=> select rolename from roles ;

   rolename

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

 Administrator

 gold

 silver

 advance

 free

 System

 OA

(7 rows)

 

netkiller=> select groupname from groups;

   groupname

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

 System

 Administrator

 gold

 silver

 advance

 free

 Company

 Person

 OA

(9 rows)

 

netkiller=> select rolename from roles union select groupname from groups;

   rolename

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

 Administrator

 advance

 Company

 free

 gold

 OA

 Person

 silver

 System

(9 rows)

 

netkiller=>

合并三个表

netkiller=> select rolename from roles union select groupname from groups union select name from person;

   rolename

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

 Administrator

 advance

 baba

 chen

 chenhongxi

 Company

 CRM

 dddd

 free

 Genenral

 gold

 HEHE

 none

 OA

 Person

 Romain

 silver

 System

 USB

 刘晓飞

 叶凤岚

 周信华

 崔敏

 张锋

 张锡云

 曹健财

 李金友

 樊厘

 王启军

 王延川

 赵凯

 邬艳

 郑良璇

 郭万海

 金志文

 

可能大家注意到了UNION 将两个表中重复的行,只输出一次。如果想全部输出可以使用
UNION ALL

netkiller=> select rolename from roles union all select groupname from groups as chen;

   rolename

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

 Administrator

 gold

 silver

 advance

 free

 System

 OA

 System

 Administrator

 gold

 silver

 advance

 free

 Company

 Person

 OA

(16 rows)

 

netkiller=>

 

方法2

       使用子查询将第二张表中的数据追加到第一张表的后面

Insert into table1(field1,field2…..fieldn) select field1,field2…..fieldn from table2

详细请参考http://www.pgsqldb.org/pgsqldoc-cvs/queries-union.html

6       视图

视图

试图是关系型数据库系统提供给用户以多种角度观察数据库中数据的重要机制。

试图是从一个或几个基本表(或视图)导出的表,它与基本表不同,是一个虚拟表。数据库中只存放视图的定义,而不存放视图对应的数据,这些数据仍存放在原来的基本表中。所以基本表中的数据发生变化时,从视图中查询出的数据也就随之改变了。也就是说,试图就像一个窗口,透过它可以看到数据库中自己感兴趣的数据及变化。

试图一经定义,就可以像基本表一样被查询、被删除,我们也可以在一个视图之上再定义新的视图,但对视图的更新(添加、删除、修改)操作则有一定的限制。

本节专门讨论视图的定义、操作及优点。

 

试图的作用:

1.         视图能够简化用户的操作

2.         视图使用户能以多种角度看待同一数据

3.         视图对重构数据库提供了一定程度的逻辑独立性

4.         视图能够对机密数据提供安全保护

 

我在工作中发现很多程序员开发数据应该程序。SQL语句写了五六行,每行最少100个字符。好比如下:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAA

这么一大堆 !@%%#@%@^#$&$&%*&^*%^(&)(*) faint 写这么长主要的操作是“,”号join操作。

我的习惯是先使用VIEW做第一次的过滤,然后在做第二次查询。最后的操作基本上都是
Select * from table where xxx = xxxx order by xxxx ASC limit x offset x
操作读出想要的记录。

6.1    VIEW基本使用实例

这是一个最基本用法。这里主要用于格式化Timestamp 输出2003-09-24 11:23:29格式。

CASE WHEN u.active=true THEN 'Y' ELSE 'N' END as "active" SQL CASE 表达式是一种通用的 条件表达式,类似于其它语言中的 if/else 语句。

 

-- ======================================================

--  'user' 

-- ======================================================  

Create table "user"

(

       "id" Serial NOT NULL,

       "userid" Varchar(50) NOT NULL,

       "passwd" Varchar(50),

       "name"    Varchar(20)NOT NULL ,

       "nickname" Varchar(20)NOT NULL ,

       "active" Boolean Default 'F',

       "email"    Varchar(50) NOT NULL,

       "question" Varchar(255) NOT NULL,

       "answer" Varchar(255) NOT NULL,

       "begin_date" Timestamp Default now(),

       "end_date" Timestamp Default now(),

       UNIQUE (userid,email),

 primary key ("id")

);

Create index "user_index" on "user" using btree ("id","userid");

 

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

--  'vuser'

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

drop view vuser;

CREATE VIEW vuser AS

    SELECT u.id,u.userid,u."name",u.nickname,

           CASE WHEN u.active=true THEN 'Y' ELSE 'N' END as "active",

           u.email,u.question,u.answer,

           to_char(u.begin_date,'YYYY-MM-DD HH:MI:SS') as begin_date,

           to_char(u.end_date,'YYYY-MM-DD HH:MI:SS') as end_date

    FROM "user" u

    Order By u.id;

6.2    使用HTML格式化VIEW的实例

-- ======================================================

--  'user' 

-- ======================================================  

Create table "user"

(

       "id" Serial NOT NULL,

       "userid" Varchar(50) NOT NULL,

       "passwd" Varchar(50),

       "name"    Varchar(20)NOT NULL ,

       "nickname" Varchar(20)NOT NULL ,

       "active" Boolean Default 'F',

       "email"    Varchar(50) NOT NULL,

       "question" Varchar(255) NOT NULL,

       "answer" Varchar(255) NOT NULL,

       "begin_date" Timestamp Default now(),

       "end_date" Timestamp Default now(),

       UNIQUE (userid,email),

 primary key ("id")

);

Create index "user_index" on "user" using btree ("id","userid");

 

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

--  'vuser'

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

drop view vuser1;

 

CREATE OR REPLACE VIEW vuser1 AS

    SELECT '<center>'||u.id||'</center>' as ID,'<font color=red>'||u.userid||'</font>' as "用户名",u."name" as "姓名",u.nickname as "昵称",

           CASE WHEN u.active=true THEN '启用' ELSE '禁用' END as "active",

           u.email,u.question,u.answer,

           to_char(u.begin_date,'YYYYMMDD HH:MI:SS') as begin_date,

           to_char(u.end_date,'YYYYMMDD HHMISS') as end_date

    FROM "user" u

    Order By u.id;

 

member=> select * from vuser1;

         id         |          用户名           | 姓名 | 昵称 | active |     email     | question | answer |         begin_date         |            end_date

--------------------+------------------------------+--------+--------+--------+---------------+----------+--------+----------------------------+--------------------------------

 <center>1</center> | <font color=red>sysop</font> | chen   | chen   | 启用 | chen@chen.com | xxxxxxx  | xxxx   | 20030924 11:23:29 | 20030924 112329

 <center>2</center> | <font color=red>admin</font> | chen   | chen   | 禁用 | chen@chen.com | xxxxxxx  | xxxx   | 20030924 11:23:29 | 20030930 112329

 

下面有一下更大胆的用法。

-- ======================================================

--  'group'

-- ======================================================

Create table "group"

(

       "id" Serial NOT NULL UNIQUE,

       "groupname" Varchar(20) NOT NULL,

       "description" Varchar(255),

       UNIQUE (groupname),

      PRIMARY KEY ("id")

);

Create index "group_index" on "group" using btree ("id","groupname");

DROP VIEW vgroup;

CREATE VIEW vgroup AS

    SELECT '<tr>'||g.id||'</td>' as id,'<tr>'||g.groupname||'</td>' as groupname,'<tr>'||g.description||'</td>' as desc

           FROM "group" g

    ORDER BY g.id;

 

postgres=# DROP VIEW vgroup;

ERROR:  view "vgroup" does not exist

postgres=# CREATE VIEW vgroup AS

postgres-#     SELECT '<tr>'||g.id||'</td>' as id,'<tr>'||g.groupname||'</td>' as groupname,'<tr>'||g.description||'</td>' as desc

postgres-#     FROM "group" g

postgres-#     ORDER BY g.id;

CREATE VIEW

postgres=# select * from vgroup ;

     id      |    groupname    |            desc

-------------+-----------------+-----------------------------

 <tr>1</td>  | <tr>Admin</td>  | <tr>xxxxxxxxxxxxxxxxxx</td>

 <tr>2</td>  | <tr>Guest</td>  | <tr>xxxxxxxxxxxxxxxxxx</td>

 <tr>3</td>  | <tr>Domain</td> | <tr>xxxxxxxxxxxxxxxxxx</td>

 <tr>4</td>  | <tr>Admin</td>  | <tr>xxxxxxxxxxxxxxxxxx</td>

 <tr>5</td>  | <tr>Guest</td>  | <tr>xxxxxxxxxxxxxxxxxx</td>

 <tr>6</td>  | <tr>Domain</td> | <tr>xxxxxxxxxxxxxxxxxx</td>

 <tr>7</td>  | <tr>Admin</td>  | <tr>xxxxxxxxxxxxxxxxxx</td>

 <tr>8</td>  | <tr>Guest</td>  | <tr>xxxxxxxxxxxxxxxxxx</td>

 <tr>9</td>  | <tr>Domain</td> | <tr>xxxxxxxxxxxxxxxxxx</td>

 <tr>10</td> | <tr>Admin</td>  | <tr>xxxxxxxxxxxxxxxxxx</td>

 <tr>11</td> | <tr>Guest</td>  | <tr>xxxxxxxxxxxxxxxxxx</td>

 <tr>12</td> | <tr>Domain</td> | <tr>xxxxxxxxxxxxxxxxxx</td>

 <tr>13</td> | <tr>Admin</td>  | <tr>xxxxxxxxxxxxxxxxxx</td>

 <tr>14</td> | <tr>Guest</td>  | <tr>xxxxxxxxxxxxxxxxxx</td>

 <tr>15</td> | <tr>Domain</td> | <tr>xxxxxxxxxxxxxxxxxx</td>

(15 rows)

 

进一步修改上面的VIEW,使它更方便输出。

DROP VIEW vgroup;

CREATE VIEW vgroup AS

    SELECT '<tr align=center>'||g.id||'</td>' as id,

    '<tr align=left><font color=red><b>'||g.groupname||'</b></font></td>' as groupname,

    '<tr><i>'||g.description||'</i></td>' as desc

    FROM "group" g

    ORDER BY g.id;

postgres=# select * from vgroup ;

            id            |                        groupname                         |                desc

--------------------------+----------------------------------------------------------+------------------------------------

 <tr align=center>1</td>  | <tr align=left><font color=red><b>Admin</b></font></td>  | <tr><i>xxxxxxxxxxxxxxxxxx</i></td>

 <tr align=center>2</td>  | <tr align=left><font color=red><b>Guest</b></font></td>  | <tr><i>xxxxxxxxxxxxxxxxxx</i></td>

 <tr align=center>3</td>  | <tr align=left><font color=red><b>Domain</b></font></td> | <tr><i>xxxxxxxxxxxxxxxxxx</i></td>

 <tr align=center>4</td>  | <tr align=left><font color=red><b>Admin</b></font></td>  | <tr><i>xxxxxxxxxxxxxxxxxx</i></td>

 <tr align=center>5</td>  | <tr align=left><font color=red><b>Guest</b></font></td>  | <tr><i>xxxxxxxxxxxxxxxxxx</i></td>

 <tr align=center>6</td>  | <tr align=left><font color=red><b>Domain</b></font></td> | <tr><i>xxxxxxxxxxxxxxxxxx</i></td>

 <tr align=center>7</td>  | <tr align=left><font color=red><b>Admin</b></font></td>  | <tr><i>xxxxxxxxxxxxxxxxxx</i></td>

 <tr align=center>8</td>  | <tr align=left><font color=red><b>Guest</b></font></td>  | <tr><i>xxxxxxxxxxxxxxxxxx</i></td>

 <tr align=center>9</td>  | <tr align=left><font color=red><b>Domain</b></font></td> | <tr><i>xxxxxxxxxxxxxxxxxx</i></td>

 <tr align=center>10</td> | <tr align=left><font color=red><b>Admin</b></font></td>  | <tr><i>xxxxxxxxxxxxxxxxxx</i></td>

 <tr align=center>11</td> | <tr align=left><font color=red><b>Guest</b></font></td>  | <tr><i>xxxxxxxxxxxxxxxxxx</i></td>

 <tr align=center>12</td> | <tr align=left><font color=red><b>Domain</b></font></td> | <tr><i>xxxxxxxxxxxxxxxxxx</i></td>

 <tr align=center>13</td> | <tr align=left><font color=red><b>Admin</b></font></td>  | <tr><i>xxxxxxxxxxxxxxxxxx</i></td>

 <tr align=center>14</td> | <tr align=left><font color=red><b>Guest</b></font></td>  | <tr><i>xxxxxxxxxxxxxxxxxx</i></td>

 <tr align=center>15</td> | <tr align=left><font color=red><b>Domain</b></font></td> | <tr><i>xxxxxxxxxxxxxxxxxx</i></td>

(15 rows)

 

上面的例子输出数据中代有HTML标记,在B/S结构程序的开发中很方便。当输出数据要改变风格时,只要CREATE OR REPLACE VIEW your_view AS 就可以,而不必关心页面与程序。

6.3    view中使用汉字做字段名

下面是一个使用汉字做字段名的例子,输出类似表格:

ID

组名

描述

3

Backup Admin

系统管理员

2

Power Admin

系统管理员

1

System Admin

系统管理员

 

ID |    组名    |     描述

----+--------------+-----------------

  3 | Backup Admin | 系统管理员

  2 | Power Admin  | 系统管理员

  1 | System Admin | 系统管理员

 

DROP VIEW vgroup;

CREATE VIEW vgroup AS

    SELECT g.id as "ID",g.groupname as "组名",g.description as "描述"

    FROM "group" g

    ORDER BY g.groupname;

postgres=# CREATE VIEW vgroup AS

postgres-#     SELECT g.id as "ID",g.groupname as "组名",g.description as "描述"

postgres-#     FROM "group" g

postgres-#     ORDER BY g.groupname;

CREATE VIEW

postgres=# \d vgroup

            View "public.vgroup"

 Column |          Type          | Modifiers

--------+------------------------+-----------

 ID     | integer                |

 组名 | character varying(20)  |

 描述 | character varying(255) |

View definition: SELECT g.id AS "ID", g.groupname AS "组名", g.description AS "描述" FROM "group" g ORDER BY g.groupname;

postgres=# insert into "group"(groupname,description) values('System Admin','系统管理员');

INSERT 35031 1

postgres=# insert into "group"(groupname,description) values('Power Admin','系统管理员');

INSERT 35032 1

postgres=# insert into "group"(groupname,description) values('Backup Admin','系统管理员');

INSERT 35033 1

postgres=# select * from vgroup ;

 ID |    组名    |     描述

----+--------------+-----------------

  3 | Backup Admin | 系统管理员

  2 | Power Admin  | 系统管理员

  1 | System Admin | 系统管理员

(3 rows)

postgres=#

6.4    取出字符如果超过20个在后尾加“…”

实现方法:

1.         首先在取字符长度,可以使用character_length()char_length()函数,它们的功能是一样的。

2.         然后判断字符是否大于20个。

3.         大于20个字符,使用substring()函数截取前20个字符。并在后尾加上“

4.         如果小于20个字符,直接取出

5.         要注意数据转换。使用::varchar(长度)

实例:

DROP SCHEMA oa CASCADE;

CREATE SCHEMA oa;

SET search_path TO public,btob,btoc,ctoc,oa;

-- ======================================================================

-- 'oa.meeting'

-- ======================================================================

Drop table oa.meeting CASCADE;

 

Create table oa.meeting

(

    "id"  Serial NOT NULL UNIQUE,

    "subject"  varchar(100) NOT NULL,

    "caller"    Varchar(10) NOT NULL ,

    "begin_time" Timestamp Default current_timestamp::timestamp (0) without time zone,

    "end_time"      Timestamp Default current_timestamp::timestamp (0) without time zone,

    "place"    Varchar(100) NOT NULL ,

    "prolocutor" Varchar(10) NOT NULL ,

    "conferee"      Varchar(255) NOT NULL ,

    "recorder"       Varchar(10) NOT NULL ,

    "leitmotiv"  Varchar(255) NOT NULL ,

    "details"  text,

    UNIQUE (subject),

    PRIMARY KEY ("id")

);

 

DROP VIEW oa.vmeeting;

CREATE OR REPLACE VIEW oa.vmeeting  AS

    SELECT id,CASE WHEN character_length(subject)>20 THEN substring(subject,1,20)||'...'::varchar(20) ELSE subject::varchar(20) END,

       caller,to_char(begin_time,'YYYY-MM-DD HH:MI') as begin_time,

       CASE WHEN character_length(place)>10 THEN substring(place,1,10)||'...'::varchar(15) ELSE place::varchar(20) END as place,

       prolocutor

    FROM oa.meeting

    Order By id DESC;

select * from oa.vmeeting;

 

6.5    视图中使用子查询

在下面的例子中status字段是来自ctoc.vbid视图中的status 字段。

注意:(select status from ctoc.vbid where uid = f.uid limit 1) as status红色部分,如果没有使用limit返回的将是结果集,在查询时会抛出异常。

ERROR:  More than one tuple returned by a subselect used as an expression.

 

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

--  'ctoc.vfavorites'

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

DROP VIEW ctoc.vfavorites;

CREATE OR REPLACE VIEW ctoc.vfavorites AS

    SELECT        f.id,

                  f.uid,

                  f.salesroom_id,

                  s.subject as subject,

                  (select status from ctoc.vbid where uid = f.uid limit 1) as status,

                   to_char(f.created,'YYYY/MM/DD HH24:MI:SS') as date

        FROM ctoc.favorites f, person p,ctoc.salesroom s

        WHERE f.uid = p.uid and f.salesroom_id = s.id

        ORDER BY f.id;

netkiller=> select * from ctoc.vfavorites;

 id | uid | salesroom_id |    subject    |              status               |        date

----+-----+--------------+---------------+-----------------------------------+---------------------

 12 |   8 |            1 | 我买MP3 | <font color="#3399FF">出局</font> | 2004/03/01 16:30:29

 13 |  95 |            1 | 我买MP3 | <font color=red>领先</font>       | 2004/03/01 16:36:39

(2 rows)

 

netkiller=>

 

select * from ctoc.vfavorites;

 

7       过程与函数

在其它数据中分别存在过程与函数,它们的功能没有区别,为什么要分为成过程与函数呢。因为过程是没有返回值的,而函数是要通过RETURN返回值的。返回值可以是任意一个符合SQL 数据类型的值或结果集,在PostgreSQL中过程与函数都是使用CREATE  FUNCTION语句来创建。

7.1    基本使用实例

我们创建一个名为system_log的表。通过add_system_log()这个过程追加记录,有些朋友可能认为这是多此一举,我们过程来完成当然有自己的想法,好处是用户不必关心数据库结构和SQL语句,可以方便地在任何语言中调用。

 

DROP TABLE system_log CASCADE;

Create table system_log

(

       id    Serial NOT NULL UNIQUE,

       uid integer NOT NULL Default 0,

       ip    inet ,

       status varchar(255),

       description varchar(255),

       login_date Timestamp Default now(),

       PRIMARY KEY("id"),

      FOREIGN KEY (uid) REFERENCES "user" (id)

);

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

-- 'Function'

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

-- DROP FUNCTION add_system_log(integer,inet,varchar);

CREATE OR REPLACE FUNCTION add_system_log(integer,inet,varchar,varchar) RETURNS boolean AS '

       DECLARE

           vUID              ALIAS FOR $1;

           vIP               ALIAS FOR $2;

              vSTATUS       ALIAS FOR $3;

              vDESC          ALIAS FOR $4;

       BEGIN

         insert into system_log(uid,ip,status,description) values(vUID,vIP,vSTATUS,vDESC);

         RETURN true;

      END;

' LANGUAGE 'plpgsql';

select add_system_log(1,'127.0.0.1','Create Database','Initialization Database');

member=> select add_system_log(1,'127.0.0.1','Create Database','Initialization Database');

 add_system_log

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

 t

(1 row)

member=> select * from system_log ;

id | uid |   ip      | status  |    description    |     login_date

--+-----+---------------+---------+------------------------+----------------------------

 

1 |  2 | 192.168.0.5  | 上线 | 密码             | 2003-09-26 15:33:18.6732

2 |  2 | 192.168.0.2  | 登录 | 用户admin       | 2003-09-26 16:19:21.824283

3 |  2 | 192.168.1.31 | 登录 | 用户admin        | 2003-09-26 17:10:47.269064

(3 rows)

 

member=> select add_system_log(1,'127.0.0.1','Create Database','Initialization Database') as log;

 log

-----

 t

(1 row)

7.2    过程中使用Select Into

这里有两个例子adduser(varchar,varchar)deluser(integer)

函数adduser(用户名,密码)             

返回:布尔值ture成功,false失败

功能:添加用户,首先查看用户是否存在,如果用户存在就返回false,如果用户不存在就插入记录并返回true

 

函数:deluser(用户ID)

返回:布尔值ture成功,false失败

功能:删除用户,如果用户存在就删除用户并返回true,如果用户不存在就返回false

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

--  'siteuser'

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

--DROP TABLE IF EXISTS siteuser;

DROP TABLE siteuser CASCADE;

DROP SEQUENCE siteuser_id_seq;

DROP INDEX siteuser_id_index;

 

CREATE TABLE siteuser (

     id integer DEFAULT nextval('siteuser_id_seq') NOT NULL,

     username varchar(20) DEFAULT '0' NOT NULL,

     Password       varchar(50) DEFAULT '0' NOT NULL,

     realname  varchar(10) DEFAULT '0' NOT NULL,

     email              varchar(50) DEFAULT '0' NOT NULL,

     create_date  timestamp DEFAULT now(),

     modify_date  timestamp DEFAULT now(),

     UNIQUE               (id,username),

       PRIMARY      KEY (id)

);

CREATE SEQUENCE siteuser_id_seq;

CREATE INDEX siteuser_id_index ON siteuser (id);

 

DROP FUNCTION adduser(varchar,varchar);

CREATE OR REPLACE FUNCTION adduser(varchar,varchar) RETURNS boolean AS '

       DECLARE

           bool boolean := false;

           name text;     

           uid   integer;

           user ALIAS FOR $1;

           pass ALIAS FOR $2;

           su    siteuser%ROWTYPE;

       BEGIN

           SELECT INTO name username FROM siteuser WHERE username = user;

             IF NOT FOUND then

              insert into siteuser(username,password) values(user,pass);

            SELECT INTO uid id FROM siteuser WHERE username = user;

              bool := true;

             ELSE

                     bool := false;

                     RAISE NOTICE ''Calling adduser() return %'',bool;

           END IF;

    RETURN bool;

      END;

' LANGUAGE 'plpgsql';

 

select adduser('ccscc','eeee');

select * from siteuser ;

 

DROP FUNCTION deluser(integer);

CREATE OR REPLACE FUNCTION deluser(integer) RETURNS boolean AS '

    DECLARE

           bool boolean := false;

           userid text;

       BEGIN

              SELECT INTO userid id FROM siteuser WHERE id = $1;

              IF FOUND then

                  delete from siteuser where id = $1;

                  bool := true;

           ELSE

           END IF;

           RETURN bool;

      END;

' LANGUAGE 'plpgsql';

 

select deluser(1);

 

7.3    返回integer

CREATE OR REPLACE FUNCTION get_user_id(varchar) RETURNS integer AS '

       DECLARE

           vUser      ALIAS FOR $1;

           uid integer;

       BEGIN

         SELECT INTO uid id FROM "users" WHERE userid = vUser;

         RETURN uid;

      END;

' LANGUAGE 'plpgsql';

7.4    返回void

 

CREATE OR REPLACE FUNCTION enable_user(varchar) RETURNS void AS '

       DECLARE

           vUser      ALIAS FOR $1;

       BEGIN

              Update "users" set status = ''true'' where userid = vUser;

              RETURN;

      END;

' LANGUAGE 'plpgsql';

 

CREATE OR REPLACE FUNCTION disable_user(varchar) RETURNS void AS '

       DECLARE

           vUser      ALIAS FOR $1;

       BEGIN

              Update "users" set status = ''false'' where userid = vUser;

              RETURN;

      END;

' LANGUAGE 'plpgsql';      

 

7.5    返回结果集record

create table test(a int, b int);

insert into test values(1,1);

insert into test values(2,2);

insert into test values(3,3);

insert into test values(4,4);

insert into test values(5,5);

insert into test values(6,6);

insert into test values(7,7);

insert into test values(8,8);

insert into test values(9,9);

 

create or replace function fun_test_record() returns setof record as '

       declare

       rec record;

       begin

      

              FOR rec IN SELECT * FROM test LOOP

                     RETURN NEXT rec;

              END LOOP;

              return NULL;

             

       end;

'language 'plpgsql';

 

select a,b from fun_test_record() test(a int, b int);

 

测试:

9812_net=> select a,b from fun_test_record() test(a int, b int);

 a | b

---+---

 1 | 1

 2 | 2

 3 | 3

 4 | 4

 5 | 5

 6 | 6

 7 | 7

 8 | 8

 9 | 9

(9 rows)

 

9812_net=> select test.a,test.b from fun_test_record() test(a int, b int);

 a | b

---+---

 1 | 1

 2 | 2

 3 | 3

 4 | 4

 5 | 5

 6 | 6

 7 | 7

 8 | 8

 9 | 9

(9 rows)

 

9812_net=>

9812_net=> EXPLAIN select a,b from fun_test_record() test(a int, b int);

                                 QUERY PLAN

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

 Function Scan on fun_test_record test  (cost=0.00..12.50 rows=1000 width=8)

(1 row)

 

9812_net=> EXPLAIN select * from test;

                       QUERY PLAN

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

 Seq Scan on test  (cost=0.00..20.00 rows=1000 width=8)

(1 row)

 

9812_net=>

 

JDBC API中使用。你尽管当它是一个SQL语句。

个人建议使用游标代替record,因为游标更方便。

7.6    例子

例子1

-- ======================================================================

--  'btoc.order_form'

-- ======================================================================

/*

       number 订单号/业务跟踪号 30. 14位为日期时间,-后面的15位为随机数

*/

DROP TABLE btoc.order_form CASCADE;

CREATE TABLE btoc.order_form (

    id            Serial NOT NULL UNIQUE,

    category_id  integer DEFAULT '0' NOT NULL,  -- foreign key

    number   varchar (35) NOT NULL,

    person_id    integer DEFAULT '0' NOT NULL, -- foreign key

    status      Varchar(10) Default '0' Check (status in ('0','1','2','3','4','5')),

    created    Timestamp Default current_timestamp::timestamp (0) without time zone,

    modified  Timestamp Default current_timestamp::timestamp (0) without time zone,

    UNIQUE (number),

    PRIMARY KEY (id),

    FOREIGN KEY (category_id) REFERENCES btoc.product_category (id) ON UPDATE CASCADE ON DELETE CASCADE,

    FOREIGN KEY (person_id) REFERENCES person (uid) ON UPDATE CASCADE ON DELETE CASCADE

);

CREATE INDEX btoc_order_form_index ON btoc.order_form (id,number,status);

 

CREATE OR REPLACE FUNCTION btoc.sp_order_form(Integer,Integer,varchar) RETURNS Integer AS '

       DECLARE

           ofid integer;

               cid ALIAS FOR $1;

               ofuid ALIAS FOR $2;

               ofstatus ALIAS FOR $3;

               num varchar(35);

       BEGIN

           select into num to_char(CURRENT_TIMESTAMP,''YYYYMMDDHH24MISS'')||''-''||to_char(random(),''FM9V9999999999999990'')::varchar(15);

               Insert into btoc.order_form(category_id,number,person_id,status) values (cid,num,ofuid,ofstatus);

               Select into ofid id FROM btoc.order_form WHERE number = num;

          IF FOUND then

                   RETURN ofid;

               ELSE

                   RAISE EXCEPTION ''Inexistent ID --> %'',ofid;

               END IF; 

      END;

' LANGUAGE 'plpgsql';

 

7.7    shell 过程语言

http://developer.postgresql.org/~petere/pgplsh/pgplsh-1.0-7.3.tar.gz

 

 

 

8       规则

这里有两上规则例子role_rulegroup_rule。它们功能都是删除其它表中受外键约束的记录。用触发器也可以实现同样功能,触发器繁琐,要写一个过程。而规则灵巧得多。

如果是单一的SelectUpdateInsert Delect推荐使用规则。如果要同时Update,Insert, Delect可以使用触发器

             IF TG_OP = ''UPDATE'' THEN

                  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

           END IF;

             IF TG_OP = ''INSERT'' THEN

                  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

                  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

           END IF;

             IF TG_OP = ''DELETE'' THEN

                  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

                  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

                  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

           END IF;

8.1    规则实例

-- ======================================================

--  'group'

-- ======================================================

Create table "group"

(

       "id" Serial NOT NULL UNIQUE,

       "groupname" Varchar(20) NOT NULL,

       "description" Varchar(255),

       UNIQUE (groupname),

      PRIMARY KEY ("id")

);

Create index "group_index" on "group" using btree ("id","groupname");

-- ======================================================

--  'groupmember'

-- ======================================================

Create table "groupmember"

(

       "id" Serial NOT NULL UNIQUE,

       "gid" integer NOT NULL Default 0,

       "uid" integer NOT NULL Default 0,

       primary key ("id")

);

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

--  'vgroupmember'

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

-- DROP VIEW vgroupmember;

CREATE VIEW vgroupmember AS

    SELECT gm.id,gm.gid,g.groupname,gm.uid,u.userid,u.name

           FROM "group" g,"user" u,groupmember gm

        Where u.id = gm.uid and g.id = gm.gid

    ORDER BY gm.id;

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

--  'RULE'

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

CREATE RULE group_rule AS ON Delete TO "group"

    DO Delete From groupmember where gid = OLD.id;

 

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

--  'Insert Data'

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

Insert into "group"(groupname,description) values('System','系统管理员');

Insert into "group"(groupname,description) values('Administrator','站点管理员');

Insert into "group"(groupname,description) values('gold','');

Insert into "group"(groupname,description) values('silver','');

Insert into "group"(groupname,description) values('copper','');

Insert into "group"(groupname,description) values('advance','高级会员');

Insert into "group"(groupname,description) values('free','免费会员');

 

-- ======================================================

--  'role'

-- ======================================================

-- drop table role CASCADE;

Create table "role"

(

       "id" Serial NOT NULL UNIQUE,

       "rolename" Varchar(20) NOT NULL,

       "description" Varchar(255),

       UNIQUE (rolename),

      PRIMARY KEY ("id")

);

Create index "role_index" on "role" using btree ("id","rolename");

 

-- ======================================================

--  'rolemember' 

-- ======================================================

-- drop table rolemember CASCADE ;

Create table "rolemember"

(

       "id" Serial NOT NULL UNIQUE,

       "rid" integer NOT NULL Default 0,

       "uid" integer NOT NULL Default 0,

 primary key ("id")

);

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

--  'vrolemember'

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

CREATE VIEW vrolemember AS

    SELECT rm.id,rm.rid,r.rolename,rm.uid,u.userid,u.name

           FROM "role" r,"user" u,rolemember rm

        Where u.id = rm.uid and r.id = rm.rid

        ORDER BY rm.id;

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

--  'RULE'

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

CREATE RULE role_rule AS ON Delete TO role

    DO Delete From rolemember where rid = OLD.id;

 

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

--  'Insert Data'

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

Insert into role(rolename,description) values('System','系统管理员');

Insert into role(rolename,description) values('Administrator','站点管理员');

Insert into role(rolename,description) values('gold','');

Insert into role(rolename,description) values('silver','');

Insert into role(rolename,description) values('copper','');

Insert into role(rolename,description) values('advance','高级会员');

Insert into role(rolename,description) values('free','免费会员');

 

-- ======================================================

--  'Foreign Key'

-- ======================================================

Alter table "groupmember" add  foreign key ("uid") references "user" ("id") on update restrict on delete restrict;

Alter table "groupmember" add  foreign key ("gid") references "group" ("id") on update restrict on delete restrict;

Alter table "rolemember" add  foreign key ("uid") references "user" ("id") on update restrict on delete restrict;

Alter table "rolemember" add  foreign key ("rid") references "role" ("id") on update restrict on delete restrict;

9       触发器

9.1    一般用法

下面clientinfo_tri触发器与clientinfo_rule规则功能相同。

 

CREATE OR REPLACE FUNCTION clientinfo_tri_func () RETURNS opaque AS '

      BEGIN

           Delete from prodorder where clientinfo_id = OLD.id;

    RETURN OLD;

      END;

' LANGUAGE 'plpgsql';

 

DROP TRIGGER clientinfo_tri on clientinfo;

CREATE TRIGGER clientinfo_tri

       BEFORE Delete ON clientinfo FOR EACH ROW

       EXECUTE PROCEDURE clientinfo_tri_func ();

 

CREATE RULE clientinfo_rule AS ON Delete TO prodorder

    DO        Delete from prodorder where clientinfo_id = OLD.id;

9.2    多个触发器使用同一个过程

这是一个多个触发器使用同一个函数例子。

触发器siteuser_delete_tri功能是:

当删除siteuser表中记录时,首先删除其它表中受外键约束的记录,如果不使用触发器或规则来完成,就很麻烦了。

如下:

       Begin;

                  Delete from company where uid = id;

                 Delete from link where uid = id;

                 Delete from product_sort where uid = id;

                  Delete from news where uid = id;

                  Delete from count where uid = id;

                  Delete from guestbook where uid = id;

                  Delete from clientinfo where uid = id;

                  Delete from column_bar where uid = id;

                  Delete from drumbeating where uid = id;

                     Commit;

       在程序中完成上面的操作,

           String sql1="Delete from company where uid = ?";

           String sql2="Delete from link where uid = ?";

           String sql3="Delete from product_sort where uid = ?";

           String sql4="Delete from news where uid = ?";

           String sql5="Delete from count where uid = ?";

           String sql6="Delete from guestbook where uid = ?";

           String sql7="Delete from clientinfo where uid = ?";

           String sql8="Delete from column_bar where uid = ?";

           String sql9="Delete from drumbeating where uid = ?";

              String id  = <your-id>;

DBConnect odb = null;

              try{

                     odb = new DBConnect(oDatabase);

                     odb.Begin();

                     odb.prepareStatement(sql1);

odb.setString(1,id);

                     rs = odb. executeUpdate ();

                     odb.prepareStatement(sql2);

odb.setString(1,id);

                     rs = odb. executeUpdate ();

                     odb.prepareStatement(sql3);

odb.setString(1,id);

                     rs = odb. executeUpdate ();

                     odb.prepareStatement(sql4);

odb.setString(1,id);

                     rs = odb. executeUpdate ();

                     odb.prepareStatement(sql5);

odb.setString(1,id);

                     rs = odb. executeUpdate ();

                     odb.prepareStatement(sql6);

odb.setString(1,id);

                     rs = odb. executeUpdate ();

                     odb.prepareStatement(sql7);

odb.setString(1,id);

                     rs = odb. executeUpdate ();

                     odb.prepareStatement(sql8);

odb.setString(1,id);

                     rs = odb. executeUpdate ();

                     odb.prepareStatement(sql9);

odb.setString(1,id);

                     rs = odb. executeUpdate ();

                    

                     odb.Commit();

              }

              catch(Exception e){

                     e.printStackTrace();

              }

              finally{

                     try{

                            odb.close();

                     }catch(Exception e){

                            e.printStackTrace();

                     }

              }

触发器siteuser_insert_tri功能是:

当向siteuser表中插入记录时同时向companycountdrumbeating……表中增加一条记录。

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

--  'siteuser'

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

--DROP TABLE IF EXISTS siteuser;

DROP TABLE siteuser CASCADE;

DROP SEQUENCE siteuser_id_seq;

DROP INDEX siteuser_id_index;

 

CREATE TABLE siteuser (

     id integer DEFAULT nextval('siteuser_id_seq') NOT NULL,

     username varchar(20) DEFAULT '0' NOT NULL,

     Password       varchar(50) DEFAULT '0' NOT NULL,

     realname  varchar(10) DEFAULT '0' NOT NULL,

     email              varchar(50) DEFAULT '0' NOT NULL,

     create_date  timestamp DEFAULT now(),

     modify_date  timestamp DEFAULT now(),

     UNIQUE               (id,username),

       PRIMARY      KEY (id)

);

CREATE SEQUENCE siteuser_id_seq;

CREATE INDEX siteuser_id_index ON siteuser (id);

 

DROP FUNCTION siteuser_tri_func() CASCADE ;

CREATE OR REPLACE FUNCTION siteuser_tri_func () RETURNS opaque AS '

--    DECLARE

--         user_id CONSTANT INTEGER := OLD.id;

      BEGIN

             IF TG_OP = ''DELETE'' THEN

                  Delete from company where uid = OLD.id;

                 Delete from link where uid = OLD.id;

                 Delete from product_sort where uid = OLD.id;

                  Delete from news where uid = OLD.id;

                  Delete from count where uid = OLD.id;

                  Delete from guestbook where uid = OLD.id;

                  Delete from clientinfo where uid = OLD.id;

                  Delete from column_bar where uid = OLD.id;

                  Delete from drumbeating where uid = OLD.id;

           END IF;

           IF TG_OP = ''INSERT'' THEN

                  INSERT INTO company(uid) values(NEW.id);

                  INSERT INTO count(uid,number,fontcolor,backgroundcolor) values(NEW.id,0,''ffffff'',''000000'');

                  INSERT INTO drumbeating(uid,logourl,bannerurl) values(NEW.id,''default_logo.jpg'',''default_banner.jpg'');

           END IF;

    RETURN OLD;

      END;

' LANGUAGE 'plpgsql';

 

 

DROP TRIGGER siteuser_delete_tri on siteuser;

CREATE TRIGGER siteuser_delete_tri

       BEFORE Delete ON siteuser FOR EACH ROW

       EXECUTE PROCEDURE siteuser_tri_func ();

 

DROP TRIGGER siteuser_insert_tri on siteuser;

CREATE TRIGGER siteuser_insert_tri

       AFTER INSERT ON siteuser FOR EACH ROW

       EXECUTE PROCEDURE siteuser_tri_func ();

9.3    时间调度触发器

PostgreSQL本身关没有提供这种功能。但是我们可以用其它方式来代替同样的功能。

[root@linux pgsql]# cat function.sh

#!/bin/bash

 

psql -Uchen member -c "select add_system_log(1,'127.0.0.1','Create Database','Initialization Database');"

# or

# psql -Uchen member -f your_sql_script.sql

9.3.1   定时触发器

定时触发器与周期触发器。的不同是定时,只运行一次,而周期是有规律的运行。

l         明天的这时候运行function.sh

[root@linux8 pgsql]# at -f function.sh tomorrow

warning: commands will be executed using (in order) a) $SHELL b) login shell c) /bin/sh

job 15 at 2003-10-14 18:05

l         今晚800运行optimize.sh Shell

[root@linux8 pgsql]# at -f optimize.sh 20:00 + 1 days

warning: commands will be executed using (in order) a) $SHELL b) login shell c) /bin/sh

job 18 at 2003-10-14 20:00

4天后的凌晨100运行function.sh

[root@linux8 pgsql]# at -f function.sh + 5 days

warning: commands will be executed using (in order) a) $SHELL b) login shell c) /bin/sh

job 20 at 2003-10-18 01:00

l         查看at queue

[root@linux8 pgsql]# atq

11      2003-10-14 01:00 a root

12      2003-10-14 18:00 a root

13      2003-10-14 18:00 b root

14      2003-10-14 18:03 a root

15      2003-10-14 18:05 a root

16      2003-10-14 01:00 a root

17      2003-10-13 20:00 a root

18      2003-10-14 20:00 a root

19      2003-10-15 01:00 a root

20      2003-10-18 01:00 a root

或使用

[root@linux8 pgsql]# at -l

11      2003-10-14 01:00 a root

12      2003-10-14 18:00 a root

13      2003-10-14 18:00 b root

14      2003-10-14 18:03 a root

15      2003-10-14 18:05 a root

16      2003-10-14 01:00 a root

17      2003-10-13 20:00 a root

18      2003-10-14 20:00 a root

19      2003-10-15 01:00 a root

20      2003-10-18 01:00 a root

9.3.2   周期触发器

l         每天的凌晨300运行一次function.sh

[root@linux etc]# cat crontab

SHELL=/bin/bash

PATH=/sbin:/bin:/usr/sbin:/usr/bin

MAILTO=root

HOME=/

 

# run-parts

01 * * * * root run-parts /etc/cron.hourly

02 4 * * * root run-parts /etc/cron.daily

22 4 * * 0 root run-parts /etc/cron.weekly

42 4 1 * * root run-parts /etc/cron.monthly

0 3 * * * root /usr/local/pgsql/function.sh

 

l         每天,每两个小时运行一次function.sh

 

0 */2 * * * root /usr/local/pgsql/function.sh

 

 

l         每月1日早上零晨2点运行 function.sh

 

0 2 1 * * root /usr/local/pgsql/function.sh

 

 

l         每个月的星期一1700点运行 function.sh

 

0 17 * * mon root /usr/local/pgsql/function.sh

 

 

例子不再举了,请参考操作系统手册。

 

9.4    其它例子

例子1

Id

other

Status

1

 

False

2

 

False

3

 

False

4

 

True

需求:要求插入数据之前,将数据库中某个表的status些字段值设为false,然后再插入,使表中最后一条记录的status字段为true

这个例子可以应用在竞价拍卖的过程中。Statusfalse表示出局,为true表是领先。

每一次出价要比现有的出价高,同时使其它用户出局,自己领先。

-- ======================================================================

--  'ctoc.bid'

-- ======================================================================

/*

       bidder 买方(信用等级)

       price 出价

       quantity 需求数量

       实际获得数量

       出价时间

 

*/

DROP TABLE ctoc.bid CASCADE;

CREATE TABLE ctoc.bid(

       id Serial NOT NULL UNIQUE,

    salesroom_id integer DEFAULT '1' NOT NULL,  -- foreign key

    bidder integer  DEFAULT '1' NOT NULL,  -- foreign key

       price       numeric(8,2) DEFAULT '0.00' NOT NULL,

       quantity Integer DEFAULT '1' NOT NULL Check (quantity not in ('0')),

    created  timestamp DEFAULT current_timestamp::timestamp (0) without time zone,

    status boolean DEFAULT true,

    PRIMARY KEY (id),

    FOREIGN KEY (salesroom_id) REFERENCES ctoc.salesroom (id) ON UPDATE CASCADE ON DELETE CASCADE,

    FOREIGN KEY (bidder) REFERENCES person (uid) ON UPDATE CASCADE ON DELETE CASCADE

);

CREATE INDEX ctoc_bid_index ON ctoc.bid (salesroom_id);

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

--  ' FUNCTION  TRIGGER '

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

CREATE OR REPLACE FUNCTION ctoc_bid_tri_func () RETURNS TRIGGER AS '

    DECLARE

    BEGIN

              Update ctoc.bid set status = false where salesroom_id = NEW.salesroom_id;               

    RETURN NEW;

    END;

' LANGUAGE 'plpgsql';

 

DROP TRIGGER ctoc_bid_tri on ctoc.bid;

CREATE TRIGGER ctoc_bid_tri

       BEFORE INSERT ON ctoc.bid FOR EACH ROW

       EXECUTE PROCEDURE ctoc_bid_tri_func ();

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

--  ' Test '

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

insert into ctoc.bid(salesroom_id,bidder,price,quantity,status) values(1,8,100,1,true);

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

--  'ctoc.vbid'

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

DROP VIEW ctoc.vbid;

CREATE OR REPLACE VIEW ctoc.vbid AS

    SELECT

           b.id,

           b.salesroom_id,

           b.bidder as uid,

           p.name as bidder,

           b.price,

           b.quantity,

           CASE WHEN b.status = true THEN b.quantity::varchar ELSE '0' END as quantity1,

              to_char(b.created,'YYYY-MM-DD HH24:MI:SS') as created,

              CASE WHEN b.status = true THEN '<font color=red>领先</font>'::varchar ELSE '<font color="#3399FF">出局</font>'::varchar END as status

    FROM ctoc.bid b,ctoc.salesroom room, person p

    WHERE b.salesroom_id = room.id and b.bidder = p.uid

    order by b.salesroom_id,id DESC;

对例子1改进:

实现在竞价过程中,每一次出价要比之前的与有出价高。如果出价低于之前的最后一次出价,抛出异常ERROR:  Calling ctoc_bid_tri_func ()

 

CREATE OR REPLACE FUNCTION ctoc_bid_tri_func () RETURNS TRIGGER AS '

    DECLARE

    BEGIN

           IF NEW.price > (select max(price) from ctoc.bid where salesroom_id = NEW.salesroom_id) THEN

                     Update ctoc.bid set status = false where salesroom_id = NEW.salesroom_id;

              ELSE

--                   RAISE NOTICE ''Calling ctoc_bid_tri_func ()'';

                     RAISE EXCEPTION ''Calling ctoc_bid_tri_func ()'';

              END IF;

    RETURN NEW;

    END;

' LANGUAGE 'plpgsql';

 

DROP TRIGGER ctoc_bid_tri on ctoc.bid;

CREATE TRIGGER ctoc_bid_tri

       BEFORE INSERT ON ctoc.bid FOR EACH ROW

       EXECUTE PROCEDURE ctoc_bid_tri_func ();

测试:

netkiller=> insert into ctoc.bid(salesroom_id,bidder,price,quantity,status) values(1,8,100,1,true);

ERROR:  Calling ctoc_bid_tri_func ()

netkiller=> insert into ctoc.bid(salesroom_id,bidder,price,quantity,status) values(1,8,120,1,true);

ERROR:  Calling ctoc_bid_tri_func ()

netkiller=> insert into ctoc.bid(salesroom_id,bidder,price,quantity,status) values(1,8,140,1,true);

INSERT 49772 1

netkiller=>

 

10             游标

CREATE FUNCTION reffunc(refcursor) RETURNS refcursor AS '

BEGIN

        OPEN $1 FOR SELECT * FROM system_log;

        RETURN $1;

END;

' LANGUAGE 'plpgsql';

 

BEGIN;

SELECT reffunc('funccursor');

FETCH ALL IN funccursor;

COMMIT;

member=>

member=> BEGIN;

BEGIN

member=> SELECT reffunc('funccursor');

  reffunc

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

 funccursor

(1 row)

 

member=> FETCH ALL IN funccursor;

 id | uid |      ip      |     status      |            description             |         login_date

----+-----+--------------+-----------------+------------------------------------+----------------------------

  8 |   1 | 192.168.0.1  | eeee            | dddddddddddddddddddddddddddddddddd | 2003-09-25 14:55:19.62117

53 |   1 | 127.0.0.1    | Create Database | Initialization Database            | 2003-09-25 15:23:34.941765

 54 |   2 | 192.168.0.5  | 上线          | 密码                             | 2003-09-26 15:33:18.6732

 55 |   2 | 192.168.0.2  | 登录          | 用户admin                        | 2003-09-26 16:19:21.824283

 56 |   2 | 192.168.1.31 | 登录          | 用户admin                        | 2003-09-26 17:10:47.269064

 

10.1       游标结果集

这是一个在Java 中读取游标返回的结果集例子:

public void Cursors(){

       String sql                     = "SELECT reffunc('funccursor')";

       String sql2                    = "FETCH ALL IN funccursor";

 

       DBConnect odb = null;

       try{

              odb = new DBConnect(oDatabase);

              odb.Begin();

              odb.prepareStatement(sql);

              rs = odb.executeQuery();

              odb.prepareStatement(sql2);

             

              //odb.setString(1,user);

              rs = odb.executeQuery();

              if(rs!=null) {

                     while(rs.next()){

                            System.out.print(rs.getString(1)+"|");

                            System.out.print(rs.getString(2)+"|");

                            System.out.print(rs.getString(3)+"|");

                            System.out.println(rs.getString(4));

                     }    

              }

              odb.Commit();

       }

       catch(Exception e){

              e.printStackTrace();

       }

       finally{

              try{

                     odb.close();

              }catch(Exception e){

                     e.printStackTrace();

              }

       }

}

53|1|127.0.0.1|Create Database

54|2|192.168.0.5|上线

55|2|192.168.0.2|登录

56|2|192.168.1.31|登录

57|2|127.0.0.1|登录

58|1|127.0.0.1|登录

 

10.2       例子

例子1

CREATE FUNCTION reffunc(refcursor,integer) RETURNS refcursor AS '

BEGIN

        OPEN $1 FOR SELECT id,pname,num as amount,price,newprice,(newprice*num) as subtotal,((price-newprice)*num) as cost_saving FROM product WHERE id = $2;

        RETURN $1;

END;

' LANGUAGE 'plpgsql';

 

例子2

CREATE OR REPLACE FUNCTION btoc.porder(refcursor,Integer,Integer) RETURNS refcursor AS '

       DECLARE

               search_id ALIAS FOR $2;

               num ALIAS FOR $3;

       BEGIN

               OPEN $1 FOR

                      SELECT

                          id,name,

                  CASE WHEN money is null THEN ''RMB'' ELSE money END||to_char(price,''99G999G999D99'') as price,

                      CASE WHEN money is null THEN ''RMB'' ELSE money END||to_char(newprice,''99G999G999D99'') as newprice,

                      num as quantity,

                      newprice*num as subtotal,

                      price*num - newprice*num as cost_saving

                   FROM btoc.product

                   WHERE id = search_id;

          IF FOUND then

                   RETURN $1;

               ELSE

                   RETURN null;

               END IF; 

      END;

' LANGUAGE 'plpgsql';

 

BEGIN;

select btoc.porder('funccursor',75,500);

FETCH ALL IN funccursor;

-- CLOSE funccursor;

-- select porder('funccursor',16,5);

-- FETCH ALL IN funccursor;

COMMIT;

11             事务处理

11.1       批量插入、更新、删除

对数据进行批量的插入、更新、删除操作,建议使用事务处理。

1.         降低对物理磁盘的读写操作,提高性能

2.         保持数据完整、一至

请看下面的例子

11.1.1 批量插入操作-1

insert into "group"(groupname,description) values('System Admin','系统管理员');

insert into "group"(groupname,description) values('Power Admin','系统管理员');

insert into "group"(groupname,description) values('Backup Admin','系统管理员');

……  ……

……  ……

……  ……

insert into "group"(groupname,description) values('xxxxxxxxxxxx','xxxxxxxxxxx');

 

这个例子要完成大量的数据插入操作。在程序在实现这个操作,基本都是使用一个循环操作如:

for(条件){

       运行SQL语句:insert into "group"(groupname,description) values('变量','变量');

}

如果插入数据足够多,你会发现你的磁盘在嚓嚓做响,并且硬盘指示灯疯狂闪烁。

优化后更改为:

begin

for(条件){

       运行SQL语句:insert into "group"(groupname,description) values('变量','变量');

}

commit

 

插入数据被保存到内存中,只有commit时你的磁盘才会嚓嚓响。除非你的存内不够用,系统使用交换分区。当前主流的服务器配置基本都是1G-2G内存再加4G交换分区,一次插入几千行的事务小CASE

 

这里给一个Java的例子:

       public void delGroupMember(ArrayList id) {

              String sql = "delete from groupmember where id=?";

              try{

                     odb = new DBConnect(oDatabase);

                     odb.Begin();

                  for(int i=0;i<id.size();i++){

                            odb.prepareStatement(sql);

                         odb.setString(1,(String)id.get(i));

                            odb.executeUpdate();

                     }

                     odb.Commit();

                     odb.AutoCommit();

              }

              catch(Exception e){

                     odb.Rollback();

                     e.printStackTrace();

              }

              finally{

                     try{

                            odb.close();

                     }catch(Exception e){

                            e.printStackTrace();

                     }

              }

       }

11.2       保持数据完整-2

当删除A表中一条记录,同时删除BCDEF……等表中的相关数据,当然你可以使用RULETRIGGER来完成,我这是只是举个例子。

由程序完成这样的删除作操,如果不使用事务处理,中途中断操作数据就会不一至。

 

Begin;

           Delete from company where uid = id;

          Delete from link where uid = id;

          Delete from product_sort where uid = id;

           Delete from news where uid = id;

           Delete from count where uid = id;

           Delete from guestbook where uid = id;

           Delete from clientinfo where uid = id;

           Delete from column_bar where uid = id;

           Delete from drumbeating where uid = id;

       Commit;

 

12             用户权限

需求例子

某公司经营虚拟主机,数据库等业务,需求如下

 

1.         每个虚拟主机用户对应一个数据(PostgreSQL)。

2.         数据库与数据库用户之间独立,互不干扰。

3.         有一些用户虚拟主机在其它公司,要买我们的PostgreSQL数据库服务。

4.         用户分为企业,个人。

5.         每户有时限,过期后自动失效(停用)。

 

分析:

1.         每个主机对应一个数据库,并且用户之间独立,我们可以配置pg_hba.conf文件来完成需求(1),(2),(3)。

2.         创建企业组和个人组来实现需求中的(4

3.         过期策略,使用VALID UNTIL选项来完成

建议:

       数据库与用户名命名规则,建议你使用该用户虚拟主机的域名。如:

       www.9812.net 数据库为:9812_net 用户名为:9812_net

       数据库名使用“_”下划线需要使用双引号"9812_net", "xuser_net"

       如果不想使用双引号,给用户添麻烦。也可以命名为:

       9812netxusernetkdeopencom

       或不用后缀直接

       9812xuserkdeopen

12.1.1

12.1.1.1       创建组

CREATE GROUP groupname;

 

要向组中增加用户或删除用户:

ALTER GROUP groupname ADD USER user1, user2... ;

ALTER GROUP groupname DROP USER user1, user2... ;

 

postgres=# CREATE GROUP company;

CREATE GROUP

postgres=# CREATE GROUP person;

CREATE GROUP

postgres=#

 

12.1.1.2       删除组

DROP GROUP groupname;

postgres=# DROP GROUP vhost;

DROP GROUP

 

12.1.2 用户

12.1.2.1       创建用户

1.         创建一个名为netkiller的用户,指定密码chen

CREATE USER netkiller WITH PASSWORD 'chen';

2.         创建一个用户:dbuser1,密码:chen,用户在2003-12-1过期。

CREATE USER dbuser1 WITH PASSWORD 'chen' VALID UNTIL '2003-12-1';

postgres=# CREATE USER dbuser1 WITH PASSWORD 'chen' VALID UNTIL '2003-12-1';

CREATE USER

postgres=# CREATE USER "kdeopen_comt" WITH PASSWORD 'chen' VALID UNTIL '2003-12-30';

CREATE USER

postgres=# CREATE USER "9812_net" WITH PASSWORD 'chen' VALID UNTIL '2004-2-1';

CREATE USER

 

3.         创建用户一个隶属于vhost组的用户。

CREATE USER vhostdbuser WITH PASSWORD 'chen' IN GROUP vhost;

postgres=# CREATE GROUP vhost;

CREATE GROUP

postgres=# CREATE USER vhostdbuser WITH PASSWORD 'chen' IN GROUP vhost;

CREATE USER

postgres=# CREATE USER vhostdbuser1 WITH PASSWORD 'chen' VALID UNTIL '2003-12-1' IN GROUP vhost;

CREATE USER

postgres=#

postgres=# \du

               List of database users

  User name   | User ID |         Attributes

--------------+---------+----------------------------

 9812_net     |     102 |

 dbuser1      |     101 |

 kdeopen_com |     103 |

 netkiller    |     100 |

 postgres     |       1 | superuser, create database

 vhostdbuser  |     104 |

 vhostdbuser1 |     105 |

(7 rows)

 

postgres=#

12.1.2.2       删除用户

DROP USER username;

postgres=# DROP USER dbuser1;

DROP USER

postgres=#

12.1.2.3       修改密码

ALTER USER "用户" PASSWORD  '密码';

postgres=# ALTER USER "9812_net" PASSWORD  '123456';

ALTER USER

postgres=#

 

测试:

bash-2.05b$ psql -h 127.0.0.1 -U9812

Password: 输入新密码

psql: FATAL:  Password authentication failed for user "9812"

 

bash-2.05b$ psql -h 127.0.0.1 -U9812_net

Password:

Welcome to psql 7.3.4, the PostgreSQL interactive terminal.

 

Type:  \copyright for distribution terms

       \h for help with SQL commands

       \? for help on internal slash commands

       \g or terminate with semicolon to execute query

       \q to quit

 

9812_net=>

12.1.3 创建数据

创建数据库,并指定所有者:

CREATE DATABASE kdeopen WITH OWNER = 9812_net TEMPLATE = template0 ENCODING = 'UNICODE';

postgres=# CREATE DATABASE "9812_net" WITH OWNER = "9812_net" TEMPLATE = template0 ENCODING = 'UNICODE';

CREATE DATABASE

postgres=# \l

         List of databases

   Name    |   Owner   | Encoding

-----------+-----------+-----------

 9812_net  | 9812_net  | UNICODE

 netkiller | netkiller | UNICODE

 postgres  | postgres  | SQL_ASCII

 template0 | postgres  | SQL_ASCII

 template1 | postgres  | SQL_ASCII

(5 rows)

 

postgres=#

12.1.4 用户认证

12.1.4.1       本地连接

# local    DATABASE  USER  METHOD  [OPTION]

# host     DATABASE  USER  IP-ADDRESS  IP-MASK  METHOD  [OPTION]

# hostssl  DATABASE  USER  IP-ADDRESS  IP-MASK  METHOD  [OPTION]

 

pg_hba.conf文件配置例子

[root@linux data]# cat pg_hba.conf

host    all         all         127.0.0.1         255.255.255.255   md5

local   all         all                                          trust

测试,从127.0.0.1连接成功

[root@linux data]# psql -h127.0.0.1 -u member

psql: Warning: The -u option is deprecated. Use -U.

User name: chen

Password:

Welcome to psql 7.3.3, the PostgreSQL interactive terminal.

 

Type:  \copyright for distribution terms

       \h for help with SQL commands

       \? for help on internal slash commands

       \g or terminate with semicolon to execute query

       \q to quit

 

member=>

从外地测试,从LAN连接失败

[root@linux data]# psql -hwww.9812.net -u member

psql: Warning: The -u option is deprecated. Use -U.

User name: chen

Password:

psql: FATAL:  No pg_hba.conf entry for host 61.145.139.113, user chen, database member

 

[root@linux2 data]#

 

注意:是本地连接也要加-h 127.0.0.1。否则系统认为你用UNIX Domain Socket 连接     /tmp/ .s.PGSQL.5432

12.1.4.2       允许任何IP连接主机

[root@linux data]# cat pg_hba.conf

host    all         all         0.0.0.0           0.0.0.0           md5

12.1.5 脚本例子

9812是本地用户(应用程序和数据库在同一台服务器上)

kdeopen 是外部用户来自202.103.190.130

xuser 是动态IP拔号用户,可以在任何地方连接他的xuser数据库

 

pg_hba.conf

[root@linux data]# cat pg_hba.conf

host    9812          9812          127.0.0.1         255.255.255.255   md5

host    kdeopen       kdeopen        202.103.190.130   255.255.255.0     md5

host    xuser          xuser          0.0.0.0           0.0.0.0           md5

 

SQL脚本:

CREATE GROUP company;

CREATE GROUP person;

CREATE USER 9812 WITH PASSWORD 'chen' VALID UNTIL '2003-12-1' IN GROUP person;

CREATE DATABASE 9812 WITH OWNER = 9812 TEMPLATE = template0 ENCODING = 'UNICODE';

CREATE USER kdeopen WITH PASSWORD 'chen' VALID UNTIL '2003-12-1' IN GROUP company;

CREATE DATABASE kdeopen WITH OWNER = kdeopen TEMPLATE = template0 ENCODING = 'UNICODE';

CREATE USER xuser WITH PASSWORD 'chen' VALID UNTIL '2003-12-1' IN GROUP person;

CREATE DATABASE xuser WITH OWNER = xuser TEMPLATE = template0 ENCODING = 'UNICODE';

12.1.6 权限

过几天写

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

13             其它技巧例子

字符串替换

update crm.customer set details = replace(details,'客户',' customer') where id >20;

 

第二章 开发篇

13.1       汉字编码问题

传统汉字编码是由两个字节组成(HzHzk 国标GB2312,GBK)的,最新版是GB18030兼容(GB2312GBK 2字节),其余的字符是4字节。其它一些过度标准还有GB 2311GB 11383GB 12345GB 13000.1GB17000

采用UTF-8编码会多占用一些空间(英文1个字节,一个汉字等其它字符需3个字节),但解决了国际化问题,UTF-8兼容GB2312BIG5EUC_CNEUC_TWGB18030等多种国家的语言编码。

解决了国际化字符问题条件是创建数据库的编码必须是UNICODEUNICODE中英文一个字母=中文一个汉字长度。

控制台(显示/输出) UTF-8 参考FAQ Putty

 

13.2       JDBC

要解决Java 中的中文问题,首先字符源就应该是UTF-8编码,如将“汉字”转成UTF-8编码,通过JDBC 插入到UNICODE编码的数据库中。这样才不会出乱码“????”,“”。我在BBS上看到很多朋友问汉字编码问题。他们没成功的的原因是他们这样组合。

ISO8859-1(汉字) à JDBC à Database (UNICODE)

ISO8859-1(汉字) à JDBC à Database (EUC_CN)

GB2312(汉字) à JDBC à Database (SQL_ASCII)

 

    正确应该是:

UTF-8(汉字) à JDBC (UTF-8) à Database (Unicode)

如果你使用psql查看记录。你的控制台也要支持UTF-8。否则你看到的还是乱码。

13.2.1 Jsp/Java

13.2.2 toChinese() 方法

我常在BBS上看到很多用户提问,Jsp/Java 读出表单、数据库中的汉字显示为“??????????”,多数用户都是使用类似下面的方法:

 

       public static String toChinese(String strvalue){

           try{

            if(strvalue==null)

               return null;

            else{

               strvalue = new String(strvalue.getBytes("ISO8859_1"), "GBK");

               return strvalue;

               }

        }catch(Exception e){

              return null;

        }

     }

13.2.3 Unicode (UTF-8) 完全解决方案

笔者不赞成使用这种方法,因为无论GBK,还是GB2312只限于英文字母、汉字存储。我推荐使用Unicode(UTF-8) 编码,可以存储任何数据。创建数据库编码采用EUC_CNUnicode编码都可以(建议使用Unicode)。Jsp页面中要加入下面几行代码。加入代码之后不需要对字符(包括汉字)做认任转换处理。全部采用UTF-8编码存储数据。

13.2.3.1       setCharacterEncoding() 方案

<%@ page contentType="text/html; charset=gb2312" language="java" import="java.sql.*" errorPage="error.jsp" %>

<html>

<head>

<title>Untitled Document</title>

<meta http-equiv="Content-Type" content="text/html; charset= gb2312">

<link href="../includes/style.css" rel="stylesheet" type="text/css">

</head>

 

改为

 

<%@ page contentType="text/html; charset=utf-8" language="java" import="java.sql.*" errorPage="" %>

<jsp:include page="../includes/unicode.jsp" flush="true" />

<%@ page import="java.util.*"%>

<jsp:useBean id="sd" scope="page" class="ebusiness.btob.supplydemand"/>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<title>Untitled Document</title>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

<link href="../includes/style.css" rel="stylesheet" type="text/css">

</head>

<%

       String CharacterEncoding = "UTF-8";

       response.setContentType("text/html;charset=UTF-8");

       request.setCharacterEncoding(CharacterEncoding);

%>

 

String CharacterEncoding = "UTF-8";

request.setCharacterEncoding(CharacterEncoding);

设置提交出去的数据就是utf-8的..

 

创建数据库:

bash-2.05b$ createdb -E Unicode mydatabase

CREATE DATABASE

bash-2.05b$ psql -l

         List of databases

    Name    |  Owner   | Encoding

------------+----------+-----------

 member     | postgres | SQL_ASCII

 mydatabase | postgres | UNICODE

 postgres   | postgres | SQL_ASCII

 pureftpd   | pureftpd | EUC_CN

 site       | postgres | EUC_CN

 template0  | postgres | SQL_ASCII

 template1  | postgres | SQL_ASCII

(7 rows)

 

bash-2.05b$

或参考“用户权限”中的“脚本例子”小节。

CREATE GROUP person;

CREATE USER xuser WITH PASSWORD 'chen' VALID UNTIL '2003-12-1' IN GROUP person;

CREATE DATABASE xuser WITH OWNER = xuser TEMPLATE = template0 ENCODING = 'UNICODE';

 

Inc.jsp

<%

       response.addHeader("Expires","-1");

       response.addHeader("Pragma", "no-cache");

       response.addHeader("cache-control", "no-store");

      

       String CharacterEncoding = "UTF-8";

       response.setContentType("text/html;charset=UTF-8");

       request.setCharacterEncoding(CharacterEncoding);

%>

 

jsp页面文件:

<%@ page contentType="text/html; charset=utf-8" language="java" import="java.sql.*" errorPage="error.jsp" %>

<%@ page import="java.util.*"%>

<%@ page import="net.xuser.util.*"%>

<%@ include file="include/inc.jsp" %>

<jsp:include page="include/privileges.jsp" flush="true" />

<jsp:useBean id="oGroup" scope="page" class="netkiller.member.group" />

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset= utf-8">

<title> </title>

<link href="include/style.css" rel="stylesheet" type="text/css">

</head>

 

<body>

 

</body>

</html>

上面的方法在跨页面提交时有问题,汉字还是出乱码。但提交给自身是没有问题的。

 

13.2.3.2       Web.xml Filter过滤方案:

SetCharacterEncodingFilter.java

/*

 * $Header: /home/cvs/jakarta-tomcat-4.0/webapps/examples/WEB-INF/classes/filters/SetCharacterEncodingFilter.java,v 1.1.2.1 2001/10/17 22:52:17 craigmcc Exp $

 * $Revision: 1.1.2.1 $

 * $Date: 2001/10/17 22:52:17 $

 *

 * ====================================================================

 *

 * The Apache Software License, Version 1.1

 *

 * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights

 * reserved.

 *

 * Redistribution and use in source and binary forms, with or without

 * modification, are permitted provided that the following conditions

 * are met:

 *

 * 1. Redistributions of source code must retain the above copyright

 *    notice, this list of conditions and the following disclaimer.

 *

 * 2. Redistributions in binary form must reproduce the above copyright

 *    notice, this list of conditions and the following disclaimer in

 *    the documentation and/or other materials provided with the

 *    distribution.

 *

 * 3. The end-user documentation included with the redistribution, if

 *    any, must include the following acknowlegement:

 *       "This product includes software developed by the

 *        Apache Software Foundation (http://www.apache.org/)."

 *    Alternately, this acknowlegement may appear in the software itself,

 *    if and wherever such third-party acknowlegements normally appear.

 *

 * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software

 *    Foundation" must not be used to endorse or promote products derived

 *    from this software without prior written permission. For written

 *    permission, please contact apache@apache.org.

 *

 * 5. Products derived from this software may not be called "Apache"

 *    nor may "Apache" appear in their names without prior written

 *    permission of the Apache Group.

 *

 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED

 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE

 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR

 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF

 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND

 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,

 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT

 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF

 * SUCH DAMAGE.

 * ====================================================================

 *

 * This software consists of voluntary contributions made by many

 * individuals on behalf of the Apache Software Foundation.  For more

 * information on the Apache Software Foundation, please see

 * <http://www.apache.org/>.

 *

 * [Additional notices, if required by prior licensing conditions]

 *

 */

 

 

package filters;

 

 

import java.io.IOException;

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.UnavailableException;

 

 

/**

 * <p>Example filter that sets the character encoding to be used in parsing the

 * incoming request, either unconditionally or only if the client did not

 * specify a character encoding.  Configuration of this filter is based on

 * the following initialization parameters:</p>

 * <ul>

 * <li><strong>encoding</strong> - The character encoding to be configured

 *     for this request, either conditionally or unconditionally based on

 *     the <code>ignore</code> initialization parameter.  This parameter

 *     is required, so there is no default.</li>

 * <li><strong>ignore</strong> - If set to "true", any character encoding

 *     specified by the client is ignored, and the value returned by the

 *     <code>selectEncoding()</code> method is set.  If set to "false,

 *     <code>selectEncoding()</code> is called <strong>only</strong> if the

 *     client has not already specified an encoding.  By default, this

 *     parameter is set to "true".</li>

 * </ul>

 *

 * <p>Although this filter can be used unchanged, it is also easy to

 * subclass it and make the <code>selectEncoding()</code> method more

 * intelligent about what encoding to choose, based on characteristics of

 * the incoming request (such as the values of the <code>Accept-Language</code>

 * and <code>User-Agent</code> headers, or a value stashed in the current

 * user's session.</p>

 *

 * @author Craig McClanahan

 * @version $Revision: 1.1.2.1 $ $Date: 2001/10/17 22:52:17 $

 */

 

public class SetCharacterEncodingFilter implements Filter {

 

 

    // ----------------------------------------------------- Instance Variables

 

 

    /**

     * The default character encoding to set for requests that pass through

     * this filter.

     */

    protected String encoding = null;

 

 

    /**

     * The filter configuration object we are associated with.  If this value

     * is null, this filter instance is not currently configured.

     */

    protected FilterConfig filterConfig = null;

 

 

    /**

     * Should a character encoding specified by the client be ignored?

     */

    protected boolean ignore = true;

 

 

    // --------------------------------------------------------- Public Methods

 

 

    /**

     * Take this filter out of service.

     */

    public void destroy() {

 

        this.encoding = null;

        this.filterConfig = null;

 

    }

 

 

    /**

     * Select and set (if specified) the character encoding to be used to

     * interpret request parameters for this request.

     *

     * @param request The servlet request we are processing

     * @param result The servlet response we are creating

     * @param chain The filter chain we are processing

     *

     * @exception IOException if an input/output error occurs

     * @exception ServletException if a servlet error occurs

     */

    public void doFilter(ServletRequest request, ServletResponse response,

                         FilterChain chain)

       throws IOException, ServletException {

 

        // Conditionally select and set the character encoding to be used

        if (ignore || (request.getCharacterEncoding() == null)) {

            String encoding = selectEncoding(request);

            if (encoding != null)

                request.setCharacterEncoding(encoding);

        }

 

       // Pass control on to the next filter

        chain.doFilter(request, response);

 

    }

 

 

    /**

     * Place this filter into service.

     *

     * @param filterConfig The filter configuration object

     */

    public void init(FilterConfig filterConfig) throws ServletException {

 

       this.filterConfig = filterConfig;

        this.encoding = filterConfig.getInitParameter("encoding");

        String value = filterConfig.getInitParameter("ignore");

        if (value == null)

            this.ignore = true;

        else if (value.equalsIgnoreCase("true"))

            this.ignore = true;

        else if (value.equalsIgnoreCase("yes"))

            this.ignore = true;

        else

            this.ignore = false;

 

    }

 

 

    // ------------------------------------------------------ Protected Methods

 

 

    /**

     * Select an appropriate character encoding to be used, based on the

     * characteristics of the current request and/or filter initialization

     * parameters.  If no character encoding should be set, return

     * <code>null</code>.

     * <p>

     * The default implementation unconditionally returns the value configured

     * by the <strong>encoding</strong> initialization parameter for this

     * filter.

     *

     * @param request The servlet request we are processing

     */

    protected String selectEncoding(ServletRequest request) {

 

        return (this.encoding);

 

    }

 

 

}

编译该文件

filters(目录)复制到WEB-INF/classes目录下。

编辑WEB-INF下的web.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">

 

<web-app>

 

<welcome-file-list>

<welcome-file>index.jsp</welcome-file>

</welcome-file-list>

 

<filter>

<filter-name>Set Character Encoding</filter-name>

<filter-class>filters.SetCharacterEncodingFilter</filter-class>

<init-param>

<param-name>encoding</param-name>

<param-value>utf-8</param-value>

</init-param>

<init-param>

<param-name>ignore</param-name>

<param-value>true</param-value>

</init-param>

</filter>

 

<filter-mapping>

<filter-name>Set Character Encoding</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

 

</web-app>

 

汉字编码的解决方案完成。

 

13.2.3.3       Jdbc url charSet方案

jdbc:postgresql://localhost:5432/database?charSet=UTF-8

 

13.3       Tomcat JNDI Datasource 配置

首先下载PostgreSQL JDBC http://jdbc.postgresql.org/

然后将.jar文件复制到/usr/local/jakarta-tomcat/common/lib/目录中

创建一个xml文件参考webapps.xml将文件复制到/usr/local/jakarta-tomcat/ conf/Catalina/localhost/目录下Tomcat 4.x jakarta-tomcat /webapps目录5.x jakarta-tomcat/conf/Catalina/localhost/

 

webapps.xml

[root@linux root]# cat /usr/local/jakarta-tomcat/webapps/webapps.xml

<Context path="/test" docBase="/var/www/html/webapps" debug="0" reloadable="true">

 

  <Logger className="org.apache.catalina.logger.FileLogger"

             prefix="localhost_webapps_log." suffix=".txt"

             timestamp="true"/>

 

  <Resource name="jdbc/postgrespool" auth="Container" type="javax.sql.DataSource"/>

  <ResourceParams name="jdbc/postgrespool">

    <parameter>

      <name>factory</name>

      <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>

    </parameter>

    <parameter>

      <name>driverClassName</name>

      <value>org.postgresql.Driver</value>

    </parameter>

    <parameter>

      <name>url</name>

      <value>jdbc:postgresql://127.0.0.1:5432/netkiller</value>

    </parameter>

    <parameter>

      <name>username</name>

      <value>netkiller</value>

    </parameter>

    <parameter>

      <name>password</name>

      <value>chen</value>

    </parameter>

    <parameter>

      <name>maxActive</name>

      <value>10</value>

    </parameter>

    <parameter>

      <name>maxIdle</name>

      <value>10</value>

    </parameter>

    <parameter>

      <name>maxWait</name>

      <value>-1</value>

    </parameter>

  </ResourceParams>

</Context>

 

DriverClassName 驱动的ClassName

url 数据库的URL  jdbc:postgresql://主机:端口/数据库

username 数据用户名

password 密码

maxActive 最大连接数

maxIdle 空闲连接

maxWait 超时时间

 

web.xml

[root@linux root]# cat /var/www/html/webapps/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">

 

<web-app>

 

        <welcome-file-list>

            <welcome-file>index.jsp</welcome-file>

        </welcome-file-list>

 

        <filter>

            <filter-name>Set Character Encoding</filter-name>

            <filter-class>filters.SetCharacterEncodingFilter</filter-class>

            <init-param>

                <param-name>encoding</param-name>

                <param-value>utf-8</param-value>

            </init-param>

                <init-param>

                        <param-name>ignore</param-name>

                        <param-value>true</param-value>

                </init-param>

        </filter>

 

        <filter-mapping>

                <filter-name>Set Character Encoding</filter-name>

                <url-pattern>/*</url-pattern>

        </filter-mapping>

 

<description>Postgresql Test App</description>

<resource-ref>

  <description>DB Connection</description>

  <res-ref-name>jdbc/postgrespool</res-ref-name>

  <res-type>javax.sql.DataSource</res-type>

  <res-auth>Container</res-auth>

</resource-ref>

 

<servlet>

        <servlet-name>DisplayChart</servlet-name>

        <servlet-class>org.jfree.chart.servlet.DisplayChart</servlet-class>

</servlet>

 

</web-app>

 

测试程序

db-connect-test.jsp

 

<%@ page contentType="text/html; charset=GBK"%>

<%@ page import="java.sql.*,

 

    javax.naming.*"%>

<%

try {

    Context initCtx = new InitialContext();

    Context ctx = (Context) initCtx.lookup("java:comp/env");

    Object obj = (Object) ctx.lookup("jdbc/postgrespool");

    javax.sql.DataSource ds = (javax.sql.DataSource)obj;

    Connection conn = ds.getConnection();

    Statement stmt = conn.createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE,

        java.sql.ResultSet.CONCUR_READ_ONLY);

    String strSQL = "SELECT * FROM users";

    ResultSet rs = stmt.executeQuery(strSQL);

%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"

"http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<title>PostgreSQL Test</title>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

</head>

 

<body>

<%

       while(rs.next()){

              out.print(rs.getString(2)+"<br>");

       }

%>

</body>

</html>

<%       

    rs.close();

    stmt.close();

    conn.close();

} catch (Exception e) {

    e.printStackTrace();

    throw e;

}

%>

 

 

测试URL

http://192.168.0.1:8080/test/db-connect-test.jsp

 

13.4       JDBC通过SSL安全连接数据库

java.sql.DriverManager.getConnection("jdbc:postgresql://db.example.com/testdb?ssl","netkiller","password")

13.5       开发相关

13.5.1 Create Java Entity Bean (not EJB CMP)

http://home.9812.net/linux/article/postgres/python/

 

这是我写的一个小程序。可以将PostgreSQL 数据库中的表。导出为javabean

13.5.2 连接数据库

package netkiller.database;

 

/**

* Title  PostgreSQL database JDBC interface.

* @author: netkiller (陈景峰)

* Company:   none

* Homepage:   http://netkiller.8800.org

* Copyright: Copyright (c) 2003

* @version 1.0

* @since

* @PostgreSQL database JDBC interface.

* @see 2003-3-19

*/

 

import java.sql.*;

import java.util.*;

import java.io.*;

import javax.sql.*;

import org.postgresql.jdbc3.*;

 

//import net.xuser.database.DBConnectionManager;

//implements Database

public class DBConnect{

      

       private     Connection conn           = null;

       private     Statement stmt              = null;

       private PreparedStatement prepstmt = null;

       private     ResultSet rs           = null;

       private DBConnectionManager dcm=null;

      

       private     String Driver          = null;

       private     String url               = null;

       private     String user                    = null;

       private     String passwd        = null;

       private boolean isConnect      = false;

      

       private String odbc               = null;

 

    private void init(String odb) {

              try{

               dcm = DBConnectionManager.getInstance(odb);

               //System.out.println(dcm);

                     if(dcm == null){

                            //this.conn == null ||

                            System.out.println("Database Connect false!");

                            //throw new Exception("Database Connect false!");

                            //return;

                     }else{

                            this.conn = dcm.getConnection();

                     }

                    

              }

              catch (Exception e)       {

                     e.printStackTrace();

              }        

    }    

       public DBConnect() {

              init("jdbc");

              this.odbc = "jdbc";

       }    

       public DBConnect(String odb) {

 

              this.Driver             = "org.postgresql.Driver";

              //this.url         = "jdbc:postgresql://localhost:5432/site";

              this.user         = "netkiller";

              this.passwd           = "chen";

              //this.setUrl("localhost","site");

              this.setUrl("192.168.0.1","netkiller");

 

              //System.out.print("Database Connection:"+getConnection());

             

              if(odb == null)odb="jdbc";

              this.odbc = odb;

              init(odb);

/*

InitialContext ctx = new InitialContext();

DataSource ds = (DataSource) ctx.lookup("java:/MSSQLDS");

Connection conn = ds.getConnection();

Statement stmt = conn.createStatement();

ResultSet rs = stmt.executeQuery("SELECT * FROM Employees");

while ( rs.next() ) {

out.println( rs.getInt(“EmployeeID”) + "<br>");

}

conn.close();

*/          

       }

      

       public void setDriver(String dri){

              this.Driver             = dri;

       }

      

       public void setUrl(String db){

              this.url           = "jdbc:postgresql://localhost:5432/"+db;

       }

      

       public void setUrl(String host,String db){

              this.url           = "jdbc:postgresql://"+ host +":5432/"+db;

       }

      

       public void setUrl(String host,int port,String db){

              this.url           = "jdbc:postgresql://"+ host +":"+ port +"/"+db;

       }

      

       public void setUser(String user){

              this.user         = user;

       }

      

       public void setPasswd(String pass){

              this.passwd           = pass;

       }

      

       public void setHost(){}

       public void setPort(){}

      

       public String getUrl(){

              return this.url;

       }

      

       public String getDriver(){

              return this.Driver;

       }

      

       public String getUser(){

              return this.user;

       }

 

       public String getPasswd(){

              return this.passwd;

       }

 

       public Connection Connection(){

              this.isConnect = false;

              try{

                     Class.forName(this.getDriver()).newInstance();

                     this.conn = DriverManager.getConnection(this.getUrl(), this.getUser(), this.getPasswd());

                     isConnect = true;   

              }

              catch (Exception e)       {

                     e.printStackTrace();

              }

              return this.conn;

       }

 

       public boolean getConnection(){

             

              this.Connection();

              if(this.isConnect){

                     return this.isConnect;

              }else{

                     System.out.println("数据库连接有问题,请检查主机,用户,密码!");

                     return this.isConnect;

              }

       }

 

       public String getCatalog(){

              String tmp = "";

              try{

                     if(this.conn != null)

                     tmp = this.conn.getCatalog();

              }catch(SQLException e) {

                     e.printStackTrace();

              }

              return tmp;

       }

 

       public void AutoCommit(){

              try{

                     this.conn.setAutoCommit(true);

              }catch(SQLException e) {

                     e.printStackTrace();

              }

       }

      

       public void Begin(){

              try{

                     this.conn.setAutoCommit(false);  

              }catch(SQLException e) {

                     e.printStackTrace();

              }

       }

      

       public void Commit(){

              try{

                     if(this.conn != null)

                     this.conn.commit();      

              }catch(SQLException e) {

                     e.printStackTrace();

              }                  

       }

      

       public void Rollback(){

              try{

                     if(this.conn != null)

                     this.conn.rollback();

              }catch(SQLException e) {

                     e.printStackTrace();

              }                  

       }

      

       public ResultSet executeQuery(String strSQL) {

 

              try {

                     this.stmt = this.conn.createStatement();

                     if(this.stmt != null){

                            this.rs = this.stmt.executeQuery(strSQL);

                     }

              } catch(SQLException e) {

                     e.printStackTrace();

              }

              /*

              finally      {

                     try{

                            // Always close properly

                            this.close();

                     }catch(Exception e){

                            e.printStackTrace();

                     }

              }*/

              return this.rs;

       }    

      

       public int getCount(String strTable){

 

              String strSQL        = "select count(*) from "+strTable;

              int   nCount           = 0;

             

              try {

                     this.stmt = this.conn.createStatement();

                     if(this.stmt != null){

                            this.rs = stmt.executeQuery(strSQL);

                     if(rs!=null) {

                            while(rs.next()){

                                   nCount = rs.getInt(1);

                            }

                     }

                     }

              }                  

              catch(SQLException e) {

                     e.printStackTrace();

              }

             

              finally      {

                     try{

                            // Always close properly

                            this.close();

                     }catch(Exception e){

                            e.printStackTrace();

                     }

              }

             

              return nCount;

       }

      

       public boolean executeUpdate(String strSQL){

              boolean isSuccess = false;

              try{

                     this.stmt = this.conn.createStatement();

                     //stmt = this.conn.createStatement();

                     stmt.executeUpdate(strSQL);

                     isSuccess       = true;

              }catch(SQLException e)       {

                     e.printStackTrace();

              }

              /*

              finally      {

                     try{

                            // Always close properly

                            this.close();   

                     }catch(Exception e){

                            e.printStackTrace();

                     }

              }*/  

              return isSuccess;

       }

      

       public void setString(int index,String value) throws SQLException {

              prepstmt.setString(index, value);

       }

      

       public void setInt(int index,int value) throws SQLException {

              prepstmt.setInt(index,value);

       }

      

       public void setBoolean(int index,boolean value) throws SQLException {

              prepstmt.setBoolean(index,value);

       }

      

       public void setDate(int index,java.sql.Date value) throws SQLException {

              prepstmt.setDate(index,value);

       }

      

       public void setLong(int index,long value) throws SQLException {

              prepstmt.setLong(index,value);

       }

      

       public void setFloat(int index,float value) throws SQLException {

              prepstmt.setFloat(index,value);

       }

      

       public void setBytes(int index,byte[] value) throws SQLException{

              prepstmt.setBytes(index,value);

       }

      

       public void addBatch() throws SQLException{

              prepstmt.addBatch();

       }

             

      

       public void prepareStatement(String sql) throws SQLException {

              if(this.conn != null)

              this.prepstmt = this.conn.prepareStatement(sql);

       }

      

       public void prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {

              this.prepstmt = this.conn.prepareStatement(sql, resultSetType, resultSetConcurrency);

       }

      

       public ResultSet executeQuery() throws SQLException {

              if (prepstmt != null) {

                     return prepstmt.executeQuery();

              }

              else return null;

       }    

      

       public int executeUpdate() throws SQLException {

              int count = 0;

              if (this.prepstmt != null)

                     count = this.prepstmt.executeUpdate();

       //     System.out.println(count);

              return count;

       }

 

       public int[] executeBatch() throws SQLException {

              int count[] = null;

              if (this.prepstmt != null)

                     count = this.prepstmt.executeBatch();

              return count;

       }

      

       public void clearParameters()throws SQLException

    {

        prepstmt.clearParameters();

              prepstmt=null;

    }

      

       public PreparedStatement getPreparedStatement() {

              return prepstmt;

       }

      

       public Statement getStatement() {

              return stmt;

       }    

             

       public boolean prepareCall(String process){ //throws Exception

              boolean isSuccess = false;

              //String procedure = "{call p_test2 (?) }";

              //String procedure = "{call "+process+" }";

              String procedure    = "{select "+process+"}";

             

              System.out.print(procedure);

              try{

                    

                  CallableStatement cstmt = this.conn.prepareCall(procedure);

                  cstmt.setString(1,"dddddd");

                  cstmt.setString(2,"ffffff");

                  cstmt.executeUpdate(); 

                                   

                  //rs = cstmt.executeQuery();

                  isSuccess       = true;

                 

              }catch(SQLException e)       {

                     e.printStackTrace();

              }    

              return isSuccess;

       }

      

       public boolean Transaction(String sql){ //throws Exception

              boolean isSuccess = false;

              try{

                     this.prepstmt = this.conn.prepareStatement(sql);

              }catch(SQLException e){

                     e.printStackTrace();

              }

/*          

              connection.beginTransaction();

              try{

                     connection.commit();              

              }catch(SQLException e)       {

                     connection.rollback();

                     e.printStackTrace();

              }    

*/          

              return isSuccess;

       }

 

       public void close() throws Exception{

              //System.out.println(this.conn.getCatalog());

              //System.out.println(prepstmt.EXECUTE_FAILED);

              if (this.rs != null)  {

                     this.rs.close();

                     this.rs     = null;

              }

              if (this.stmt != null) {

                     this.stmt.close();

                     this.stmt = null;

              }

              if (this.prepstmt != null) {

                     this.prepstmt.close();

                     this.prepstmt = null;

              }

              if (conn!=null)

              {

                    

                     //this.conn.close();

                     dcm.freeConnection(conn);

                     //dcm.freeConnection("PostgreSQL",conn);

                     dcm.release();

                     //this.conn      = null;    

              }

              //System.out.println(new java.util.Date() +": Database Connection close :"+this.conn+ "|"+this.conn.isClosed());

       }

 

       public static void main(String args[]) {

              System.out.println("Starting DBConnect...");

              //DBConnect pg = new DBConnect();

              Connection conn           = null;

              Statement stmt              = null;

        PreparedStatement prepstmt = null;

              try{

                     Jdbc3PoolingDataSource source = new Jdbc3PoolingDataSource();

                     source.setDataSourceName("A Data Source");

                     source.setServerName("192.168.0.1");

                     source.setDatabaseName("netkiller");

                     source.setUser("netkiller");

                     source.setPassword("chen");

                     source.setMaxConnections(10);

                     source.setInitialConnections(5);

                    

                     //new InitialContext().rebind("DataSource", source);

                     //DataSource source = (DataSource)new InitialContext().lookup("DataSource");

 

                     int n = 1;

                    

                     for(int i=0;i<100000;i++){

                     //source.setLoginTimeout();

                     conn = source.getConnection();

                     //prepstmt.clearParameters();

                     prepstmt = conn.prepareStatement("select * from \"users\" where id=?");

                     //System.out.println(conn.nativeSQL("select sss from users"));

                     prepstmt.setInt(1,1);

                     ResultSet rs = prepstmt.executeQuery();            

                     System.out.println(prepstmt.getQueryTimeout());

                     if(rs!=null) {

                            while(rs.next()){

                                   System.out.print(n +"|");

                                   System.out.print(rs.getInt(1) +"|");

                                   System.out.print(rs.getString(2) +"|");

                                   System.out.print(rs.getString(3) +"|");

                                   System.out.print(rs.getString(4) +"|");

                                   System.out.print(rs.getString(5) +"|");

                                   System.out.print(rs.getString(6) +"|");

                                   System.out.println();

                                   n++;

                            }

                    

                     }

                     conn.close();

                     }

              }catch(Exception e)       {

                     e.printStackTrace();

              }

             

              //pg.getConnection();

 

             

              //System.out.println(pg.executeQuery("select * from siteuser"));

              //pg.executeUpdate();

/*

             

              try{

              pg.prepareStatement("select * from \"users\" where id=?");

              pg.setInt(1,1);

              ResultSet rs = pg.executeQuery();       

                    

                     if(rs!=null) {

                    

                            while(rs.next()){

                                   System.out.print(rs.getInt(1) +"|");

                                   System.out.print(rs.getString(2) +"|");

                                   System.out.print(rs.getString(3) +"|");

                                   System.out.print(rs.getString(4) +"|");

                                   System.out.print(rs.getString(5) +"|");

                                   System.out.print(rs.getString(6) +"|");

                                   System.out.println();

                            }

                    

                     }

                     pg.close();

              }catch(Exception e)       {

                     e.printStackTrace();

              }

              System.out.println(org.postgresql.util.UnixCrypt.crypt("hi"));

              //System.out.println(org.postgresql.util.MD5Digest.encode("hi");

             

*/                 

       }

}

 

13.5.3 处理SQL 语句

package netkiller.database;

 

import java.util.*;

 

public class Database extends DBConnect{

      

       private String sqlFrom = null;

       private String sqlWhere = null;

       private String sqlOrder = null;

       private String sqlGroup = null;

       private String sqlLimit = null;

       private String sqlOffset = null;

      

       //private HashMap sqlHashField = new HashMap();

       private Hashtable sqlHashField = new Hashtable();

       private Vector        sqlVectorField = new Vector();

       private StringBuffer sql = new StringBuffer();

       private boolean isError = false;

       private final static String ERROR = "ERROR:";

 

       public Database() {

              // TODO: Add your code here

       }

      

       public void setFrom(String value){

              this.sqlFrom = value;    

       }

       public String getFrom(){

              if(sqlFrom == null){

                     isError = true;

                     return "<table>";

              }

              return this.sqlFrom;

       }

       public void setWhere(String value){

              this.sqlWhere = value;   

       }

       public String getWhere(){

              /*

              if(sqlWhere == null){

                     return "<where>"; 

              }

              */

              return sqlWhere;

       }

       public void setOrder(String value){

              this.sqlOrder = value;

       }

       public void setGroup(String value){

              this.sqlGroup = value;   

       }

       public void setLimit(String value){

              this.sqlLimit = value;     

       }

       public void setOffset(String value){

              this.sqlOffset = value;   

       }

       public void setLimit(int value){

              this.sqlLimit = value+"";

       }

       public void setOffset(int value){

              this.sqlOffset = value+"";     

       }    

       public void put(Object key,Object value){

              sqlHashField.put(key,value);

       }

       public void add(Object object){

              sqlVectorField.add(object);

       }

       public String Select(){

              sql = new StringBuffer(1024);

              sql.append("Select ");

              Enumeration enumer = sqlVectorField.elements();

              while(enumer.hasMoreElements()){

                     sql.append(enumer.nextElement());

                     if(enumer.hasMoreElements()) sql.append(",");

              }

              sql.append(" From "+ getFrom());

              if(sqlOrder != null) sql.append(" Where "+ getWhere());

              if(sqlOrder != null) sql.append(" Order By "+ sqlOrder);

              if(sqlGroup != null) sql.append(" Group By "+ sqlGroup);

              if(sqlLimit != null) sql.append(" Limit "+ sqlLimit);

              if(sqlOffset!= null) sql.append(" Offset "+ sqlOffset);

              return isError?ERROR+sql.toString():sql.toString();

       }

       public String Delete(){

              sql = new StringBuffer(255);

              sql.append("Delete From ");

              sql.append(getFrom());

              if(sqlOrder != null) sql.append(" Where "+ getWhere());

              return isError?ERROR+sql.toString():sql.toString();

       }

/*

       public String Update(){

              sql = new StringBuffer(1024);

              Iterator iterator = sqlHashField.entrySet().iterator();

              sql.append("Update ");

              String key,value;

              if(sqlFrom  != null) sql.append(sqlFrom+ " Set ");

              while(iterator.hasNext()){

                     Map.Entry map = (Map.Entry)iterator.next();

                     key = (String)map.getKey();

                 value = (String)map.getValue();

                     sql.append(key+"="+value);

                     if(iterator.hasNext())sql.append(",");

              }

              if(sqlWhere != null) sql.append(" Where "+ sqlWhere);

              return sql.toString();

       }

*/

 

       public String Update(){

              sql = new StringBuffer(1024);

              Iterator iterator = sqlHashField.entrySet().iterator();

              sql.append("Update ");

              String key,value,swap = "";

              sql.append(getFrom()+ " Set ");

              while(iterator.hasNext()){

                     Map.Entry map = (Map.Entry)iterator.next();

                     key = (String)map.getKey();

                 value = (String)map.getValue();

                

                     if(iterator.hasNext()){

                            swap = ","+key+"="+value + swap;     

                     }else{

                            swap = key+"="+value + swap;   

                     }

              }

              sql.append(swap);

              if(sqlOrder != null) sql.append(" Where "+ getWhere());

              return isError?ERROR+sql.toString():sql.toString();

       }

 

       public String Insert(){

              sql = new StringBuffer(1024);

              Enumeration enumer = sqlHashField.keys();

              sql.append("Insert Into ");

              String key = "", value = "";

              sql.append(getFrom()+ "(");

              sqlHashField.size();

              while(enumer.hasMoreElements()){

                 String tmp = (String)enumer.nextElement();

                     if(enumer.hasMoreElements()){

                            key = "," + tmp + key;

                            value = ","+ sqlHashField.get(tmp) +value;

                     }else{

                            key = tmp + key;

                            value = sqlHashField.get(tmp) + value;

                     }

                    

                    

              }

              sql.append(key);           

              sql.append(") value(");

              sql.append(value);

              sql.append(")");

             

              return isError?ERROR+sql.toString():sql.toString();

       }

 

       public static void main(String[] args) {

              // TODO: Add your code here

              Database db = new Database();

              db.add("id");

              db.add("name");

              db.add("company");

              db.add("pages");

      

              db.put("id","1");

              db.put("name","netkiller");

              db.put("company","none");

              db.put("number","10");

              db.put("tel","0755-1234666");

              db.put("fax","0755-2556888");

 

              db.setFrom("ctoc.test");

              db.setWhere("chen = chen");

              db.setOrder("id");

              db.setGroup("name");

              db.setLimit(10);

              db.setOffset("0");

                           

              String sql = db.Select();

              System.out.println(sql);

              System.out.println(db.Delete());

              System.out.println(db.Update());

              System.out.println(db.Insert());

             

 

       }

      

}

 

13.5.4 处理HTML表格

package netkiller.table;

 

import java.sql.*;

import java.util.*;

import java.util.regex.*;

import javax.servlet.jsp.*;

import javax.servlet.ServletRequest;

import javax.servlet.http.HttpServletRequest;

import netkiller.util.*;

import netkiller.database.*;

 

 

public class BaseTable { //extends AnySQL

 

       //AnySQL oTable = new AnySQL();

       private static String oDatabase     = null;

       private static final String Auth      = "cleartext";   //crypt

       public static final String DESC = "DESC";

       public static final String ASC  = "ASC";

       public static final String RADIO         = "radio";

       public static final String CHECKBOX   = "checkbox";

      

       private DBConnect dbc                                     = null;

       private ResultSet rs                            = null;

       private PageContext pageContext         = null;    

       private Vector vError = new Vector();

      

       private static boolean debug = false;

 

       private int      nTableColumn = 0;

       private int      nTableRow           = 0;

       private int      nColumnCount       = 0;

       private int              nRowCount           = 0;

      

       private boolean isChoose              = false;

       private String  strChooseStyle       = "";

       private boolean isDelete         = false;

//     private String        strDeleteLink  = null;

       private boolean isEdit                   = false;

       private String        strEditLink             = null;

       private boolean isFilter          = false;

      

       private String[][]   aTableData            = null;

       private String[]      strTableHeader       = null;

       private String[]      strTableField   = null;

       private int             nSqlLimit        = 1;

       private int                   nSqlOffset             = 0;

       private static String strSQL          = null;

       private String               strWhere        = null;

       private int                     nPage                    = 0;

      

       private String sqlWhere = null;

       private String sqlOrder = "";

       private String sqlLimit = "";

       private String sqlOffset= "";

             

       private Vector v = new Vector();

       private Vector cursor = new Vector();

       private Vector filter = new Vector();

      

       // HTML

//     private String        strTableName  = null;

//     private String        strCssClass            = null;

//     private int      nHeight                 = 0;

//     private int      nWidth                  = 0;

      

       public BaseTable() {

       }

      

       public BaseTable(String odb) {

              this.setDatabaseHandle(odb);

       }

             

       public void setDatabaseHandle(String odb){

              this.oDatabase = odb;

       }

      

       public String getDatabaseHandle(){

              return this.oDatabase;   

       }

      

       //功能

       //javax.servlet.jsp.PageContext pageContext

       public void setPageContext(PageContext pc){

              pageContext = pc;

              try{

                     ServletRequest request = pageContext.getRequest();

                     jspParameter jsppar = new jspParameter(request);

                     int page = jsppar.getInt("page",0);

                    

                     String filter           = jsppar.getString("filter");

                     String condition     = jsppar.getString("condition");

                     String key                    = jsppar.getString("key");

                    

                     this.setPage(page);

                     this.setWhere(filter,condition,key);

                     //this.setWhere("id","like","5");

                     //this.setWhere("id = 67");

                     this.MakeHtmlTable();

                    

                     if(debug){

                            pageContext.getOut().print("SQL:"+this.getSQL()+"<br>");

                            pageContext.getOut().print("Table:"+this.sqlAnalyzer(this.getSQL())+"<br>");

                            pageContext.getOut().print("Where:"+this.getWhere()+"<br>");

                            pageContext.getOut().print("Order:"+this.getOrderBy()+"<br>");

                            pageContext.getOut().print("Limit:"+this.getLimit()+"<br>");

                            pageContext.getOut().print("Offset:"+this.getOffset()+"<br>");

                            pageContext.getOut().print("Count:"+this.getRowCount()+" sql = select count(*) from "+this.sqlAnalyzer(this.getSQL())+getWhere()+"<br>");

                            this.getException();

                     }

              }catch(Exception e){

                     e.printStackTrace();

              }           

             

       }    

       // Debug

       public void setDebug(boolean debug){

              System.out.println("SQL:"+this.getSQL()+"<br>");

              this.debug = debug;

       }

      

       // 批量选择记录 radio,checkbox

       public void setChoose(boolean bool,String style){

              this.isChoose = bool;

              this.strChooseStyle = style;

              if(this.strChooseStyle.equals("radio")){

              }else if(this.strChooseStyle.equals("checkbox")){

              }else{

                     this.isChoose = false;    

              }

                    

                    

       }

       public String getChooseStyle(String id){

              String tmp = null;

              if(this.strChooseStyle.equals("radio")){

                     tmp = "<input type=\"radio\" name=\"id\" value=\""+id+"\">";

              }else if(this.strChooseStyle.equals("checkbox")){

                     tmp = "<input type='checkbox' name='id' value='"+id+"'>";

              }else{     }

              return tmp;

       }

      

/*   

                                   if(isEdit){

                                          //v.add("<td><a href=\"javascript:OpenDialog('http://localhost:8080/autosite/member/"+strEditLink+aTableData[0][r]+"')\">编辑</a></td>");

                                          v.add("<td "+this.getHtmlTd()+"><a href="+strEditLink+rs.getString(1)+">编辑</a></td>");

                                   }

                                   if(isDelete){

                                          //v.add("<td><input type=\"button\" name=\"Delete\" value=\"删除\" onclick=\"javascript:mysubmit('del_selected')\"></td>");

                                          //v.add("<td><a href="+strDeleteLink+aTableData[0][r]+">删除</a></td>"); //onclick=\"javascript:mysubmit('del_selected')\"

                                          v.add("<td "+this.getHtmlTd()+" align='center'><a href="+this.getDeleteLink(strDeleteLink+rs.getString(1))+">删除</a></td>"); //onclick=\"javascript:mysubmit('del_selected')\"

                                   }

       */

       // 删除记录按钮

       public void setDelete(boolean bool){

              this.isDelete    = bool;

       }

       // 编辑记录按钮

       public void setEdit(boolean bool,String url){

              this.isEdit              = bool;

              strEditLink             = url;

       }

      

       public void setFilter(boolean filter){

              this.isFilter     = filter;

       }

       public boolean getFilter(){

              return this.isFilter;

       }

 

    //TableModel

    public void setTableModel(){}

       public void setSize(){}

       public void getSize(){}

      

       public void setBorder(int border){

              this.htmlTableBorder = " border="+border;

       }

       public String getBorder(){

              return this.htmlTableBorder;

       }

       public void setFont(){}

       public void getFont(){}

       public void setGridground(){}

       public void getGridground(){}

       public void setForeground(){}

       public void getForeground(){}

       public void setBackground(){}

       public void getBackground(){}

       /**

        * 版面设置

        **/

       public void setLayout(String css){}

       public void getLayout(String css){}

       public void setMaximumSize(){}

       public void setMinimumSize(){}

      

       public void setTableHeader(String[] sth){

              strTableHeader       = sth;

       }

       public String[] getTableHeader(){

              return strTableHeader;

       }

      

       public void setPage(int page){

              this.nPage = page;

       }

       // 取得当前页

       public int getPage(){

              return this.nPage;

       }

 

       /**

        *    <table></table>,<tr></tr>,<td></td>

        **/

       private String htmlTableCaption  = null;

       private String htmlTable        = "";

       private String htmlTableBorder      = "";

       private String htmlTableHeight      = "";

       private String htmlTableWidth       = "";

       private String htmlTr            = "";

       private String htmlTd            = "";

      

       private String htmlRowHeight= "";

       private String htmlRowWidth = "";

               

       private String htmlHeaderTr = "";

       private String htmlHeaderTd = "";

             

       public void setHtmlTable(String html){

              this.htmlTable = html;

       }

       public void setHtmlTableCaption(String html){

              htmlTableCaption =  "<caption>";

              htmlTableCaption += html;

            htmlTableCaption += "</caption>";

    }

       public String getHtmlTableCaption(){

              if(htmlTableCaption == null)htmlTableCaption ="";

            return htmlTableCaption;

    }    

       public void setHtmlTableHeaderTr(String html){

              this.htmlHeaderTr= html;     

       }

       public String getHtmlTableHeaderTr(){

              return this.htmlHeaderTr;     

       }

      

       public void setHtmlTableHeaderTd(String html){

              this.htmlHeaderTd  = html;   

       }

       public String getHtmlTableHeaderTd(){

              return this.htmlHeaderTd;

       }    

      

       public void setHtmlTr(String html){

              this.htmlTr     = html;   

       }

       public void setHtmlTd(String html){

              this.htmlTd     = html;   

       }

       public String getHtmlTable(){

              return this.htmlTable + getBorder();

       }

       public String getHtmlTr(){

              return this.htmlTr; 

       }

       public String getHtmlTd(){

              return this.htmlTd + getRowHeight() + getRowWidth();    

       }

       public void setRowHeight(int high){

              this.htmlRowHeight = " height="+high;

       }

       public String getRowHeight(){

              return this.htmlRowHeight;

       }

       public void setRowWidth(int width){

              this.htmlRowWidth = " width="+width;

       }

       public String getRowWidth(){

              return this.htmlRowWidth;   

       }    

      

       private HashMap hashAddHtmlColumn = new HashMap();

       private HashMap htmlTableRow=  new HashMap();

       private HashMap htmlColumn=  new HashMap();

      

       //HTML Row Operator

       //public void addRow(String html){}

       //public String getRow(){}

      

       public void setHtmlTableRow(int col,String beginmarkup,String field,String endmarkup,String end){

              String key = col + "";

              String value = beginmarkup+"<table:row key='"+field+"' />"+endmarkup+"<table:row value />"+end;

              this.htmlTableRow.put(key,value);

       }

       public void setHtmlTableRow(int col,String begin,String end){

              String key = col + "";

              String value = begin+"<table:row value />"+end;

              this.htmlTableRow.put(key,value);

       }

             

       //HTML Comlumn Operator

 

       /**

        *    Hide Column

        **/

       private int arrayHideColumn[] = null;

      

       public void setHideColumn(int col){

              arrayHideColumn = new int[1];

              arrayHideColumn[0] = col;

       }    

       public void setHideColumn(int col[]){

              arrayHideColumn = col;

       }

       public boolean getHideColumn(int col){

              boolean isHide = false;

              if(arrayHideColumn == null){

                     isHide = true;

              }else{

                     for(int hide=0;hide<arrayHideColumn.length;hide++){

                            if(arrayHideColumn[hide] == col){

                                   isHide = false;

                                   break;

                            }else{

                                   isHide = true;

                            }

                     }

              }

              return isHide; 

       }

      

      

       public void addHtmlColumn(int key,String value){

              this.hashAddHtmlColumn.put(key + "",value);

       }

       public void addRs2HtmlColumn(int key,String begin0,String field,String begin1,String value,String end){

              value = begin0+"<!-- key='"+field+"' -->"+begin1+"<!-- value='"+value+"' -->"+end;

              this.hashAddHtmlColumn.put(key + "",value);

       }    

 

       public void addHtmlColumn(int key,String begin0,String field,String begin1,String value,String end){

              value = begin0+"<!-- key='"+field+"' -->"+begin1+value+end;

              this.hashAddHtmlColumn.put(key + "",value);

       }

      

       public void addHtmlColumn(int key,String begin,String value,String end){

              value = begin+value+end;

              this.hashAddHtmlColumn.put(key + "",value);

       }

      

       public void setColumnWidth(){}

      

       public void setColumnCount(int number){

              nTableColumn = number;

       }

       public int getColumnCount(){

              return nTableColumn;

       }

       public void getColumnName(){}

       public void getColumnValue(){}

      

       public void setHtmlColumn(int col,String beginmarkup,String field,String endmarkup,String end){

              String key = col + "";

              String value = beginmarkup+"<!-- key="+field+" -->"+endmarkup+"<!-- value -->"+end;

              this.htmlColumn.put(key,value);

       }

       public void setHtmlColumn(int col,String begin,String end){

              String key = col + "";

              String value = begin+"<!-- value -->"+end;

              this.htmlColumn.put(key,value);

       }

/**

 * 其它方法

 **/

//     private int nSequence = 0;

       private boolean isShowSequence = true;

       public void setSequence(boolean bool){

              isShowSequence = bool;

       }

/*    public int getSequence(){

              return nSequence;

       }

*/

       /**

        *    返回表记录

        **/

       public void setRowCount(int number){

              nTableRow     =    number;

       }

       public int getRowCount(){

              return nTableRow;

       }    

       public int getCount(String strTable){

              int nCount      = 0;

              try{

                     dbc = new DBConnect(oDatabase);

                     dbc.prepareStatement("select count(*) from "+strTable+getWhere());

                     rs = dbc.executeQuery();

                     if(rs != null){

                            while(rs.next()){

                                   nCount    = rs.getInt(1);

                            }

                            setRowCount(nCount);

                     }

              }

              catch(Exception e){

                     e.printStackTrace();

              }

              finally{

                     try{

                            if(rs != null)rs.close();

                            dbc.close();

                     }catch(Exception e){

                            e.printStackTrace();

                     }

              }    

              return nCount;

       }

      

       public void setValueAT(){}

       public void getCursor(){}

      

//     public void setListData(Vector){}

//     public void setListData(String[]){}

      

      

       public boolean setVisible(boolean bool){

              return true;

       }

       public void visible(){

              setVisible(true);

       }

       public void hide(){

              setVisible(false);

       }

 

       public void enable(){};

       public void disable(){};

      

       public void setSQL(String sql){

              this.strSQL = sql;

       }

 

       public String getSQL(){

              return this.strSQL + getWhere() +" "+ sqlOrder +" "+ sqlLimit +" "+sqlOffset;

             

       }

 

       public void setWhere(String field,String cond,String val){

              if(val != null && field != null && cond != null){

                     if(cond.equals("like")){

                            this.strWhere = field+" "+cond+" '%"+val+"%'";

                     }else{

                            this.strWhere = field+" "+cond+" '"+val+"'";

                     }

                     if(sqlWhere != null)

                            sqlWhere +=" And "+strWhere;

                     else

                            sqlWhere = this.strWhere;

                     this.isFilter = true;

              }

       }

      

       public void setWhere(String where){

              if(this.sqlWhere == null){

                     this.sqlWhere = where;

              }else{

                     this.sqlWhere = " and " + where;

              }

       }

      

       public String getWhere(){

              String tmp = null;

              if(sqlWhere == null){

                     tmp = "";

              }else{

                     tmp = " Where "+sqlWhere;

                    

              }

              return tmp;

       }

 

       public void setOrderBy(String order,String sort){

              if(order != null){

                     if(sort.equals(DESC)){

                            this.sqlOrder += " ORDER BY "+ order +" DESC";

                     }else{

                            this.sqlOrder += " ORDER BY "+ order +" ASC";

                     }

              }else

                     sqlOrder = "";

       }    

      

       public String getOrderBy(){

              return sqlOrder;

       }

      

       public void setSort(String order,String sort){

              if(order != null){   

                     if(sort.equals(DESC)){

                            this.sqlOrder += " ORDER BY "+ order +" DESC";

                     }else{

                            this.sqlOrder += " ORDER BY "+ order +" ASC";

                     }

              }else

                     sqlOrder = "";

       }

       public void setLimit(int limit){

                     this.nSqlLimit  = limit;

                     this.sqlLimit = " limit "+limit;

       }

       public int getLimit(){

              return this.nSqlLimit;

       }

      

       public void setOffset(int offset){

              this.nSqlOffset       = offset;

              if(this.isFilter == false){

                     sqlOffset = " offset "+offset;

              }

       }

       public int getOffset(){

              return this.nSqlOffset;

       }

      

       public String sqlAnalyzer(String sql){

              String tmp= sql.substring(sql.toLowerCase().indexOf(" from ")+6);

              String value = "";

              if(tmp.indexOf(" ") == -1){

                     value = tmp.substring(0,sql.length());

              }else{

                     value = tmp.substring(0,tmp.indexOf(" "));

              }

              return value;

       }

 

       public java.sql.ResultSet TableResultSet(){

              //this.setOffset(this.nSqlLimit*this.nPage);

              this.getCount(sqlAnalyzer(this.getSQL()));

              try{

                     this.setOffset(this.nSqlLimit*this.nPage);

                     dbc = new DBConnect();

                     dbc.prepareStatement(this.getSQL());

                     rs = dbc.executeQuery();

                    

                     //while(rs.next()){

                     //System.out.println("test:" +rs.getString(1));      

                     //}

                     vError.add("TableResultSet()");

              }

              catch(Exception e){

                     vError.add(e.toString());

              }

              return rs;

       }

       public String getJavaScript(){

              String script = "";

              script += "<script language=\"JavaScript\" type=\"text/JavaScript\"> \n";

              script += "<!-- \n";

              script += "function Delete(url){ \n";

              script += "        if(confirm(\"您确定要删除?\")){ \n";

             script += "             location.href=url; \n";

             script += "        } \n";

              script += "} \n";

              script += "//--> \n";

              script += "</script> \n";

              return script;  

       }

       public Vector MakeHtmlTable(){

              v.add("<!-- Html Table 组件 netkiller 陈景峰 netkillers@sohu.com --> \n");

              v.add("<!-- Begin --> \n");

             

              String field     = "";

              Pattern pattern       = null;

              Matcher matcher    = null;    

              int begin,end = 0;

             

              if(isDelete) v.add(this.getJavaScript());

              this.setOffset(this.nSqlLimit*this.nPage);

              this.getCount(sqlAnalyzer(this.getSQL()));

              try{

                     dbc = new DBConnect();

                     dbc.prepareStatement(this.getSQL());

                     rs = dbc.executeQuery();

                    

                     ResultSetMetaData rsmd = rs.getMetaData() ;

                     this.setColumnCount(rsmd.getColumnCount());

                     //-------- Header Begin -------------

                     if(strTableHeader == null){

                            strTableHeader = new String[this.getColumnCount()];

                            strTableField  = new String[this.getColumnCount()];

                            for(int col=1;col<=this.getColumnCount();col++){

                                   strTableHeader[col-1] = rsmd.getColumnName(col);

                                   strTableField[col-1] = rsmd.getColumnName(col);

                            }

                     }else{

                            strTableField  = new String[this.getColumnCount()];

                            for(int col=1;col<=this.getColumnCount();col++){

                                   strTableField[col-1] = rsmd.getColumnName(col);

                            }

                     }

                     //-------- Header End -------------

                     if(rs!=null) {

                            v.add("<table "+this.getHtmlTable()+"> \n");

                            v.add(getHtmlTableCaption() +"\n");

                            if(strTableHeader != null){

                                   v.add("<tr "+this.getHtmlTableHeaderTr()+"> \n");

                                   if(isShowSequence){

                                          v.add("\t<td "+this.getHtmlTableHeaderTd()+">&nbsp;</td> \n");

                                   }

                                   for(int i=0;i<this.getTableHeader().length;i++){

                                          if(getHideColumn(i+1)){

                                                 if(htmlTableRow.containsKey("0")){

                                                       

                                                        field = ((String)this.htmlTableRow.get("0"));

                                                        if(field.indexOf("key=") != -1){

                                                               begin = field.indexOf("<table:row key='");

                                                               end = field.indexOf("' />",begin);

                                                               String sql_field = field.substring(begin+16,end);

                                                               pattern = Pattern.compile("<table:row key='(.*)' />");

                                                               matcher = pattern.matcher(field);

                                                               field = matcher.replaceAll(sql_field);

                                                               field = field.replaceAll("<table:row value />",this.getTableHeader()[i]);      

                                                        }else{

                                                               field = field.replaceAll("<table:row value />",this.getTableHeader()[i]);      

                                                        }

                                                       

                                                        v.add("    <td "+this.getHtmlTableHeaderTd()+">"+field+"</td> \n");

                                                 }else{

                                                        v.add("    <td "+this.getHtmlTableHeaderTd()+">"+this.getTableHeader()[i]+"</td> \n");

                                                 }

                                                

                                          }

                                   }

                                   v.add("</tr> \n");

                            }

                           

                            if(isEdit){

                                          //v.add("<td><a href=\"javascript:OpenDialog('http://localhost:8080/autosite/member/"+strEditLink+aTableData[0][r]+"')\">编辑</a></td>");

                                          //v.add("<td "+this.getHtmlTd()+"><a href="+strEditLink+rs.getString(1)+">编辑</a></td>");

                                   this.addHtmlColumn(-1,"<a href='"+strEditLink,"id","'>","修改","</a>");

                            }

                            if(isDelete){

                                          //v.add("<td><input type=\"button\" name=\"Delete\" value=\"删除\" onclick=\"javascript:mysubmit('del_selected')\"></td>");

                                          //v.add("<td><a href="+strDeleteLink+aTableData[0][r]+">删除</a></td>"); //onclick=\"javascript:mysubmit('del_selected')\"

                                          //v.add("<td "+this.getHtmlTd()+" align='center'><a href="+this.getDeleteLink(strDeleteLink+rs.getString(1))+">删除</a></td>"); //onclick=\"javascript:mysubmit('del_selected')\"

                                   this.addHtmlColumn(-2,"<a href=javascript:Delete('?op=delete&id=","id","')>","删除","</a>");

                            }

                           

                            boolean bool = false;

                            int row = 1;

                            while(rs.next()){

                                   v.add("  <tr "+this.getHtmlTr()+"> \n");

                                                                      if(isShowSequence){

                                          v.add("\t<td "+this.getHtmlTd()+"><center>"+row+"</center></td> \n");

                                   }

                                   for(int col=1;col<=this.getColumnCount();col++){

                                          if(getHideColumn(col)){ //隐藏列

                                                 String key = col + "";

                                                 bool = htmlColumn.containsKey(key);

                                                 if(bool){  //列设置

                                                        field = ((String)this.htmlColumn.get(key));

                                                        begin = field.indexOf("key=");

                                                        if(begin != -1){

                                                               begin = field.indexOf("<!-- key=");

                                                               end = field.indexOf(" -->",begin);

                                                               String sql_field = field.substring(begin+9,end);

                                                               field = field.replaceAll("<!-- key="+sql_field+" -->",rs.getString(sql_field));

                                                        }

                                                        field = field.replaceAll("<!-- value -->",rs.getString(col));

                                                        v.add("    <td "+this.getHtmlTd()+">"+ field +"</td> \n");

                                                 }else if(htmlTableRow.containsKey(row+"")){

                                                        field = ((String)this.htmlTableRow.get(row+""));

                                                        if(field.indexOf("key=") != -1){

                                                               begin = field.indexOf("<table:row key='");

                                                               end = field.indexOf("' />",begin);

                                                               String sql_field = field.substring(begin+16,end);

                                                               pattern = Pattern.compile("<table:row key='(.*)' />");

                                                               matcher = pattern.matcher(field);

                                                               field = matcher.replaceAll(rs.getString(sql_field));

                                                        }

                                                        field = field.replaceAll("<table:row value />",rs.getString(col));

                                                        v.add("    <td "+this.getHtmlTd()+">"+ field +"</td> \n");

                                                 }else{

                                                        v.add("    <td "+this.getHtmlTd()+">"+ rs.getString(col) +"&nbsp;</td> \n");

                                                 }

                                                 // add table column

                                                 bool = hashAddHtmlColumn.containsKey(key);

                                                 if(bool){

                                                        field = (String)this.hashAddHtmlColumn.get(key);

                                                        begin = field.indexOf("key=");

                                                        if(begin == -1){

                                                               v.add("    <td "+this.getHtmlTd()+">"+(String)this.hashAddHtmlColumn.get(key)+"&nbsp;</td> \n");

                                                        }else{

                                                               begin = field.indexOf("<!-- key='");

                                                               end = field.indexOf("' -->",begin);

                                                               String sql_field = field.substring(begin+10,end);

                                                               field = field.replaceAll("<!-- key='"+sql_field+"' -->",rs.getString(sql_field));

                                                              

                                                               begin = field.indexOf("<!-- value='");

                                                               if(begin != -1){

                                                                      end = field.indexOf("' -->",begin);

                                                                      sql_field = field.substring(begin+12,end);

                                                                      field = field.replaceAll("<!-- value='"+sql_field+"' -->",rs.getString(sql_field));

                                                               }

                                                               v.add("    <td "+this.getHtmlTd()+">"+ field +"</td> \n");

                                                        }

                                                 }

                                                 if(col == this.getColumnCount()){

                                                        if(hashAddHtmlColumn.containsKey("-1")){

                                                               field = (String)this.hashAddHtmlColumn.get("-1");

                                                               begin = field.indexOf("key=");

                                                               if(begin == -1){

                                                                      v.add("    <td "+this.getHtmlTd()+">"+(String)this.hashAddHtmlColumn.get(key)+"&nbsp;</td> \n");

                                                               }else{

                                                                      begin = field.indexOf("<!-- key='");

                                                                      end = field.indexOf("' -->",begin);

                                                                      String sql_field = field.substring(begin+10,end);

                                                                      field = field.replaceAll("<!-- key='"+sql_field+"' -->",rs.getString(sql_field));

                                                                     

                                                                      begin = field.indexOf("<!-- value='");

                                                                      if(begin != -1){

                                                                             end = field.indexOf("' -->",begin);

                                                                             sql_field = field.substring(begin+12,end);

                                                                             field = field.replaceAll("<!-- value='"+sql_field+"' -->",rs.getString(sql_field));

                                                                      }

                                                                      v.add("    <td "+this.getHtmlTd()+">"+ field +"</td> \n");

                                                               }

                                                        }

                                                        if(hashAddHtmlColumn.containsKey("-2")){

                                                               field = (String)this.hashAddHtmlColumn.get("-2");

                                                               begin = field.indexOf("key=");

                                                               if(begin == -1){

                                                                      v.add("    <td "+this.getHtmlTd()+">"+(String)this.hashAddHtmlColumn.get(key)+"&nbsp;</td> \n");

                                                               }else{

                                                                      begin = field.indexOf("<!-- key='");

                                                                      end = field.indexOf("' -->",begin);

                                                                      String sql_field = field.substring(begin+10,end);

                                                                      field = field.replaceAll("<!-- key='"+sql_field+"' -->",rs.getString(sql_field));

                                                                     

                                                                      begin = field.indexOf("<!-- value='");

                                                                      if(begin != -1){

                                                                             end = field.indexOf("' -->",begin);

                                                                             sql_field = field.substring(begin+12,end);

                                                                             field = field.replaceAll("<!-- value='"+sql_field+"' -->",rs.getString(sql_field));

                                                                      }

                                                                      v.add("    <td "+this.getHtmlTd()+">"+ field +"</td> \n");

                                                               }

                                                        }

                                                       

                                                 }

                                          }

                                   }

                                  

                    

                                  

                                   row ++;

                                   v.add("  </tr> \n");

                            }

                            v.add("</table> \n");

                     }else{

                            v.add("没有数据");

                     }

                    

                     //=========================================

                     // 表格导航条

                     //=========================================

                     int npage = this.getPage();

                     int pagecount = 0;

                     if(this.getRowCount()%this.getLimit() == 0){

                                   pagecount = this.getRowCount()/this.getLimit();

                     }else{

                                   pagecount = this.getRowCount()/this.getLimit()+1;

                     }

                    

                     cursor.add("<!-- Begin 表格控制条 --> \n");

                     cursor.add("<table border=0 style='border-collapse: collapse' cellpadding='2'> \n"); //align=right

                            cursor.add("<tr> \n");

                            cursor.add("<td>总计"+ this.getRowCount() +"条纪录</td>");

                            cursor.add("<td>"+ (npage+1) + "/" + pagecount +"</td>");

                            cursor.add("<td>&nbsp;&nbsp;&nbsp;&nbsp;</td>");

                            cursor.add("<td><a href='?page=0'>[首页]</a></td>");

                            if(npage == 0){

                                   cursor.add("<td>[上一页]</td>");

                            }else{

                                   cursor.add("<td><a href='?page="+ (npage-1) +"'>[上一页]</a></td>");

                            }

                           

                            cursor.add(" \n <td> \n");

                                   cursor.add("<select name='page' id='page' size=0 onChange=window.location.href='?page='+this.options[this.selectedIndex].value> \n");

                                   cursor.add("<option value='"+npage+"' selected>["+(npage+1)+"]</option> \n");     

                                   for(int i=0;i<pagecount;i++){

                                          cursor.add("<option value='"+i+"'>"+(i+1)+"</option> \n");

                                   }

                                   cursor.add("</select> \n");

                            cursor.add("</td> \n");

                           

                            if(npage+1 == pagecount){

                                   cursor.add("<td>[下一页]</td>");

                                   cursor.add("<td>[末页]</td>");

                            }else{

                                   cursor.add("<td><a href='?page="+ (npage+1) +"'>[下一页]</a></td>");

                                   cursor.add("<td><a href='?page="+ (pagecount-1) +"'>[末页]</a></td>");

                            }

                            cursor.add("\n </tr> \n");

 

                     cursor.add("</table> \n");     

                     cursor.add("<!-- End 表格控制条 --> \n");

                    

                     filter.add("<!-- --------------------- Begin Filter ------------------ --> \n");

                            filter.add("<table boder=0>");

                            filter.add("<form method='post' action=''>");

                            //filter.add("<td>筛选</td>");

                            filter.add("<td>");

                            filter.add("<select name='filter' id='filter'> \n");

                            filter.add("<option value='id' selected>选择筛选列</option> \n");

                                   for(int i=0;i<this.strTableField.length;i++){

                                          if(i>=getTableHeader().length)break;

                                          if(getHideColumn(i+1)) //continue;

                                                 filter.add("<option value='"+this.strTableField[i]+"'>"+this.getTableHeader()[i]+"</option> \n");

                                   }

                           

                            filter.add("</select> \n");

                            filter.add("</td>");

                            filter.add("<td>");

                            filter.add("<select name='condition' id='condition'> \n");

                                   filter.add("<option value='like' selected>模糊</option> \n");

                                   filter.add("<option value='='>=</option> \n");

                                   filter.add("<option value='!='></option> \n");

                                   filter.add("<option value='>'>></option> \n");

                                   filter.add("<option value='>='>>=</option> \n");

                                   filter.add("<option value='<'><</option> \n");

                                   filter.add("<option value='<='><=</option> \n");

                            filter.add("</select> \n");

                            filter.add("</td>");

                            filter.add("<td>");

                            filter.add("<input name='key' type='text' id='key'>");

                            filter.add("</td>");

                            filter.add("<td>");

                            filter.add("<input type='submit' name='Submit' value=' 查询 '>");

                            filter.add("</td>");

                            filter.add("</form>");

                            filter.add("</table> \n");

                     filter.add("<!-- --------------------- End Filter -------------------- --> \n");

              }

              catch(Exception e){

                     v.add("没有数据或类型不匹配");

                     e.printStackTrace();

              }

              finally{

                     try{

                            if(rs != null)rs.close();

                            dbc.close();

                     }catch(Exception e){

                            e.printStackTrace();

                     }

              }    

              v.add("<!-- End --> \n");

              return v;

       }

       public boolean getHtmlStyleTable(){

              boolean isSuccess = false;

              Vector html = this.v;

              try{

                     Enumeration enumer = html.elements();

                     while(enumer.hasMoreElements()){

                            String strHtml = (String) enumer.nextElement();

                            pageContext.getOut().print(strHtml);

                     }

                     isSuccess = true;

              }catch(Exception e){

                     System.out.print(e.toString());

              }           

              return isSuccess;

       }

      

       public boolean getCursorControlKeys(){

              boolean isSuccess = false;

              try{

                     Enumeration enumer = this.cursor.elements();

                     while(enumer.hasMoreElements()){

                            String strHtml = (String) enumer.nextElement();

                            pageContext.getOut().print(strHtml);

                     }           

                     isSuccess = true;

              }catch(Exception e){

                            e.printStackTrace();

              }           

              return isSuccess;

       }

 

       public void getFilterControl(){

              try{

                     Enumeration enumer = this.filter.elements();

                     while(enumer.hasMoreElements()){

                            String strHtml = (String) enumer.nextElement();

                            pageContext.getOut().print(strHtml);

                     }           

              }catch(Exception e){

                            e.printStackTrace();

              }

       }

      

       public String[][] getTableData(){

              int row    = 0;

              String[][] data = null;

              this.setOffset(this.nSqlLimit*this.nPage);

              //this.setRowCount();

              this.getCount(sqlAnalyzer(this.getSQL()));

              try{

                     dbc = new DBConnect(oDatabase);

                     dbc.prepareStatement(this.getSQL());

                     //System.out.println(this.getSQL());

                     rs = dbc.executeQuery();

                    

                     ResultSetMetaData rsmd = rs.getMetaData() ;

                     this.setColumnCount(rsmd.getColumnCount());

                     //data = new String[this.getColumnCount()][this.getRowCount()];

                     data = new String[this.getColumnCount()][this.nSqlLimit];

                     strTableHeader = new String[this.getColumnCount()];

                     for(int col=1;col<=this.getColumnCount();col++){

                            strTableHeader[col-1] = rsmd.getColumnName(col);

                     }

                     if(rs!=null) {

                            while(rs.next()){

                                   for(int col=1;col<=this.getColumnCount();col++){

                                          data[col-1][row]=rs.getString(col);

                                   }

                                   row++;

                            }

                     }

 

                     if(row != this.getLimit()){

                            String[][] tmp = new String[this.getColumnCount()][row];

                            //tmp = data;

 

                            for(int r=0;r<row;r++){

                                   for(int col=0;col<this.getColumnCount();col++){

                                          tmp[col][r] = data[col][r];

                                   }

                            }

                            data = tmp;

                            /*

                            for(int r=row;r<=this.getLimit();r++){

                                   for(int col=1;col<=this.getColumnCount();col++){

                                          data[col-1][r]="";

                                   }

                            }

                            */

                     }

                     rs.close();

              }

              catch(Exception e){

                     e.printStackTrace();

              }

              finally{

                     try{

                            if(rs != null)rs.close();

                            dbc.close();

                     }catch(Exception e){

                            e.printStackTrace();

                     }

              }    

              return data;

       }    

       public Vector MakeHtmlTable(int page,int limit,String order,String seq){

              Vector v         = new Vector();

              String script          = null;

              //String script_edit = "window.showModelessDialog("http://www.9812.net","dialogwin","scroll:0;status:0;help:1;resizable:1;dialogWidth:480px;dialogHeight:320px");"

              String old_seq        = seq;

              //this.getCount(this.sqlAnalyzer(this.getSQL()));

             

              if(seq.equals("ASC")){

                     this.setSort(order,ASC);

                     seq = "DESC";

              }else{

                     this.setSort(order,DESC);                           //排序,DESCASC

                     seq = "ASC";

              }

 

              this.setLimit(limit);                             //设置每页记录条数

              this.setOffset(this.nSqlLimit*page);      //翻页操作

              this.setPage(page);

              //v.add(this.strSQL);                                         //测试输出SQL

              try{

                     aTableData      = getTableData();

                           

                            script =  "<script language=\"JavaScript\"> \n";

                            script += "<!-- \n";

                            script += "function CheckAll(form){ \n";

                            script += "      for(var i=0;i<form.elements.length;i++) { \n";

                            script += "             var e = form.elements[i]; \n";

                            script += "             if(e.name != 'chkall') \n";

                            script += "             e.checked = form.chkall.checked; \n";

                            script += "      } \n";

                            script += "} \n";

                          

                           script += "function OpenDialog(url){ \n";

                           script += "      window.showModelessDialog(url,'dialogwin','scroll:0;status:0;help:1;resizable:1;dialogWidth:480px;dialogHeight:320px'); \n";

                           script += "} \n";

                          

                            script += "function Delete(url){ \n";

                            script += "        if(confirm(\"您确定要删除?\")){ \n";

                           script += "             location.href=url; \n";

                           script += "        } \n";

                           script += "} \n";

                          

                           script += "function allChecked(radio){ \n";

                           script += "      for(i=0; i<radio.length; i++) \n";

                           script += "             if(radio[i].checked) \n";

                           script += "        return (true); \n";

                           script += "                    return(false); \n";

                           script += "} \n";

                          

                           script += "//--> \n";

                           script += "</script> \n";

                   

                            v.add(script);

                           

                     v.add("<table border='1' cellpadding='1' cellspacing='0' style='border-collapse: collapse' bordercolor='#111111' width='100%' id='AutoNumber1'>");

                     v.add("<tr align=middle>");

                     if(isChoose && this.strChooseStyle.equals("checkbox")){

                            v.add("<td><input type=\"checkbox\" name=\"chkall\" value=\"on\" onclick=\"CheckAll(this.form)\"></td>");

                     }else if(this.strChooseStyle.equals("radio")){

                            v.add("<td></td>");      

                     }

                            v.add("<td>序号</td>");

                     for(int i=0;i<this.getTableHeader().length;i++){

                            v.add("<td><a href='?order="+this.getTableHeader()[i]+"&seq="+seq+"&page="+this.getPage()+"'>"+(this.getTableHeader()[i].equals(order)?this.getTableHeader()[i]+(old_seq.equals("ASC")?"":""):this.getTableHeader()[i])+"</a></td>");

                     }

                     // -------------------------------------------------------------------------------------------

                     v.add("</tr> \n");

                     //System.out.println(aTableData[0].length);

                    

                     for(int r=0;r<aTableData[0].length;r++){

                            v.add("<tr onmouseover=\"this.style.backgroundColor='#f2f2f2'\" style=\"CURSOR: hand\" onmouseout=\"this.style.backgroundColor=''\" align=middle>");

                            if(isChoose){

                                  

                                   v.add("<td>"+getChooseStyle(aTableData[0][r])+"</td>");

                            }

                                         

                                          v.add("<td>"+ (r+1) +"</td>");     //序列

                                   for(int c=0;c<aTableData.length;c++){

                                          v.add("<td>"+ aTableData[c][r] +"</td>");

                                   }

/*                               

                            if(isEdit){

                                   //v.add("<td><a href=\"javascript:OpenDialog('http://localhost:8080/autosite/member/"+strEditLink+aTableData[0][r]+"')\">编辑</a></td>");

                                   v.add("<td><a href="+strEditLink+aTableData[0][r]+">编辑</a></td>");

                            }

                            if(isDelete){

                                   //v.add("<td><input type=\"button\" name=\"Delete\" value=\"删除\" onclick=\"javascript:mysubmit('del_selected')\"></td>");

                                   //v.add("<td><a href="+strDeleteLink+aTableData[0][r]+">删除</a></td>"); //onclick=\"javascript:mysubmit('del_selected')\"

                                   v.add("<td><a href="+this.getDeleteLink(strDeleteLink+aTableData[0][r])+">删除</a></td>"); //onclick=\"javascript:mysubmit('del_selected')\"

                            }

*/                        

                            v.add("</tr> \n");

                     }

                     v.add("</table> \n");

                     v.add("<BR>");

                     //====================================================================================

                     v.add("<table border=1 style='border-collapse: collapse' bordercolor='#111111' cellpadding='2' align=right> \n");

                     v.add("<tr>");

                     v.add("<td>"+ this.getRowCount() +"</td>");

                    

                     if(page == 0){

                            v.add("<td><font face='Webdings' size='4'>7</font></td>");

                            v.add("<td><font face='Webdings' size='4'>3</font></td>");

                     }else{

                            v.add("<td><a href='?page=0'><font face='Webdings' size='4'>7</font></a></td>");

                            v.add("<td><a href='?order="+order+"&seq="+old_seq+"&page="+ (page-1) +"'><font face='Webdings' size='4'>3</font></a></td>");

                     }

                     int pagecount = 0;

                     if(this.getRowCount()%this.getLimit() == 0){

                            pagecount = this.getRowCount()/this.getLimit();

                     }else{

                            pagecount = this.getRowCount()/this.getLimit()+1;

                     }

                    

                     v.add("<td>");

                            v.add("<select name='page' id='page' size=0 onChange=window.location.href='?page='+this.options[this.selectedIndex].value> \n");

                            v.add("<option value='"+page+"' selected>["+(page+1)+"]</option>");     

                            for(int i=0;i<pagecount;i++){

                                   v.add("<option value='"+i+"'>"+(i+1)+"</option>");

                            }

                            v.add("</select> \n");

                     v.add("</td>");

                    

                     if(page+1 == pagecount){

                            v.add("<td><font face='Webdings' size='4'>4</font></td>");

                            v.add("<td><font face='Webdings' size='4'>8</font></td>");

                     }else{

                            v.add("<td><a href='?order="+order+"&seq="+old_seq+"&page="+ (page+1) +"'><font face='Webdings' size='4'>4</font></a></td>");

                            v.add("<td><a href='?page="+ (pagecount-1) +"'><font face='Webdings' size='4'>8</font></a></td>");

                     }

                    

                     v.add("<td>"+ (page+1) + "/" + pagecount +"</td>");

                     /* --------------------- Begin Filter ------------------ */

                     if(this.getFilter()){

                            v.add("<td> &nbsp;&nbsp;&nbsp;&nbsp; </td>");

                            v.add("<td>筛选</td>");

                            v.add("<td>");

                            v.add("<select name='field' id='field'> \n");

                            v.add("<option value='"+this.getTableHeader()[0]+"' selected>"+this.getTableHeader()[0]+"</option> \n");

                            for(int i=1;i<this.getTableHeader().length;i++){

                                   v.add("<option value='"+this.getTableHeader()[i]+"'>"+this.getTableHeader()[i]+"</option> \n");

                            }

                            v.add("</select> \n");

                            v.add("</td>");

                            v.add("<td>");

                            v.add("<select name='condition' id='condition'> \n");

                                   v.add("<option value='like' selected>模糊</option> \n");

                                   v.add("<option value='='>=</option> \n");

                                   v.add("<option value='!='></option> \n");

                                   v.add("<option value='>'>></option> \n");

                                   v.add("<option value='>='>>=</option> \n");

                                   v.add("<option value='<'><</option> \n");

                                   v.add("<option value='<='><=</option> \n");

                            v.add("</select> \n");

                            v.add("</td>");

                            v.add("<td>");

                            v.add("<input name='val' type='text' id='val'>");

                            v.add("</td>");

                            v.add("<td>");

                            v.add("<input type='submit' name='Submit' value=' 查询 '>");

                            v.add("</td>");

                     }

                     /* --------------------- End Filter ------------------ */

                     v.add("</tr>");

                     v.add("</table> \n");

              }

              catch(Exception e){

                     e.printStackTrace();

              }

              finally{

                     try{

                     }catch(Exception e){

                            e.printStackTrace();

                     }

              }

              return v;

       }

      

       public Vector getHtmlTables(int page,int limit,String order,String seq,String sql){

              this.setSQL(sql);

              this.setChoose(true,RADIO);

//            this.setEdit(true,"?op=edit&id=");

//            this.setDelete(true,"?op=delete&id=");

              return MakeHtmlTable(page,limit,order,seq);

       }

      

       //public void close() throws Exception {}

       public void clear(){}

       public void close(){

              try{

                     if(rs != null)rs.close();

                     dbc.close();

                     vError.add("close()");

              }catch(Exception e){

                     vError.add(e.toString());

              }

       }

    public void getException(){

        AnalyseException ae = new AnalyseException(this.vError);

        try{

               pageContext.getOut().print(ae.getException());

        }catch(Exception e){}

        System.out.println(ae.getException());

    }

          

       public static void main(String[] args) {

              BaseTable t = new BaseTable();

              //System.out.println(t.getCount("oa.away"));

              String sql = "select * from btob.supply_demand";

              //System.out.println(t.sqlAnalyzer("select id,subject,docfrom,created,type From oa.vdocument Where pid=38 limit 10 offset 0"));

      

              //t.getHtmlTable()

              t.setSQL(sql);

              try{

                     ResultSet rs = t.TableResultSet();

                     while(rs.next()){

                            System.out.println(rs.getString(1));     

                     }

              }catch(SQLException e){

                     System.out.println(e.toString());

              }

/*          

              t.setWhere("id like '%4%'");

              t.setLimit(2);

              t.setPage(0);

              t.setHtmlTable("border=0");

              t.setHtmlTr("bgcolor=#FF0000");

              t.setHtmlTd("bordercolor=#0000FF");

              t.setRowHeight(50);

              t.setRowWidth(100);

              t.setBorder(10);

              String head[]={"序号","aaa","bbb","ccc","ddd"};

              t.setTableHeader(head);

 

              t.setEdit(true,"?op=edit&id=");

              t.setDelete(true,"?op=delete&id=");

              t.setHideColumn(1);

              t.setHtmlColumn(2,"<font color=blue>","</font>");

              //t.setHtmlColumn(3,"<font color=blue>","</font>");

              t.setHtmlColumn(5,"<font color=blue>","</font>");

              t.addHtmlColumn(3,"<a target=meeting href='details.jsp?id=","id","'>","subject","</a>");

              t.setHtmlColumn(4,"<a href='?id=","id","'>","</a>");

              Vector v = t.MakeHtmlTable();

              for(int i=0;i<v.size();i++){

                     //System.out.print(v.get(i));

              }

*/          

//            v = t.getFilterControl();

//            for(int i=0;i<v.size();i++){

//                   System.out.print(v.get(i));

//            }

              //t.getFilterControl();

              t.getException();

             

       }    

}

 

13.5.5 什么时候应该把文件存在数据库中

关于这个问题网上讨论的贴子很多……

将文件存在数据中优势:

n         至少要比放在磁盘上安全一些

用户如果想出得数据库存储的文件,第一关就是连接数据库。这要提供用户,密码。

可以通过SSL访问数据库,这样更加安全。

n         数据完整

当记录删除时,文件也同时被删除,通过事务处理,可以完好的保持数据的完整,而磁盘文件系统不行。磁盘文件系统也不支持事务。

n         不会被病毒感染

关于性能:

n         不用说就应该知道比文件系统要慢

但只要何理使用,可能效率更高一些。不要在频繁读写操作的环境使用。

n         存放文件大小要看你的需求

你的数据库用户很多,如果文件很大。就需要长时间读取,这会站用宝贵数据库连接。

 

下面是一个将图片存入数据库的例子:

数据库结构

DROP TABLE images;

CREATE TABLE images (

       id Serial NOT NULL UNIQUE,

       filename varchar(255) NOT NULL Default 'unknown',

      img bytea,

      size Integer NOT NULL Default '0',

    created    Timestamp Default current_timestamp::timestamp (0) without time zone,

    modified Timestamp Default current_timestamp::timestamp (0) without time zone,

    PRIMARY KEY ("id")

);

 

JSP程序

<%@ page contentType="text/html; charset=utf-8" language="java" import="java.sql.*" errorPage="" %>

<%@ page import="java.util.*"%>

<%@ page import="java.io.*"%>

<jsp:useBean id="test" scope="page" class="netkiller.database.DBConnect"/>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<title>Untitled Document</title>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

</head>

 

<body>

<%

              try{

                    

                     File file = new File("/tmp/1078215958235.jpg");

                     FileInputStream  fis = new  FileInputStream(file);

 

                     test.prepareStatement("insert into images(filename,img) values(?,?)");

                     test.setString(1,file.getName());

                     test.setBinaryStream(2,fis,fis.available());

                     System.out.println(test.executeUpdate());

                     fis.close();

                    

                     test.prepareStatement("select * from images");

                     ResultSet rs = test.executeQuery();            

                     if(rs!=null) {

                            while(rs.next()){

                                   String filename = rs.getString("filename");

                                   FileOutputStream file1 = new FileOutputStream("/var/www/html/webapps/tmp/"+filename);

                                   byte[] imgBytes = rs.getBytes("img");

                                   file1.write(imgBytes);

                                   file1.close();

                                   out.print("<img src="+filename+">");

                            }

                     }

                     test.close();

              }catch(Exception e)       {

                     e.printStackTrace();

              }

 

%>

</body>

</html>

 

 

14             PHP

14.1       PHP 连接PostgreSQL

编译PHP时请加 --with-pgsql 选项:

    tar zxf php-?.?.?.tar.gz

    cd php-?.?.?

    ./configure --prefix=/usr/local/php --with-apxs=/usr/local/apache/bin/apxs \

        --with-config-file-path=/usr/local/etc --enable-track-vars --with-xml \

        --with-pgsql --with-mysql \

       --with-ldap --enable-ftp --with-openssl --with-iconv --with-kerberos \

       --with-java=/usr/local/java

    make

    make install

    cp php.ini-dist /usr/local/etc/php.ini

 

RPM安装,请确认是否已经安装了php-pgsql包。

[root@linux root]# rpm -qa |grep php

php-imap-4.3.4-1.1

php-4.3.4-1.1

php-snmp-4.3.4-1.1

php-devel-4.3.4-1.1

php-mysql-4.3.4-1.1

php-xmlrpc-4.3.4-1.1

php-domxml-4.3.4-1.1

php-odbc-4.3.4-1.1

php-pgsql-4.3.4-1.1

php-ldap-4.3.4-1.1

[root@linux root]#

 

14.2       set CLIENT_ENCODING TO 'GB18030';方案

PHP 连接PostgreSQL数据库,我是使用PHPBB提供的Class,只要稍加改造就可很好支持UNICODE。注意下面的红色代码!

<?php

  /***************************************************************************

   *                               postgres7.php

   *                            -------------------

   *   begin                : Saturday, Feb 13, 2001

   *   copyright            : (C) 2001 The phpBB Group

   *   email                : supportphpbb.com

   *

   *   $Id: postgres7.php,v 1.19 2002/03/05 02:19:38 psotfx Exp $

   *

   ***************************************************************************/

 

/***************************************************************************

 *

 *   This program is free software; you can redistribute it and/or modify

 *   it under the terms of the GNU General Public License as published by

 *   the Free Software Foundation; either version 2 of the License, or

 *   (at your option) any later version.

 *

 ***************************************************************************/

 

if(!defined("SQL_LAYER"))

{

 

define("SQL_LAYER","postgresql");

 

class sql_db

{

 

       var $db_connect_id;

       var $query_result;

       var $in_transaction = 0;

       var $row = array();

       var $rowset = array();

       var $rownum = array();

       var $num_queries = 0;

 

       //

       // Constructor

       //

       function sql_db($sqlserver, $sqluser, $sqlpassword, $database, $persistency = true)

       {

              $this->connect_string = "";

 

              if( $sqluser )

              {

                     $this->connect_string .= "user=$sqluser ";

              }

 

              if( $sqlpassword )

              {

                     $this->connect_string .= "password=$sqlpassword ";

              }

 

              if( $sqlserver )

              {

                     if( ereg(":", $sqlserver) )

                     {

                            list($sqlserver, $sqlport) = split(":", $sqlserver);

                            $this->connect_string .= "host=$sqlserver port=$sqlport ";

                     }

                     else

                     {

                            if( $sqlserver != "localhost" )

                            {

                                   $this->connect_string .= "host=$sqlserver ";

                            }

                     }

              }

 

              if( $database )

              {

                     $this->dbname = $database;

                     $this->connect_string .= "dbname=$database";

              }

 

              $this->persistency = $persistency;

 

              $this->db_connect_id = ( $this->persistency ) ? pg_pconnect($this->connect_string) : pg_connect($this->connect_string);

 

              return ( $this->db_connect_id ) ? $this->db_connect_id : false;

       }

 

       //

       // Other base methods

       //

       function sql_close()

       {

              if( $this->db_connect_id )

              {

                     //

                     // Commit any remaining transactions

                     //

                     if( $this->in_transaction )

                     {

                            @pg_exec($this->db_connect_id, "COMMIT");

                     }

 

                     if( $this->query_result )

                     {

                            @pg_freeresult($this->query_result);

                     }

 

                     return @pg_close($this->db_connect_id);

              }

              else

              {

                     return false;

              }

       }

 

       //

       // Query method

       //

       function sql_query($query = "", $transaction = false)

       {

              //

              // Remove any pre-existing queries

              //

              unset($this->query_result);

              if( $query != "" )

              {

                     $this->num_queries++;

 

                     $query = preg_replace("/LIMIT ([0-9]+),([ 0-9]+)/", "LIMIT \\2 OFFSET \\1", $query);

$encoding  = " set CLIENT_ENCODING TO 'GB18030';";

//$encoding  = "SET CLIENT_ENCODING TO 'GBK'"; 也可以

                     $this->query_result = @pg_exec($this->db_connect_id, $encoding);

 

                     if( $transaction == BEGIN_TRANSACTION && !$this->in_transaction )

                     {

                            $this->in_transaction = TRUE;

 

                            if( !@pg_exec($this->db_connect_id, "BEGIN") )

                            {

                                   return false;

                            }

                     }

 

                     $this->query_result = @pg_exec($this->db_connect_id, $query);

                     if( $this->query_result )

                     {

                            if( $transaction == END_TRANSACTION )

                            {

                                   $this->in_transaction = FALSE;

 

                                   if( !@pg_exec($this->db_connect_id, "COMMIT") )

                                   {

                                          @pg_exec($this->db_connect_id, "ROLLBACK");

                                          return false;

                                   }

                            }

 

                            $this->last_query_text[$this->query_result] = $query;

                            $this->rownum[$this->query_result] = 0;

 

                            unset($this->row[$this->query_result]);

                            unset($this->rowset[$this->query_result]);

 

                            return $this->query_result;

                     }

                     else

                     {

                            if( $this->in_transaction )

                            {

                                   @pg_exec($this->db_connect_id, "ROLLBACK");

                            }

                            $this->in_transaction = FALSE;

 

                            return false;

                     }

              }

              else

              {

                     if( $transaction == END_TRANSACTION && $this->in_transaction )

                     {

                            $this->in_transaction = FALSE;

 

                            if( !@pg_exec($this->db_connect_id, "COMMIT") )

                            {

                                   @pg_exec($this->db_connect_id, "ROLLBACK");

                                   return false;

                            }

                     }

 

                     return true;

              }

       }

 

       //

       // Other query methods

       //

       function sql_numrows($query_id = 0)

       {

              if( !$query_id )

              {

                     $query_id = $this->query_result;

              }

 

              return ( $query_id ) ? @pg_numrows($query_id) : false;

       }

 

       function sql_numfields($query_id = 0)

       {

              if( !$query_id )

              {

                     $query_id = $this->query_result;

              }

 

              return ( $query_id ) ? @pg_numfields($query_id) : false;

       }

 

       function sql_fieldname($offset, $query_id = 0)

       {

              if( !$query_id )

              {

                     $query_id = $this->query_result;

              }

 

              return ( $query_id ) ? @pg_fieldname($query_id, $offset) : false;

       }

 

       function sql_fieldtype($offset, $query_id = 0)

       {

              if( !$query_id )

              {

                     $query_id = $this->query_result;

              }

 

              return ( $query_id ) ? @pg_fieldtype($query_id, $offset) : false;

       }

 

       function sql_fetchrow($query_id = 0)

       {

              if( !$query_id )

              {

                     $query_id = $this->query_result;

              }

 

              if($query_id)

              {

                     $this->row = @pg_fetch_array($query_id, $this->rownum[$query_id]);

 

                     if( $this->row )

                     {

                            $this->rownum[$query_id]++;

                            return $this->row;

                     }

              }

 

              return false;

       }

 

       function sql_fetchrowset($query_id = 0)

       {

              if( !$query_id )

              {

                     $query_id = $this->query_result;

              }

 

              if( $query_id )

              {

                     unset($this->rowset[$query_id]);

                     unset($this->row[$query_id]);

                     $this->rownum[$query_id] = 0;

 

                     while( $this->rowset = @pg_fetch_array($query_id, $this->rownum[$query_id], PGSQL_ASSOC) )

                     {

                            $result[] = $this->rowset;

                            $this->rownum[$query_id]++;

                     }

 

                     return $result;

              }

 

              return false;

       }

 

       function sql_fetchfield($field, $row_offset=-1, $query_id = 0)

       {

              if( !$query_id )

              {

                     $query_id = $this->query_result;

              }

 

              if( $query_id )

              {

                     if( $row_offset != -1 )

                     {

                            $this->row = @pg_fetch_array($query_id, $row_offset, PGSQL_ASSOC);

                     }

                     else

                     {

                            if( $this->rownum[$query_id] )

                            {

                                   $this->row = @pg_fetch_array($query_id, $this->rownum[$query_id]-1, PGSQL_ASSOC);

                            }

                            else

                            {

                                   $this->row = @pg_fetch_array($query_id, $this->rownum[$query_id], PGSQL_ASSOC);

 

                                   if( $this->row )

                                   {

                                          $this->rownum[$query_id]++;

                                   }

                            }

                     }

 

                     return $this->row[$field];

              }

 

              return false;

       }

 

       function sql_rowseek($offset, $query_id = 0)

       {

 

              if(!$query_id)

              {

                     $query_id = $this->query_result;

              }

 

              if( $query_id )

              {

                     if( $offset > -1 )

                     {

                            $this->rownum[$query_id] = $offset;

                            return true;

                     }

                     else

                     {

                            return false;

                     }

              }

 

              return false;

       }

 

       function sql_nextid()

       {

              $query_id = $this->query_result;

 

              if($query_id && $this->last_query_text[$query_id] != "")

              {

                     if( preg_match("/^INSERT[\t\n ]+INTO[\t\n ]+([a-z0-9\_\-]+)/is", $this->last_query_text[$query_id], $tablename) )

                     {

                            $query = "SELECT currval('" . $tablename[1] . "_id_seq') AS last_value";

                            $temp_q_id =  @pg_exec($this->db_connect_id, $query);

                            if( !$temp_q_id )

                            {

                                   return false;

                            }

 

                            $temp_result = @pg_fetch_array($temp_q_id, 0, PGSQL_ASSOC);

 

                            return ( $temp_result ) ? $temp_result['last_value'] : false;

                     }

              }

 

              return false;

       }

 

       function sql_affectedrows($query_id = 0)

       {

              if( !$query_id )

              {

                     $query_id = $this->query_result;

              }

 

              return ( $query_id ) ? @pg_cmdtuples($query_id) : false;

       }

 

       function sql_freeresult($query_id = 0)

       {

              if( !$query_id )

              {

                     $query_id = $this->query_result;

              }

 

              return ( $query_id ) ? @pg_freeresult($query_id) : false;

       }

 

       function sql_error($query_id = 0)

       {

              if( !$query_id )

              {

                     $query_id = $this->query_result;

              }

 

              $result['message'] = @pg_errormessage($this->db_connect_id);

              $result['code'] = -1;

 

              return $result;

       }

 

} // class ... db_sql

 

} // if ... defined

 

?>

注:SET CLIENT_ENCODING TO 'value'; value是:

EUC_JP, SJIS, EUC_KR, UHC, JOHAB, EUC_CN, GBK, EUC_TW, BIG5, LATIN1 to LATIN10, ISO_8859_5, ISO_8859_6, ISO_8859_7, ISO_8859_8, WIN, ALT, KOI8, WIN1256, TCVN, WIN874, GB18030, WIN1250

例表中没有GB2312SET CLIENT_ENCODING TO 'GB2312'这样操作不会返回错误:

member=> SET CLIENT_ENCODING TO 'GB2312';

ERROR:  invalid value for option 'client_encoding': 'GB2312'

member=>

$encoding  = " set CLIENT_ENCODING TO 'GB18030';"; set CLIENT_ENCODING TO 'GB18030'尾部的“;”符号加不加都可以。

14.3       convert()方案

另一种方法是使用convert()函数:

select convert(描述,'UNICODE','GBK')as desc from ;

select convert(组名 using utf_8_to_gb18030) from ;

14.4       PHP iconv() 函数方案

在数据外部转码,使用PHP提供的iconv()函数来完成。

注!安装编译PHP时要加入--with-iconv模块。

function addUser($user,$passwd,$name,$nickname,$active="false",$email){

       global $db;

       $name = iconv( 'GB2312','UTF-8', $name );

       $sql = "insert into \"user\"(userid,passwd,name,nickname,active,email,question,answer) values('$user','$passwd','$name','$nickname','$active','$email','question','answer')";

       if ( !($result = $db->sql_query($sql)) ){

              message_die(GENERAL_ERROR, 'Error in obtaining userdata', '', __LINE__, __FILE__, $sql);

       }

};

 

function getUserInfo($uid){

       global $db;

       $sql = "select * from \"user\" where userid='$uid'";

      

//     $codesql = "set CLIENT_ENCODING TO 'EUC_CN';";

//     $codesql = "set CLIENT_ENCODING TO 'BIG5';";

//     $codesql = "set CLIENT_ENCODING TO 'GB18030';";

       $db->sql_query($codesql);

      

       if ( !($result = $db->sql_query($sql)) ){

              message_die(GENERAL_ERROR, 'Could not \'select\' userdata', '', __LINE__, __FILE__, $sql);

       }

       $count=$db->sql_numrows();

      

       for ($i=0;$i<$count;$i++){

              if( $row = $db->sql_fetchrow($result) ){

                     $tmp[0] = $row[0];

                     $tmp[1] = $row[1];

                     $tmp[2] = $row[2];

                     $tmp[3] = iconv( 'UTF-8', 'GBK', $row[3] );

//                   $tmp[3] = $row[3];

                     $tmp[4] = $row[4];

                     $tmp[5] = $row[5];

                     $tmp[6] = $row[6];

                     $tmp[7] = $row[7];

                     $tmp[8] = $row[8];

                     $tmp[9] = $row[9];

                     $tmp[10] = $row[10];

              }

       }

       return $tmp;  

};

14.5       在标准I/O上使用 Linux iconv 命令方案

Iconv也是一个Linux提供的命令:

[root@linux script]# iconv --help

Usage: iconv [OPTION...] [FILE...]

Convert encoding of given files from one encoding to another.

 

 Input/Output format specification:

  -f, --from-code=NAME       encoding of original text

  -t, --to-code=NAME         encoding for output

 

 Information:

  -l, --list                 list all known coded character sets

 

 Output control:

  -c                         omit invalid characters from output

  -o, --output=FILE          output file

  -s, --silent               suppress warnings

      --verbose              print progress information

 

  -?, --help                 Give this help list

      --usage                Give a short usage message

  -V, --version              Print program version

 

Mandatory or optional arguments to long options are also mandatory or optional

for any corresponding short options.

 

Report bugs using the `glibcbug' script to <bugs@gnu.org>.

 

使用方法

[root@linux script]# iconv -f gb2312 -t big5 /tmp/gb.txt -o /tmp/big5.txt

 

如果你的PHP编译安装时没有加入--with-iconv模块。你又不想重新编译它,可以通过管道来调用LINUX iconv 命令,从标准I/O上(输入/输出)的返回数据。

 

       function iconvs($from,$to,$gb){

              $fp = popen( "echo \"$gb\" | iconv -f $from -t $to", "r" );

              while (!feof($fp)) {

                     $buffer .= fgets($fp, 4096);

              }

              pclose($fp);

              return $buffer;

       }

      

       function gb18030_utf8($gb){

              $encode = $this->iconvs("GB18030","UTF-8",$gb);

              return $encode;     

       }

      

       function utf8_gb18030($gb){

              $encode = $this->iconvs("UTF-8","GB18030",$gb);

              return $encode;                   

       }

iconv 支持字符集列表:

[root@linux script]# iconv -l

The following list contain all the coded character sets known.  This does

not necessarily mean that all combinations of these names can be used for

the FROM and TO command line parameters.  One coded character set can be

listed with several different names (aliases).

 

  437, 500, 500V1, 850, 851, 852, 855, 856, 857, 860, 861, 862, 863, 864, 865,

  866, 869, 874, 904, 1026, 1046, 1047, 8859_1, 8859_2, 8859_3, 8859_4, 8859_5,

  8859_6, 8859_7, 8859_8, 8859_9, 10646-1:1993, 10646-1:1993/UCS4,

  ANSI_X3.4-1968, ANSI_X3.4-1986, ANSI_X3.4, ANSI_X3.110-1983, ANSI_X3.110,

  ARABIC, ARABIC7, ARMSCII-8, ASCII, ASMO-708, ASMO_449, BALTIC, BIG-5,

  BIG-FIVE, BIG5-HKSCS, BIG5, BIG5HKSCS, BIGFIVE, BS_4730, CA, CN-BIG5, CN-GB,

  CN, CP-AR, CP-GR, CP-HU, CP037, CP038, CP273, CP274, CP275, CP278, CP280,

  CP281, CP282, CP284, CP285, CP290, CP297, CP367, CP420, CP423, CP424, CP437,

  CP500, CP737, CP775, CP813, CP819, CP850, CP851, CP852, CP855, CP856, CP857,

  CP860, CP861, CP862, CP863, CP864, CP865, CP866, CP868, CP869, CP870, CP871,

  CP874, CP875, CP880, CP891, CP903, CP904, CP905, CP912, CP915, CP916, CP918,

  CP920, CP922, CP930, CP932, CP933, CP935, CP936, CP937, CP939, CP949, CP950,

  CP1004, CP1026, CP1046, CP1047, CP1070, CP1079, CP1081, CP1084, CP1089,

  CP1124, CP1129, CP1132, CP1133, CP1160, CP1161, CP1162, CP1163, CP1164,

  CP1250, CP1251, CP1252, CP1253, CP1254, CP1255, CP1256, CP1257, CP1258,

  CP1361, CP10007, CPIBM861, CSA7-1, CSA7-2, CSASCII, CSA_T500-1983, CSA_T500,

  CSA_Z243.4-1985-1, CSA_Z243.4-1985-2, CSA_Z243.419851, CSA_Z243.419852,

  CSDECMCS, CSEBCDICATDE, CSEBCDICATDEA, CSEBCDICCAFR, CSEBCDICDKNO,

  CSEBCDICDKNOA, CSEBCDICES, CSEBCDICESA, CSEBCDICESS, CSEBCDICFISE,

  CSEBCDICFISEA, CSEBCDICFR, CSEBCDICIT, CSEBCDICPT, CSEBCDICUK, CSEBCDICUS,

  CSEUCKR, CSEUCPKDFMTJAPANESE, CSGB2312, CSHPROMAN8, CSIBM037, CSIBM038,

  CSIBM273, CSIBM274, CSIBM275, CSIBM277, CSIBM278, CSIBM280, CSIBM281,

  CSIBM284, CSIBM285, CSIBM290, CSIBM297, CSIBM420, CSIBM423, CSIBM424,

  CSIBM500, CSIBM851, CSIBM855, CSIBM856, CSIBM857, CSIBM860, CSIBM863,

  CSIBM864, CSIBM865, CSIBM866, CSIBM868, CSIBM869, CSIBM870, CSIBM871,

  CSIBM880, CSIBM891, CSIBM903, CSIBM904, CSIBM905, CSIBM918, CSIBM922,

  CSIBM930, CSIBM932, CSIBM933, CSIBM935, CSIBM937, CSIBM939, CSIBM943,

  CSIBM1026, CSIBM1124, CSIBM1129, CSIBM1132, CSIBM1133, CSIBM1160, CSIBM1161,

  CSIBM1163, CSIBM1164, CSIBM11621162, CSISO4UNITEDKINGDOM, CSISO10SWEDISH,

  CSISO11SWEDISHFORNAMES, CSISO14JISC6220RO, CSISO15ITALIAN, CSISO16PORTUGESE,

  CSISO17SPANISH, CSISO18GREEK7OLD, CSISO19LATINGREEK, CSISO21GERMAN,

  CSISO25FRENCH, CSISO27LATINGREEK1, CSISO49INIS, CSISO50INIS8,

  CSISO51INISCYRILLIC, CSISO58GB1988, CSISO60DANISHNORWEGIAN,

  CSISO60NORWEGIAN1, CSISO61NORWEGIAN2, CSISO69FRENCH, CSISO84PORTUGUESE2,

  CSISO85SPANISH2, CSISO86HUNGARIAN, CSISO88GREEK7, CSISO89ASMO449, CSISO90,

  CSISO92JISC62991984B, CSISO99NAPLPS, CSISO103T618BIT, CSISO111ECMACYRILLIC,

  CSISO121CANADIAN1, CSISO122CANADIAN2, CSISO139CSN369103, CSISO141JUSIB1002,

  CSISO143IECP271, CSISO150, CSISO150GREEKCCITT, CSISO151CUBA,

  CSISO153GOST1976874, CSISO646DANISH, CSISO2022CN, CSISO2022JP, CSISO2022JP2,

  CSISO2022KR, CSISO2033, CSISO5427CYRILLIC, CSISO5427CYRILLIC1981,

  CSISO5428GREEK, CSISO10367BOX, CSISOLATIN1, CSISOLATIN2, CSISOLATIN3,

  CSISOLATIN4, CSISOLATIN5, CSISOLATIN6, CSISOLATINARABIC, CSISOLATINCYRILLIC,

  CSISOLATINGREEK, CSISOLATINHEBREW, CSKOI8R, CSKSC5636, CSMACINTOSH,

  CSNATSDANO, CSNATSSEFI, CSN_369103, CSPC8CODEPAGE437, CSPC775BALTIC,

  CSPC850MULTILINGUAL, CSPC862LATINHEBREW, CSPCP852, CSSHIFTJIS, CSUCS4,

  CSUNICODE, CUBA, CWI-2, CWI, CYRILLIC, DE, DEC-MCS, DEC, DECMCS, DIN_66003,

  DK, DS2089, DS_2089, E13B, EBCDIC-AT-DE-A, EBCDIC-AT-DE, EBCDIC-BE,

  EBCDIC-BR, EBCDIC-CA-FR, EBCDIC-CP-AR1, EBCDIC-CP-AR2, EBCDIC-CP-BE,

  EBCDIC-CP-CA, EBCDIC-CP-CH, EBCDIC-CP-DK, EBCDIC-CP-ES, EBCDIC-CP-FI,

  EBCDIC-CP-FR, EBCDIC-CP-GB, EBCDIC-CP-GR, EBCDIC-CP-HE, EBCDIC-CP-IS,

  EBCDIC-CP-IT, EBCDIC-CP-NL, EBCDIC-CP-NO, EBCDIC-CP-ROECE, EBCDIC-CP-SE,

  EBCDIC-CP-TR, EBCDIC-CP-US, EBCDIC-CP-WT, EBCDIC-CP-YU, EBCDIC-CYRILLIC,

  EBCDIC-DK-NO-A, EBCDIC-DK-NO, EBCDIC-ES-A, EBCDIC-ES-S, EBCDIC-ES,

  EBCDIC-FI-SE-A, EBCDIC-FI-SE, EBCDIC-FR, EBCDIC-GREEK, EBCDIC-INT,

  EBCDIC-INT1, EBCDIC-IS-FRISS, EBCDIC-IT, EBCDIC-JP-E, EBCDIC-JP-KANA,

  EBCDIC-PT, EBCDIC-UK, EBCDIC-US, EBCDICATDE, EBCDICATDEA, EBCDICCAFR,

  EBCDICDKNO, EBCDICDKNOA, EBCDICES, EBCDICESA, EBCDICESS, EBCDICFISE,

  EBCDICFISEA, EBCDICFR, EBCDICISFRISS, EBCDICIT, EBCDICPT, EBCDICUK, EBCDICUS,

  ECMA-114, ECMA-118, ECMA-128, ECMA-CYRILLIC, ECMACYRILLIC, ELOT_928, ES, ES2,

  EUC-CN, EUC-JISX0213, EUC-JP, EUC-KR, EUC-TW, EUCCN, EUCJP, EUCKR, EUCTW, FI,

  FR, GB, GB2312, GB13000, GB18030, GBK, GB_1988-80, GB_198880,

  GEORGIAN-ACADEMY, GEORGIAN-PS, GOST_19768-74, GOST_19768, GOST_1976874,

  GREEK-CCITT, GREEK, GREEK7-OLD, GREEK7, GREEK7OLD, GREEK8, GREEKCCITT,

  HEBREW, HP-ROMAN8, HPROMAN8, HU, IBM-856, IBM-922, IBM-930, IBM-932, IBM-933,

  IBM-935, IBM-937, IBM-939, IBM-943, IBM-1046, IBM-1124, IBM-1129, IBM-1132,

  IBM-1133, IBM-1160, IBM-1161, IBM-1162, IBM-1163, IBM-1164, IBM037, IBM038,

  IBM256, IBM273, IBM274, IBM275, IBM277, IBM278, IBM280, IBM281, IBM284,

  IBM285, IBM290, IBM297, IBM367, IBM420, IBM423, IBM424, IBM437, IBM500,

  IBM775, IBM813, IBM819, IBM850, IBM851, IBM852, IBM855, IBM856, IBM857,

  IBM860, IBM861, IBM862, IBM863, IBM864, IBM865, IBM866, IBM868, IBM869,

  IBM870, IBM871, IBM874, IBM875, IBM880, IBM891, IBM903, IBM904, IBM905,

  IBM912, IBM915, IBM916, IBM918, IBM920, IBM922, IBM930, IBM932, IBM933,

  IBM935, IBM937, IBM939, IBM943, IBM1004, IBM1026, IBM1046, IBM1047, IBM1089,

  IBM1124, IBM1129, IBM1132, IBM1133, IBM1160, IBM1161, IBM1162, IBM1163,

  IBM1164, IEC_P27-1, IEC_P271, INIS-8, INIS-CYRILLIC, INIS, INIS8,

  INISCYRILLIC, ISIRI-3342, ISIRI3342, ISO-2022-CN-EXT, ISO-2022-CN,

  ISO-2022-JP-2, ISO-2022-JP-3, ISO-2022-JP, ISO-2022-KR, ISO-8859-1,

  ISO-8859-2, ISO-8859-3, ISO-8859-4, ISO-8859-5, ISO-8859-6, ISO-8859-7,

  ISO-8859-8, ISO-8859-9, ISO-8859-10, ISO-8859-11, ISO-8859-13, ISO-8859-14,

  ISO-8859-15, ISO-8859-16, ISO-10646, ISO-10646/UCS2, ISO-10646/UCS4,

  ISO-10646/UTF-8, ISO-10646/UTF8, ISO-CELTIC, ISO-IR-4, ISO-IR-6, ISO-IR-8-1,

  ISO-IR-9-1, ISO-IR-10, ISO-IR-11, ISO-IR-14, ISO-IR-15, ISO-IR-16, ISO-IR-17,

  ISO-IR-18, ISO-IR-19, ISO-IR-21, ISO-IR-25, ISO-IR-27, ISO-IR-37, ISO-IR-49,

  ISO-IR-50, ISO-IR-51, ISO-IR-54, ISO-IR-55, ISO-IR-57, ISO-IR-60, ISO-IR-61,

  ISO-IR-69, ISO-IR-84, ISO-IR-85, ISO-IR-86, ISO-IR-88, ISO-IR-89, ISO-IR-90,

  ISO-IR-92, ISO-IR-98, ISO-IR-99, ISO-IR-100, ISO-IR-101, ISO-IR-103,

  ISO-IR-109, ISO-IR-110, ISO-IR-111, ISO-IR-121, ISO-IR-122, ISO-IR-126,

  ISO-IR-127, ISO-IR-138, ISO-IR-139, ISO-IR-141, ISO-IR-143, ISO-IR-144,

  ISO-IR-148, ISO-IR-150, ISO-IR-151, ISO-IR-153, ISO-IR-155, ISO-IR-156,

  ISO-IR-157, ISO-IR-166, ISO-IR-179, ISO-IR-193, ISO-IR-197, ISO-IR-199,

  ISO-IR-203, ISO-IR-209, ISO-IR-226, ISO646-CA, ISO646-CA2, ISO646-CN,

  ISO646-CU, ISO646-DE, ISO646-DK, ISO646-ES, ISO646-ES2, ISO646-FI, ISO646-FR,

  ISO646-FR1, ISO646-GB, ISO646-HU, ISO646-IT, ISO646-JP-OCR-B, ISO646-JP,

  ISO646-KR, ISO646-NO, ISO646-NO2, ISO646-PT, ISO646-PT2, ISO646-SE,

  ISO646-SE2, ISO646-US, ISO646-YU, ISO2022CN, ISO2022CNEXT, ISO2022JP,

  ISO2022JP2, ISO2022KR, ISO6937, ISO8859-1, ISO8859-2, ISO8859-3, ISO8859-4,

  ISO8859-5, ISO8859-6, ISO8859-7, ISO8859-8, ISO8859-9, ISO8859-10,

  ISO8859-11, ISO8859-13, ISO8859-14, ISO8859-15, ISO8859-16, ISO88591,

  ISO88592, ISO88593, ISO88594, ISO88595, ISO88596, ISO88597, ISO88598,

  ISO88599, ISO885910, ISO885911, ISO885913, ISO885914, ISO885915, ISO885916,

  ISO_646.IRV:1991, ISO_2033-1983, ISO_2033, ISO_5427-EXT, ISO_5427,

  ISO_5427:1981, ISO_5427EXT, ISO_5428, ISO_5428:1980, ISO_6937-2,

  ISO_6937-2:1983, ISO_6937, ISO_6937:1992, ISO_8859-1, ISO_8859-1:1987,

  ISO_8859-2, ISO_8859-2:1987, ISO_8859-3, ISO_8859-3:1988, ISO_8859-4,

  ISO_8859-4:1988, ISO_8859-5, ISO_8859-5:1988, ISO_8859-6, ISO_8859-6:1987,

  ISO_8859-7, ISO_8859-7:1987, ISO_8859-8, ISO_8859-8:1988, ISO_8859-9,

  ISO_8859-9:1989, ISO_8859-10, ISO_8859-10:1992, ISO_8859-14,

  ISO_8859-14:1998, ISO_8859-15:1998, ISO_9036, ISO_10367-BOX, ISO_10367BOX,

  ISO_69372, IT, JIS_C6220-1969-RO, JIS_C6229-1984-B, JIS_C62201969RO,

  JIS_C62291984B, JOHAB, JP-OCR-B, JP, JS, JUS_I.B1.002, KOI-7, KOI-8, KOI8-R,

  KOI8-T, KOI8-U, KOI8, KOI8R, KOI8U, KSC5636, L1, L2, L3, L4, L5, L6, L7, L8,

  L10, LATIN-GREEK-1, LATIN-GREEK, LATIN1, LATIN2, LATIN3, LATIN4, LATIN5,

  LATIN6, LATIN7, LATIN8, LATIN10, LATINGREEK, LATINGREEK1, MAC-CYRILLIC,

  MAC-IS, MAC-SAMI, MAC-UK, MAC, MACCYRILLIC, MACINTOSH, MACIS, MACUK,

  MACUKRAINIAN, MS-ANSI, MS-ARAB, MS-CYRL, MS-EE, MS-GREEK, MS-HEBR,

  MS-MAC-CYRILLIC, MS-TURK, MSCP949, MSCP1361, MSMACCYRILLIC, MSZ_7795.3,

  MS_KANJI, NAPLPS, NATS-DANO, NATS-SEFI, NATSDANO, NATSSEFI, NC_NC0010,

  NC_NC00-10, NC_NC00-10:81, NF_Z_62-010, NF_Z_62-010_(1973), NF_Z_62-010_1973,

  NF_Z_62010, NF_Z_62010_1973, NO, NO2, NS_4551-1, NS_4551-2, NS_45511,

  NS_45512, OS2LATIN1, OSF00010001, OSF00010002, OSF00010003, OSF00010004,

  OSF00010005, OSF00010006, OSF00010007, OSF00010008, OSF00010009, OSF0001000A,

  OSF00010020, OSF00010100, OSF00010101, OSF00010102, OSF00010104, OSF00010105,

  OSF00010106, OSF00030010, OSF0004000A, OSF0005000A, OSF05010001, OSF100201A4,

  OSF100201A8, OSF100201B5, OSF100201F4, OSF100203B5, OSF1002011C, OSF1002011D,

  OSF1002035D, OSF1002035E, OSF1002035F, OSF1002036B, OSF1002037B, OSF10010001,

  OSF10020025, OSF10020111, OSF10020115, OSF10020116, OSF10020118, OSF10020122,

  OSF10020129, OSF10020352, OSF10020354, OSF10020357, OSF10020359, OSF10020360,

  OSF10020364, OSF10020365, OSF10020366, OSF10020367, OSF10020370, OSF10020387,

  OSF10020388, OSF10020396, OSF10020402, OSF10020417, PT, PT2, R8, ROMAN8, SE,

  SE2, SEN_850200_B, SEN_850200_C, SHIFT-JIS, SHIFT_JIS, SHIFT_JISX0213, SJIS,

  SS636127, ST_SEV_358-88, T.61-8BIT, T.61, T.618BIT, TCVN-5712, TCVN,

  TCVN5712-1, TCVN5712-1:1993, TIS-620, TIS620-0, TIS620.2529-1, TIS620.2533-0,

  TIS620, TS-5881, UCS-2, UCS-2BE, UCS-2LE, UCS-4, UCS-4BE, UCS-4LE, UCS2,

  UCS4, UHC, UJIS, UK, UNICODE, UNICODEBIG, UNICODELITTLE, US-ASCII, US, UTF-7,

  UTF-8, UTF-16, UTF-16BE, UTF-16LE, UTF-32, UTF-32BE, UTF-32LE, UTF7, UTF8,

  UTF16, UTF16BE, UTF16LE, UTF32, UTF32BE, UTF32LE, VISCII, WCHAR_T,

  WIN-SAMI-2, WINBALTRIM, WINDOWS-1250, WINDOWS-1251, WINDOWS-1252,

  WINDOWS-1253, WINDOWS-1254, WINDOWS-1255, WINDOWS-1256, WINDOWS-1257,

  WINDOWS-1258, WINSAMI2, WS2, YU

[root@linux script]#

强大的iconv 是由C语言中的iconv()函数实现的

 

15             开发工具/开发环境

15.1       Macromedia Dreamweaver MX 2004 JSP开发环境的配置

新建站点:

1           选择Manage Sites…

2           单击New…,然后选择Site

3           输入站点名称:mySite,下一步

4           选择我想使用服务器技术,在列表中选择“JSP”,下一步

5           选择,编辑、测试一台计算机上。选择一个站点目录。下一步

注:我的z:是使用net use z: \\192.168.0.1\web 映射的。\\192.168.0.1\weblinux服务器,webSamba 共享/var/www/html/webapps,而/var/www/html/webappsnetkiller.xml <Context path="/netkiller" docBase="/var/www/html/webapps" reloadable="true" debug="0" privileged="true">

 

[root@linux root]# cat /etc/samba/smb.conf

[web]

  comment = PC Directories

  path = /var/www/html/webapps

  public = yes

  writable = yes

 

[root@linux root]# cat /usr/local/jakarta-tomcat/webapps/netkiller.xml

<!--

 

    Context configuration file for the Tomcat Administration Web App

 

    $Id: admin.xml,v 1.3 2002/07/23 12:12:15 remm Exp $

 

-->

 

 

<Context path="/netkiller" docBase="/var/www/html/webapps" reloadable="true"

        debug="0" privileged="true">

 

  <!-- Uncomment this Valve to limit access to the Admin app to localhost

   for obvious security reasons. Allow may be a comma-separated list of

   hosts (or even regular expressions).

  <Valve className="org.apache.catalina.valves.RemoteAddrValve"

    allow="127.0.0.1"/>

  -->

 

  <Logger className="org.apache.catalina.logger.FileLogger"

             prefix="localhost_netkiller_log." suffix=".txt"

          timestamp="true"/>

 

</Context>

6           URL输入: http://192.168.0.1:8080/netkiller,单击“Test User

7           下一步

8           选择:No ,下一步

9           单击“Done

10        单击“Done

Dreamweaver站点如何操作这里就不讲了,请看相关教材

11        Ctrl+u 调出Dreamweaver控制面版,做如下设置。

11.1       Fonts 字体设置:

11.2       New Document 新建文档设置:

11.3       单击 OK 按钮。

 

15.2       Jcreator

JCreator is written entirely in C++, which makes it fast and efficient compared to the Java based editors/IDEs.

 

JCreator 的功能简单,特点速度快。笔者就用它来写Bean,在Dreamweaver中写JSP

单击“Tools”菜单à选择“Options…

点击“JDK Profilesà弹出下面对话框

 

15.3       Eclipse

关于Eclipse 的配置方法这里就不谈了。网上文档很多

15.4       JBuilder + Weblogic + PostgreSQL开发环境

 

JBuilder9+Weblogic8+PostgreSQL7 How to

 

BEA Weblogic platform811 安装

 

1.         双击下载的platform811_win32.exe文件

2.         开始解压

3.         单击Next

4.         单击Next

5.         选择安装BEA目录

6.         默认完全安装,单击下一步Next

7.         选择安装bea weblogic8.1产品目录,下一步Next

8.         开始安装。需要几分钟

9.         单击Done完成安装

配置向导

1.         启动bea weblogic Configuration Wizard工具

1.         显示Configuration Wizard界面

2.         单击Next

3.         单击Next

4.         输入用户、密码(密码需要8位)

5.         bae weblogic默认安装了JDK1.4.1,我要使用JDK 1.4.2

选择Other Java SDK

6.         单击Next

7.         Configuration Name : netkiller

8.         选择Start Admin Server ,单击Done

 

数据库连接池

9.         IE地址栏中输入:http://localhost:7001/console

10.     关闭weblogic

11.     配置PostgreSQL JDBC 驱动

PostgreSQL JDBC 驱动pg73jdbc3.jar 复制到D:\bea\weblogic81\server\lib目录下

编辑文件D:\bea\user_projects\domains\netkiller\startWebLogic.cmd

set CLASSPATH下面加入

set CLASSPATH=%CLASSPATH%;%WL_HOME%\server\lib\pg73jdbc3.jar

12.     然后启动weblogic ànetkiller

注意:d:\bea\WEBLOG~1\server\lib\pg73jdbc3.jar

d:\bea\user_projects\domains\netkiller>ECHO OFF

.

CLASSPATH=C:\J2SDK1~1.2_0\lib\tools.jar;d:\bea\WEBLOG~1\server\lib\weblogic_sp.j

ar;d:\bea\WEBLOG~1\server\lib\weblogic.jar;d:\bea\WEBLOG~1\server\lib\ojdbc14.ja

r;d:\bea\WEBLOG~1\common\eval\pointbase\lib\pbserver44.jar;d:\bea\WEBLOG~1\commo

n\eval\pointbase\lib\pbclient44.jar;C:\J2SDK1~1.2_0\jre\lib\rt.jar;d:\bea\WEBLOG

~1\server\lib\webservices.jar;;d:\bea\WEBLOG~1\server\lib\pg73jdbc3.jar

.

PATH=d:\bea\WEBLOG~1\server\bin;C:\J2SDK1~1.2_0\jre\bin;C:\J2SDK1~1.2_0\bin;C:\W

INDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;d:\bea\WEBLOG~1\server\bin\o

ci920_8

.

***************************************************

*  To start WebLogic Server, use a username and   *

*  password assigned to an admin-level user.  For *

*  server administration, use the WebLogic Server *

*  console at http:\\[hostname]:[port]\console    *

***************************************************

 

13.     登录

14.     登陆后显示

15.     选择netkiller-->Service-->JDBC-->Connection Pools

16.     单击Configure a new JDBC Connection Pool...

17.     选择Database Type: 选择PostgreSQL,然后单击Continue

18.     输入数据

ame:连接池名

Database Name:数据库名

Host Name:主机名

Port:端口号

Database User Name:数据库用户名

Password:数据库密码

Confirm Password:确认密码

然后单击Continue

19.     测试数据库连接

1.         单击Test Driver Configuation,输入绿色Connection successful 测试成功。如果是红色表示出错。

2.         单击Create and deploy

3.         连接池配置完成

数据源配置

1.         选择netkiller-->Service-->JDBC--> Data Source

 

2.         单击Configure a new JDBC Data Source

3.         JNDI Name:输入MyJDBCDataSource

4.         单击Continue

5.         选择一个连接池,然后单击Continue

6.         单击Create

7.         数据源配置完成

查看JNDI树

1.         展开netkilleràServersàmyserver

2.         myserver 上单击鼠标右键,选择View JNDI tree

myserver 下可以看到myJDBCDataSource

3.         数据源配置完成

 

JBuilder 9.0 Weblogic 配置

1.         ToolsàConfigure JDKs

2.         单击New

3.         选择JDK安装目录

4.         单击OK,完成

5.         Tools à Configure Servers

6.         选择Weblogic Platform Server 8.x

7.         REnable Server

8.         Home directory:选择D:/bea/weblogic81/server

9.         切换到Custom

10.     设置

BEA home directoryd:/bea

JDK Installation directory:你的JDK安装目录

Domain directoryD:/bea/user_projects/domains/netkiller

输入密码:********

勾去Add an Console item to the Tools menu

单击OK完成

 

新建项目

 

 

 

 

 

单击OK

新建

 

OK

OK

 

15.5       GUI数据库管理与设计(建模)工具

15.5.1 phpPgAdmin

这是一个PHP写的WEB数据库管理工具。

主页:http://phppgadmin.sourceforge.net/

下载:同上

安装:我是使用系统默认的apache

n         通过samba phpPgAdmin-3.3.tar.gz 复制到/var/www/html目录下

n         解包

n         进入phpPgAdmin目录

 

[root@linux root]# cd /var/www/html

[root@linux html]# tar zxvf phpPgAdmin-3.3.tar.gz

[root@linux html]# cd phpPgAdmin

[root@linux conf]# cd conf/

[root@linux conf]# vi config.inc.php

 

加入主机$conf['servers'][0]['host'] = '127.0.0.1';

修改默认数据库$conf['servers'][0]['defaultdb'] = 'netkiller';

        // Display name for the server on the login screen

        $conf['servers'][0]['desc'] = 'PostgreSQL';

 

        // Hostname or IP address for server.  Use '' for UNIX domain socket.

        $conf['servers'][0]['host'] = '127.0.0.1';

 

        // Database port on server (5432 is the PostgreSQL default)

        $conf['servers'][0]['port'] = 5432;

 

        // Change the default database only if you cannot connect to template1

        $conf['servers'][0]['defaultdb'] = 'netkiller';

 

n         IE地址栏中输入:http://192.168.0.1/phpPgAdmin/

n         出现下面登陆界面

 

n         输入用户名,密码,选择语言

n         登陆

关于如何使用phpPgAdmin这里就赘述了。phpPgAdmin只提供了一些基本功能,不过在WEB上远程管理,还是比较方便的。

下面你会看到更高级,复杂的管理工具。

15.5.2 PgAdmin III

主页http://www.pgadmin.org/

下载http://www.pgadmin.org/pgadmin3/download.php

中文http://www.pgadmin.org/pgadmin3/download.php?locale=zh_CN

pgAdmin III for PostgreSQL

 

15.5.3 Case Studio 2

主页:http://www.casestudio.com/

下载:http://www.casestudio.com/enu/download.aspx

 

 

 

 

 

 

CASE Studio 2 - Feature

LITE

FULL

Entity relationship diagrams

 

 

Clipper (older version)

no.gif - 1kb

no.gif - 1kb

DBISAM 3

no.gif - 1kb

no.gif - 1kb

IBM DB2 UDB ver. 8.1

no.gif - 1kb

no.gif - 1kb

IBM DB2 UDB ver. 7.1

no.gif - 1kb

no.gif - 1kb

Informix (older version)

no.gif - 1kb

no.gif - 1kb

Informix 9

no.gif - 1kb

no.gif - 1kb

Ingres (older version)

no.gif - 1kb

no.gif - 1kb

InterBase 7

no.gif - 1kb

no.gif - 1kb

InterBase 6 SQL 3

no.gif - 1kb

no.gif - 1kb

InterBase 6 SQL 1

no.gif - 1kb

no.gif - 1kb

InterBase 5

no.gif - 1kb

no.gif - 1kb

InterBase 4

no.gif - 1kb

no.gif - 1kb

MS Access 2000

no.gif - 1kb

no.gif - 1kb

MS Access 97

no.gif - 1kb

no.gif - 1kb

MS SQL 2000

no.gif - 1kb

no.gif - 1kb

MS SQL 7

no.gif - 1kb

no.gif - 1kb

MS SQL 6.5

no.gif - 1kb

no.gif - 1kb

MySQL 4 (incl. innoDB)

no.gif - 1kb

no.gif - 1kb

MySQL 3.23

no.gif - 1kb

no.gif - 1kb

Oracle 9

no.gif - 1kb

no.gif - 1kb

Oracle 8

no.gif - 1kb

no.gif - 1kb

Oracle 7

no.gif - 1kb

no.gif - 1kb

Paradox (older version)

no.gif - 1kb

no.gif - 1kb

Pervasive

no.gif - 1kb

no.gif - 1kb

PostgreSQL 7.3 BETA

no.gif - 1kb

no.gif - 1kb

PostgreSQL 7

no.gif - 1kb

no.gif - 1kb

Sybase 12.5

no.gif - 1kb

no.gif - 1kb

 

 

 

Data flow diagram

 

 

Data flows

no.gif - 1kb

no.gif - 1kb

Data stores

no.gif - 1kb

no.gif - 1kb

Processes

no.gif - 1kb

no.gif - 1kb

Terminators

no.gif - 1kb

no.gif - 1kb

 

 

 

Reverse engineering

 

 

Clipper (older version)

no.gif - 1kb

no.gif - 1kb

DBISAM 3

no.gif - 1kb

no.gif - 1kb

IBM DB2 UDB ver. 7

no.gif - 1kb

no.gif - 1kb

IBM DB2 UDB ver. 8

no.gif - 1kb

no.gif - 1kb

Informix (older version)

no.gif - 1kb

no.gif - 1kb

Informix 9

no.gif - 1kb

no.gif - 1kb

Ingres (older version)

no.gif - 1kb

no.gif - 1kb

InterBase 7

no.gif - 1kb

no.gif - 1kb

InterBase 6 SQL 3, InterBase 6 SQL 1

no.gif - 1kb

no.gif - 1kb

InterBase 5

no.gif - 1kb

no.gif - 1kb

InterBase 4

no.gif - 1kb

no.gif - 1kb

MS Access 2000

no.gif - 1kb

no.gif - 1kb

MS Access 97

no.gif - 1kb

no.gif - 1kb

MS SQL 2000

no.gif - 1kb

no.gif - 1kb

MS SQL 7

no.gif - 1kb

no.gif - 1kb

MS SQL 6.5

no.gif - 1kb

no.gif - 1kb

MySQL 4 (incl. innoDB)

no.gif - 1kb

no.gif - 1kb

MySQL 3.23

no.gif - 1kb

no.gif - 1kb

Oracle 9

no.gif - 1kb

no.gif - 1kb

Oracle 8

no.gif - 1kb

no.gif - 1kb

Oracle 7

no.gif - 1kb

no.gif - 1kb

Paradox (older version)

no.gif - 1kb

no.gif - 1kb

Pervasive

no.gif - 1kb

no.gif - 1kb

PostgreSQL 7.3 BETA

no.gif - 1kb

no.gif - 1kb

PostgreSQL 7

no.gif - 1kb

no.gif - 1kb

Sybase 12.5

no.gif - 1kb

no.gif - 1kb

 

 

 

Reports & export possibilities

 

 

RTF reports

no.gif - 1kb

no.gif - 1kb

HTML reports

no.gif - 1kb

no.gif - 1kb

Export into JPG, BMP or PNG

no.gif - 1kb

no.gif - 1kb

Export into XML

no.gif - 1kb

no.gif - 1kb

 

 

 

Features

 

 

After script items

no.gif - 1kb

no.gif - 1kb

Alternate keys

no.gif - 1kb

no.gif - 1kb

Alter scripts

no.gif - 1kb

no.gif - 1kb

Autolayout

no.gif - 1kb

no.gif - 1kb

Before script items

no.gif - 1kb

no.gif - 1kb

Cardinality

no.gif - 1kb

no.gif - 1kb

Data dictionary (domains)

no.gif - 1kb

no.gif - 1kb

Descriptions

no.gif - 1kb

no.gif - 1kb

Drops generation

no.gif - 1kb

no.gif - 1kb

Foreign keys definition

no.gif - 1kb

no.gif - 1kb

Functions

no.gif - 1kb

no.gif - 1kb

Indexes

no.gif - 1kb

no.gif - 1kb

Informative relationships

no.gif - 1kb

no.gif - 1kb

Internal clipboard

no.gif - 1kb

no.gif - 1kb

M:N relationships

no.gif - 1kb

no.gif - 1kb

Network features

no.gif - 1kb

no.gif - 1kb

New user defined data types

no.gif - 1kb

no.gif - 1kb

Non-identifying relationships

no.gif - 1kb

no.gif - 1kb

Notes

no.gif - 1kb

no.gif - 1kb

Object type bodies*

no.gif - 1kb

no.gif - 1kb

Object types*

no.gif - 1kb

no.gif - 1kb

Package bodies*

no.gif - 1kb

no.gif - 1kb

Packages*

no.gif - 1kb

no.gif - 1kb

Patterns for views, procedures and triggers

no.gif - 1kb

no.gif - 1kb

Primary keys definition

no.gif - 1kb

no.gif - 1kb

Referential integrity

no.gif - 1kb

no.gif - 1kb

Rough uppercase/lowercase selection

no.gif - 1kb

no.gif - 1kb

Self relationships

no.gif - 1kb

no.gif - 1kb

Sequences*

no.gif - 1kb

no.gif - 1kb

SQL script generation

no.gif - 1kb

no.gif - 1kb

Storages

no.gif - 1kb

no.gif - 1kb

Stored procedures

no.gif - 1kb

no.gif - 1kb

Support of compound foreign keys

no.gif - 1kb

no.gif - 1kb

Synonyms*

no.gif - 1kb

no.gif - 1kb

Triggers

no.gif - 1kb

no.gif - 1kb

User permissions (in models)

no.gif - 1kb

no.gif - 1kb

Users (in models)

no.gif - 1kb

no.gif - 1kb

Users group (in models)

no.gif - 1kb

no.gif - 1kb

Views

no.gif - 1kb

no.gif - 1kb

 

 

 

Model maintenance

 

 

Database/Model conversion**

no.gif - 1kb

no.gif - 1kb

Gallery

no.gif - 1kb

no.gif - 1kb

Model check

no.gif - 1kb

no.gif - 1kb

Submodels

no.gif - 1kb

no.gif - 1kb

To-Do list

no.gif - 1kb

no.gif - 1kb

Version comparsion

no.gif - 1kb

no.gif - 1kb

Version manager

no.gif - 1kb

no.gif - 1kb

 

 

 

Scripting and user defined templates

 

 

OLE Automation objects

no.gif - 1kb

no.gif - 1kb

Large COM interface

no.gif - 1kb

no.gif - 1kb

MS Scripting

no.gif - 1kb

no.gif - 1kb

Jscript support

no.gif - 1kb

no.gif - 1kb

VB script support

no.gif - 1kb

no.gif - 1kb

Templates editor

no.gif - 1kb

no.gif - 1kb

Templates export

no.gif - 1kb

no.gif - 1kb

Templates import

no.gif - 1kb

no.gif - 1kb

User defined variables editor

no.gif - 1kb

no.gif - 1kb

 

 

 

Displaying

 

 

Visual creation of DFD

no.gif - 1kb

no.gif - 1kb

Visual creation of ERD

no.gif - 1kb

no.gif - 1kb

Alignment in columns

no.gif - 1kb

no.gif - 1kb

Attributes syntax highlighting

no.gif - 1kb

no.gif - 1kb

Entity background color selection

no.gif - 1kb

no.gif - 1kb

Font selection

no.gif - 1kb

no.gif - 1kb

Logical model

no.gif - 1kb

no.gif - 1kb

Physical model

no.gif - 1kb

no.gif - 1kb

Logical view / physical view

no.gif - 1kb

no.gif - 1kb

Model background color selection

no.gif - 1kb

no.gif - 1kb

Shadows

no.gif - 1kb

no.gif - 1kb

Stamp

no.gif - 1kb

no.gif - 1kb

Straight relationship lines

no.gif - 1kb

no.gif - 1kb

Text descriptions

no.gif - 1kb

no.gif - 1kb

Variable display level

no.gif - 1kb

no.gif - 1kb

 

 

 

Support

 

 

Free email support

no.gif - 1kb

no.gif - 1kb

Free updates of CASE Studio 2

no.gif - 1kb

no.gif - 1kb

 

15.5.4 PostgreSQL Manager

EMS PostgreSQL Manager

主页:http://ems-hitech.com/pgmanager/

下载:http://ems-hitech.com/pgmanager/download.phtml

 

1 主界面

 

2 数据管理

 

3 强大的E-R 图功能

 

4 这是我用逆向工程导入已经存在的数据库

 

EMS PostgreSQL Manager is a powerful graphical tool for PostgreSQL administration and development. It makes creating and editing PostgreSQL database objects easy and fast, and allows you to run SQL scripts, manage users and their privileges, build SQL queries visually, extract, print and search metadata, export data to 14 available formats and import them from most popular formats, view and edit BLOB fields, and many more...

 

Version 2.0 Features

 

  Full PostgreSQL 7.4 support!
   Visual Database Designer - to design your database intuitively!
   Plpgsql Function Debugger - to fix the errors in the function code and to optimize the function work!
   HTML Report Generator - to generate detailed reports about your database in HTML format!
   Internal SSH Client - to connect to your database using Secure SHell!
   Highly improved Data Export and Data Import wizards!
   And much more...

 

Find the list of all program features as well as the Professional/Lite and Windows/Linux differences in the Feature Matrix.

 

Easy management of all PostgreSQL objects:

  Creating/Dropping databases;
   Creating/Dropping/Altering tables, views, functions, sequences
   Creating/Dropping types, aggregates, operators, languages
   Creating/Dropping/Altering tables subobjects: foreign keys, checks, indices, triggers
   Creating/Altering table fields
   Creating/Dropping/Altering table/view rules
   Duplicating tables, table fields, views, functions, rules, triggers, sequences, types, aggregates, operators, languages
   Support of all field types
   Viewing/Editing data in tables
   Adding/Editing/Deleting users, groups and their privileges

 

Powerful tools to work with PostgreSQL server

  Database Explorer featuring

  Multiple database connections
   Registering/Unregistering databases allows working only with the databases required
   Grouping/Ungrouping registered databases by host name
   Project View allows combining database object with user items
   Powerful User Manager, Group Manager and Grant Manager

 

 SQL processing and watching tools, including:

  Powerful SQL Editor
   Script Executing (SQL Script)
   Visual Query Builder
   SQL Monitor
   Powerful metadata printing module with the opportunity of customizing reports(fonts, colors, etc.)
   Extracting metadata into text files or SQL Script editor

 

 Powerful data manipulation tools, including:

  Powerful BLOB Viewer/Editor with several types of viewing BLOB data:
   Export data to Excel, RTF (Word), HTML, XML, DBF, TXT, CSV, SYLK, DIF, LaTeX and Windows Clipboard.
   Import Data Wizard
   Copy Data to/from file wizards

 

And some other useful features, including:

  Customizable program options: windows, fonts, grid colors, etc
   Customizable editors: custom colors, fonts etc.
   Customizable toolbars for all program windows
   Keyboard templates
   Powerful Visual Options Module
   Possibility of saving all the program settings
   Detailed Help System
   PostgreSQL Manager Direct
   And other useful tools, including TO-DO list for each database, External Tool Manager, etc.

15.5.5 DeZign for Databases

主页:http://www.datanamic.com/

下载:http://www.datanamic.com/download/index.html

 

Feature highlights:

n          Entity Relationship Diagram (ERD) editor.

n          Template driven schema generation (DDL).

n          One project cabn contain multiple subdiagrams.

n          Powerful report generator (HTML, Text, HTML with image map).

n          Creation of domains is supported. Usage of domains is supported even for a database that does not support domains.

n          Supports the ER modeling techniques including some advanced techniques like sub categories.

n          Fast, facile graphics manipulation.

n          Automatic resolution of many-to-many relationships.

n          Object browser for entities, relationships, attributes and domains.

n          Creation of triggers, procedures and sequences is supported.

n          Multiple display levels.

n          Export diagram to an image file (Bitmap, Gif, JPeg or Windows Metafile).

n          Object naming tool.

n          Automatic foreign key migration at design time.

n          Version control.

n          Full cardinality and connectivity support.

 

15.5.6 GUI工具比较

 

数据管理

维护

设计(建模)

逆向工程

最好得分

phpPgAdmin

ñ

ò

 

 

ò

PgAdmin III

ñ

ò

 

 

õ

Case Studio 2

 

 

ó

ô

õõ

DeZign for Databases

 

 

ó

ô

õõõ

PostgreSQL Manager

ñ

ò

ó

ô

õõõõ

 

 

 

 

 

 

 

我个人对PostgreSQL Manager的评价是,它完全可以与Oracle DBA StudioMS SQL Server 2000的图形界面管理工具相媲美。

 

16             FAQ

16.1       关于“”与null

'' = \0

 

这么说吧.

一个杯子,杯是空的吗???

NO,里面还有空气呢.这就是""

 

让他中空就是null

16.2       Postgresql与其它数据库

关于测试大家去看一下TPC-CTPC-WTPC-HTPC-R

网上有很多文章评论PostgreSQL MySQL Oracle , Sybase , MS Sql Server……而且还做了测试。结果当然是MySQL快了。还有一些无聊人丑化PostgreSQL,说它不稳定,爱宕机……

我要问测试过程得出的结果是否公平?

n         做测试的人是做什么的。是数据方面高手吗?或DBA吗?

n         他对数据优化了吗?

n         记录多少?

n         存储大小?

n         测试结果是应用于什么领域?

n         使用什么APIjdbc,odbc,c++ api……

 

如果你看过这类文章你会发现他们基本上是如下套路:

1.         创建数据

2.         创建表

3.         取当前时间,开始时间

4.         使用程序循环对test表分别插入、删除、更新数据

5.         取当前时间,结束时间

6.         两次时间差,得出结果

7.         这样可以得出三个结果,插入、删除、更新

这样的测试结果一点也不公平。

 

我这里有几种测试数据库性能方法。只供参考,不一定正确、准确。

测试环境和件条:

n         相同配置的计算机

n         相同操作系统

n         使用同一种语言和数据库接口(最公平的是使用C++ API连接数据库)

n         注意索引

n         win平测试结果不准

测试实例:

1.         首先进行单表的插入、删除、更新测试。得出结果(流程同上)

2.         进行事务处理单表的插入、删除、更新测试,每10010005000等为一个组做事务,得出结果 (一)

3.         多表测试
创建一个实表,有11字段,id字段为PK主键,在表中插入10条记录
然后创建维表,有11字段,id字段为FK外建,参考实表id字段(一对多),插入10条记录,
以此类推。见 图(二)使用join测试分别在不同维度时的结果,更高级测试请参看《数据仓库》

4.         对于大型数据库是不能光看记录多少,还要看数据库容量。从5G起步,10G50G100G200G…… 使用上面的多表测试方法将其中某字段改为大对象。得出结果

5.         子查询性能测试

6.         压力测试 要自己写一个小程序,多线程连接数据。
然后几台机上运行这个程序5几进程,每个进程中有10个线程

 

(一)

 

图(二)

 

16.3       Putty

主页:http://www.chiark.greenend.org.uk/~sgtatham/putty/

16.3.1 Putty密钥认证

1.         运行puttygen.exe

 

2.         选择SSH2 RSA 或者 SSH2 DSA

3.         点击“Generate”按钮

 

SSH1 RSA 产生速度快些。SSH2 可能要等一回。

4.         成功

5.         分别保存公钥public和私钥private

6.         将公钥上传到linux上,我产生密钥是给chen用户使用的。

7.         chen登录linux安装密钥

[chen@linux chen]$ mkdir .ssh

[chen@linux chen]$ chmod 700 .ssh

[chen@linux chen]$ cat public > .ssh/authorized_keys2

[chen@linux chen]$ chmod 600 .ssh/authorized_keys2

Linux 的密钥安装好了,我们来测试一下。

运行putty

输入Host Name

选择SSH下的Auth菜单。

Private key file for authentication:

选择你的私钥。

然后单击“Open”按钮

login as: chen

Sent username "chen"

Trying public key authentication.

Passphrase for key "rsa-key-20040315":

[chen@linux chen]$

 

可能出现的几种问题:

 

1Server refused our key

公匙和私匙不匹配,或者没有 authorized_keys 文件

 

2Unable to use key file  (SSH1 private key)

私匙文件的格式不正确,你可以分别试一下sshssh2

16.3.2 中输入汉字的问题

1.         运行Putty登陆到服务器

2.         在标题栏上单击右键

3.         选择“Change Settings…”菜单

4.         弹出下面对话框

5.         选择Category:列表下Window项中的Translation

6.         弹出下面对话框

7.         Character set translation on received data区域Received data assumed tobe in which character set:下拉列表中选择“UTF-8”编码

8.         弹出下面对话框

9.         单击应用按钮“Apply

10.     putty中输入中文。任何输入法都可以。

16.4       控制台下输入汉字

zhcon是工作在Linux控制台下的高效双字节中//(CJK)虚拟终端,就像DOS环境中的UCDOS一样,为控制台(console)环境提供完整的双字节语言环境。

主页:http://zhcon.sourceforge.net/

项目网页http://sourceforge.net/projects/zhcon/

下载zhcon

wget http://keihanna.dl.sourceforge.net/sourceforge/zhcon/zhcon-0.2.3.tar.gz

截图:

http://zhcon.sourceforge.net/images/scr_vim61.png

http://zhcon.sourceforge.net/images/scr_mc.gif

http://zhcon.sourceforge.net/images/scr_lynx.gif

http://zhcon.sourceforge.net/images/scr_emac.gif

http://zhcon.sourceforge.net/images/scr_bbs.gif

http://zhcon.sourceforge.net/images/scr_vi.gif

http://zhcon.sourceforge.net/images/scr_overspot.gif

安装

[root@linux zhcon-0.2.3]# ./configure

[root@linux zhcon-0.2.3]# make

[root@linux zhcon-0.2.3]# make install

运行:

[root@linux root]#zhcon

16.5       PostgreSQL RPM 包安装后,为何没有5432端口

安装:

    rpm -Uvh --nodeps postgresql-libs-?.?.?-1PGDG.i386.rpm

    rpm -Uvh --nodeps postgresql-?.?.?-1PGDG.i386.rpm

    rpm -Uvh --nodeps postgresql-devel-?.?.?-1PGDG.i386.rpm

    rpm -Uvh --nodeps postgresql-server-?.?.?-1PGDG.i386.rpm

    rpm -Uvh --nodeps postgresql-contrib-?.?.?-1PGDG.i386.rpm

    rpm -Uvh --nodeps postgresql-docs-?.?.?-1PGDG.i386.rpm

    rpm -Uvh --nodeps postgresql-jdbc-?.?.?-1PGDG.i386.rpm

    rpm -Uvh --nodeps postgresql-pl-?.?.?-1PGDG.i386.rpm

    rpm -Uvh --nodeps postgresql-python-?.?.?-1PGDG.i386.rpm

    rpm -Uvh --nodeps postgresql-tcl-?.?.?-1PGDG.i386.rpm

    rpm -Uvh --nodeps postgresql-test-?.?.?-1PGDG.i386.rpm

    rpm -qa|grep post

 

查看:

[root@linux script]# rpm -qa|grep post

postgresql-contrib-7.3.3-1PGDG

postgresql-7.3.3-1PGDG

postgresql-tcl-7.3.3-1PGDG

postgresql-devel-7.3.3-1PGDG

postgresql-jdbc-7.3.3-1PGDG

postgresql-test-7.3.3-1PGDG

postgresql-server-7.3.3-1PGDG

postgresql-pl-7.3.3-1PGDG

postgresql-libs-7.3.3-1PGDG

postgresql-python-7.3.3-1PGDG

postfix-1.1.11-5

postgresql-docs-7.3.3-1PGDG

启动、初始化:

[root@linux root]# service postgresql start

[root@linux root]# su postgres

bash-2.05b$ createdb

bash-2.05b$ psql

Welcome to psql 7.3.3, the PostgreSQL interactive terminal.

 

Type:  \copyright for distribution terms

       \h for help with SQL commands

       \? for help on internal slash commands

       \g or terminate with semicolon to execute query

       \q to quit

 

postgres=#

       使用“\q”退出数据库。

配置:

       PostgreSQL配置默认没有启用TCP/IP连接,开启tcpip_socket编辑postgresql.conf文件

[root@linux root]# cd /var/lib/pgsql/data/

[root@linux data]# vi postgresql.conf

#

#       Connection Parameters

#

 

tcpip_socket = true

 

#ssl = false

 

#max_connections = 32

#superuser_reserved_connections = 2

 

#port = 5432

#hostname_lookup = false

#show_source_port = false

:wq (保存)

       tcpip_socket = false改为tcpip_socket = true 即可,端口默认5432。如果你想使用其它端口配置port = 5432 即可。

 

运行:

[root@linux root]# service postgresql restart

                                                           [  OK  ]

Starting postgresql service:                                     [  OK  ]

 

查看:

使用端口扫描工具NAMP查看PostgreSQL  tcpip_socket功能是否启用,

输出5432/tcp   open        postgre 配置成功。

 

[root@linux root]# nmap localhost

 

Starting nmap V. 3.00 ( www.insecure.org/nmap/ )

Interesting ports on localhost.localdomain (127.0.0.1):

(The 1592 ports scanned but not shown below are in state: closed)

Port       State       Service

22/tcp     open        ssh

25/tcp     open        smtp

80/tcp     open        http

111/tcp    open        sunrpc

139/tcp    open        netbios-ssn

389/tcp    open        ldap

2401/tcp   open        cvspserver

3306/tcp   open        mysql

5432/tcp   open        postgres

 

Nmap run completed -- 1 IP address (1 host up) scanned in 2 seconds

[root@linux root]#

 

测试:

[root@linux root]# psql -h127.0.0.1 -Upostgres

Welcome to psql 7.3.3, the PostgreSQL interactive terminal.

 

Type:  \copyright for distribution terms

       \h for help with SQL commands

       \? for help on internal slash commands

       \g or terminate with semicolon to execute query

       \q to quit

 

postgres=#

16.6       PostgreSQL 7.4.2 rhel3(高级服务器版,俗称AS3)

[root@linuxas3 postgres]# wget ftp://ftp.tw.postgresql.org/pub/postgresql/binary/v7.4.2/redhat/rhel3/*

[root@linuxas3 postgres]# rpm --nodeps -Uvh *.rpm

   1:postgresql-test        ########################################### [  8%]

   2:postgresql             ########################################### [ 17%]

   3:postgresql-contrib     ########################################### [ 25%]

   4:postgresql-debuginfo   ########################################### [ 33%]

   5:postgresql-devel       ########################################### [ 42%]

   6:postgresql-docs        ########################################### [ 50%]

   7:postgresql-jdbc        ########################################### [ 58%]

   8:postgresql-libs        ########################################### [ 67%]

   9:postgresql-pl          ########################################### [ 75%]

  10:postgresql-python      ########################################### [ 83%]

  11:postgresql-server      ########################################### [ 92%]

  12:postgresql-tcl         ########################################### [100%]

 

[root@linuxas3 postgres]# rpm -qa | grep postgres

postgresql-libs-7.4.2-1PGDG

postgresql-devel-7.4.2-1PGDG

postgresql-7.4.2-1PGDG

postgresql-docs-7.4.2-1PGDG

postgresql-python-7.4.2-1PGDG

postgresql-contrib-7.4.2-1PGDG

postgresql-jdbc-7.4.2-1PGDG

postgresql-server-7.4.2-1PGDG

postgresql-debuginfo-7.4.2-1PGDG

postgresql-tcl-7.4.2-1PGDG

postgresql-test-7.4.2-1PGDG

postgresql-pl-7.4.2-1PGDG

[root@linuxas3 postgres]#

 

16.7       Pureftpd pgsql认证模块

Pure-FTPd + LDAP + MySQL + PGSQL + Virtual-Users + Quota How To

http://home.9812.net/linux/article/pureftpd/

16.8       Vsftpd pgsql认证

vsftpd的虚拟用户配置:PAM + PgSQL + FreeBSD-4

作者:powerplane

连接:http://www.freebsdchina.org/forum/digest_4589.html

 

16.9       OpenLDAP-PostgreSQL HOWTO

http://www.samse.fr/GPL/ldap_pg/HOWTO/

 

16.10 PostgreSQL 成功案例与解决方案

http://www.isc.org/products/OpenReg/

OpenReg is an implementation of a domain registry, such as might be used by top-level domain operators to manage the delegation of domains in a "shared registry" environment. OpenReg:

  • supports the Extensible Provisioning Protocol (EPP), the IETF standards-track protocol for interaction between registries and registrars;
  • is designed and debugged as a distributed multi-process system;
  • supports PostgreSQL and is designed to accommodate to very large registries;
  • publishes zone files to be served using BIND;
  • gathers comprehensive profiling and load statistics;
  • is published as free software, under a BSD-style licence.

 

 

 

 

17             附录

17.1       实例

/*

#########################################################

Created          2003-7-21

Modified  2003-7-22

Project           XXXXXXXXXXXXX

Model            XXXXXXXXXX

Company        XXXXXXXX

Author           陈景峰

Version           1.0

Database PostgreSQL 7.3.3

#########################################################

*/

 

-- ======================================================

--  'CREATE DATABASE' 

-- ======================================================  

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

-- CREATE USER netkiller WITH PASSWORD 'chen';

-- CREATE DATABASE netkiller WITH OWNER = netkiller TEMPLATE = template0 ENCODING = 'EUC_CN';

-- postgres=# CREATE DATABASE member WITH OWNER = netkiller TEMPLATE = template0 ENCODING = 'UNICODE';

-- createlang plpgsql netkiller

-- createlang plpgsql member

 

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

 

Drop index "group_index";

Drop table "group" CASCADE;

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

Drop index "role_index";

Drop table "role" CASCADE;

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

Drop table "rolemember" Restrict;

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

Drop table "groupmember" CASCADE;

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

Drop table "trust" Restrict;

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

Drop table userinfo CASCADE;

DROP TABLE system_log CASCADE;

DROP TABLE user_log CASCADE;

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

Drop table "user" CASCADE;

 

-- ======================================================

--  'user' 

-- ======================================================  

Create table "user"

(

       "id" Serial NOT NULL,

       "userid" Varchar(50) NOT NULL,

       "passwd" Varchar(50),

       "name"    Varchar(20)NOT NULL ,

       "nickname" Varchar(20)NOT NULL ,

       "active" Boolean Default 'F',

       "email"    Varchar(50) NOT NULL,

       "question" Varchar(255) NOT NULL,

       "answer" Varchar(255) NOT NULL,

       "begin_date" Timestamp Default now(),

       "end_date" Timestamp Default now(),

       UNIQUE (userid,email),

 primary key ("id")

);

Create index "user_index" on "user" using btree ("id","userid");

 

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

--  'vuser'

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

drop view vuser;

CREATE VIEW vuser AS

    SELECT u.id,u.userid,u."name",u.nickname,

           CASE WHEN u.active=true THEN 'Y' ELSE 'N' END as "active",

           u.email,u.question,u.answer,

           to_char(u.begin_date,'YYYY-MM-DD HH:MI:SS') as begin_date,

           to_char(u.end_date,'YYYY-MM-DD HH:MI:SS') as end_date

    FROM "user" u

    Order By u.id;

 

-- DROP FUNCTION user_tri_func() CASCADE ;

CREATE OR REPLACE FUNCTION user_tri_func () RETURNS TRIGGER AS '

    DECLARE

           -- old_id ALIAS FOR OLD.id;

           -- new_id CONSTANT INTEGER := New.id;

    BEGIN

        IF TG_OP = ''DELETE'' THEN

                  Delete from groupmember where uid = OLD.id;

                 Delete from rolemember where uid = OLD.id;

                 Delete from userinfo where uid = OLD.id;

                 Delete from trust where uid = OLD.id;

                 Delete from system_log where uid = OLD.id;

                 Delete from user_log where uid = OLD.id;

       END IF;

           IF TG_OP = ''INSERT'' THEN

                  -- INSERT INTO company(uid) values(NEW.id);

           END IF;

    RETURN OLD;

    END;

' LANGUAGE 'plpgsql';

-- DROP TRIGGER user_delete_tri on user;

-- DROP TRIGGER user_insert_tri on user;

CREATE TRIGGER users_delete_tri

       BEFORE Delete ON "user" FOR EACH ROW

       EXECUTE PROCEDURE user_tri_func ();

 

CREATE TRIGGER users_insert_tri

       AFTER INSERT ON "user" FOR EACH ROW

       EXECUTE PROCEDURE user_tri_func ();

/*

-- ======================================================

--  'privileges'

-- ======================================================

--Drop table "privileges" Restrict;

Create table "privileges"

(

       "id" integer NOT NULL UNIQUE ,

       "read" integer,

       "update" integer,

       "write" integer,

 primary key ("id")

);

*/

-- ======================================================

--  'group'

-- ======================================================

Create table "group"

(

       "id" Serial NOT NULL UNIQUE,

       "groupname" Varchar(20) NOT NULL,

       "description" Varchar(255),

       UNIQUE (groupname),

      PRIMARY KEY ("id")

);

Create index "group_index" on "group" using btree ("id","groupname");

-- ======================================================

--  'groupmember'

-- ======================================================

Create table "groupmember"

(

       "id" Serial NOT NULL UNIQUE,

       "gid" integer NOT NULL Default 0,

       "uid" integer NOT NULL Default 0,

       UNIQUE (gid,uid),

       primary key ("id")

);

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

--  'vgroupmember'

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

-- DROP VIEW vgroupmember;

CREATE VIEW vgroupmember AS

    SELECT gm.id,gm.gid,g.groupname,gm.uid,u.userid,u.name

           FROM "group" g,"user" u,groupmember gm

        Where u.id = gm.uid and g.id = gm.gid

    ORDER BY gm.id;

/*   

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

--  'vgroup'

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

-- PHP Interface View

CREATE OR REPLACE VIEW vgroup AS

    SELECT gm.id,gm.uid,gm.gid,g.groupname

    FROM "group" g,groupmember gm

    Where g.id = gm.gid

    ORDER BY gm.id;

*/   

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

--  'RULE'

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

CREATE RULE group_rule AS ON Delete TO "group"

    DO Delete From groupmember where gid = OLD.id;

 

-- ======================================================

--  'role'

-- ======================================================

-- drop table role CASCADE;

Create table "role"

(

       "id" Serial NOT NULL UNIQUE,

       "rolename" Varchar(20) NOT NULL,

       "description" Varchar(255),

       UNIQUE (rolename),

      PRIMARY KEY ("id")

);

Create index "role_index" on "role" using btree ("id","rolename");

 

-- ======================================================

--  'rolemember' 

-- ======================================================

-- drop table rolemember CASCADE ;

Create table "rolemember"

(

       "id" Serial NOT NULL UNIQUE,

       "rid" integer NOT NULL Default 0,

       "uid" integer NOT NULL Default 0,

       UNIQUE (rid,uid),

 primary key ("id")

);

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

--  'vrolemember'

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

CREATE VIEW vrolemember AS

    SELECT rm.id,rm.rid,r.rolename,rm.uid,u.userid,u.name

           FROM "role" r,"user" u,rolemember rm

        Where u.id = rm.uid and r.id = rm.rid

        ORDER BY rm.id;

 

/*       

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

--  'vrole'

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

CREATE OR REPLACE VIEW vrole AS

    SELECT rm.id,rm.uid,rm.rid,r.rolename

    FROM "user" u,role r,rolemember rm

    Where u.id = rm.uid and r.id = rm.rid

    ORDER BY rm.id;

*/   

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

--  'RULE'

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

CREATE RULE role_rule AS ON Delete TO role

    DO Delete From rolemember where rid = OLD.id;

 

-- ======================================================

--  'Foreign Key'

-- ======================================================

Alter table "groupmember" add  foreign key ("uid") references "user" ("id") on update restrict on delete restrict;

Alter table "groupmember" add  foreign key ("gid") references "group" ("id") on update restrict on delete restrict;

Alter table "rolemember" add  foreign key ("uid") references "user" ("id") on update restrict on delete restrict;

Alter table "rolemember" add  foreign key ("rid") references "role" ("id") on update restrict on delete restrict;

 

-- ======================================================

--  'trust'

-- ======================================================

Create table "trust"

(

       "id" Serial NOT NULL UNIQUE,

       "uid" integer NOT NULL Default 0,

       "rate" Varchar(20) Default '0' Check (rate in ('0','1','2','3','4','5')),

      primary key ("uid")

);

Alter table "trust" add  foreign key ("uid") references "user" ("id") on update restrict on delete restrict;

-- ======================================================

--  'userinfo'

-- ======================================================

-- Drop table userinfo CASCADE;

Create table "userinfo"

(

       id     Serial NOT NULL UNIQUE,

       uid integer NOT NULL Default 0,

       tel   Varchar (20) NOT NULL,

       fax varchar(20),

       email varchar(60),

       province varchar(8),

       city varchar(10),

       address varchar(255) DEFAULT '' NOT NULL,

     postalcode      varchar(6)   DEFAULT '' NOT NULL,     -- post office code      

      bank              varchar(20)   DEFAULT '' NOT NULL,   -- bank

      bankaccount   varchar(20)   DEFAULT '' NOT NULL,   -- Back Account    

       "rate" Varchar(20) Default '0' Check (rate in ('0','1','2','3','4','5')),

      PRIMARY KEY(id),

      FOREIGN KEY (uid) REFERENCES "user" (id)

);

 

 

-- ======================================================

--  'log system'

-- ======================================================

Create table user_log

(

       id    Serial NOT NULL UNIQUE,

       uid integer NOT NULL Default 0,

       ip    inet,

       status varchar(255),

       PRIMARY KEY("id"),

      FOREIGN KEY (uid) REFERENCES "user" (id)

);

-- drop table system_log CASCADE;

Create table system_log

(

       id    Serial NOT NULL UNIQUE,

       uid integer NOT NULL Default 0,

       ip    inet ,

       status varchar(255),

       description varchar(255),

       login_date Timestamp Default now(),

       PRIMARY KEY("id"),

      FOREIGN KEY (uid) REFERENCES "user" (id)

);

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

--  'system_log'

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

drop view vsystem_log ;

CREATE OR REPLACE VIEW vsystem_log AS

    SELECT u.userid,u.name,log.ip,log.status,log.description,

           to_char(log.login_date,'YYYY-MM-DD HH:MI:SS') as login_date

    FROM "user" u,system_log log

    Where log.uid = u.id

    ORDER BY log.id;

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

-- 'Function'

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

-- DROP FUNCTION add_system_log(integer,inet,varchar);

CREATE OR REPLACE FUNCTION add_system_log(integer,inet,varchar,varchar) RETURNS boolean AS '

       DECLARE

           vUID       ALIAS FOR $1;

           vIP  ALIAS FOR $2;

              vSTATUS       ALIAS FOR $3;

              vDESC    ALIAS FOR $4;

       BEGIN

         insert into system_log(uid,ip,status,description) values(vUID,vIP,vSTATUS,vDESC);

         RETURN true;

      END;

' LANGUAGE 'plpgsql';

select add_system_log(1,'127.0.0.1','Create Database','Initialization Database');

 

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

--  'Insert Data'

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

insert into "user"(userid,passwd,name,nickname,email,question,answer) values('sysop','chen','chen','chen','chen@chen.com','xxxxxxx','xxxx');

insert into "user"(userid,passwd,name,nickname,email,question,answer) values('admin','chen','chen','chen','chen@chen.com','xxxxxxx','xxxx');

insert into "user"(userid,passwd,name,nickname,email,question,answer) values('netkiller','chen','陈景峰','Netkiller','chen@chen.com','xxxxxxx','xxxx');

update "user" set active='true' where userid='sysop';

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

--  'Insert Data'

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

Insert into "group"(groupname,description) values('System','系统管理员');

Insert into "group"(groupname,description) values('Administrator','站点管理员');

Insert into "group"(groupname,description) values('gold','gold diamond');

Insert into "group"(groupname,description) values('silver','silver diamond');

Insert into "group"(groupname,description) values('advance','高级会员');

Insert into "group"(groupname,description) values('free','免费会员');

 

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

--  'Insert Data'

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

Insert into "role"(rolename,description) values('System','系统管理员');

Insert into "role"(rolename,description) values('Administrator','站点管理员');

Insert into "role"(rolename,description) values('gold','gold diamond');

Insert into "role"(rolename,description) values('silver','silver diamond');

Insert into "role"(rolename,description) values('advance','高级会员');

Insert into "role"(rolename,description) values('free','免费会员');

 

insert into groupmember(gid,uid) values((select id from "group" where groupname ='System'),(select id from vuser where userid='sysop'));

insert into rolemember(rid,uid) values((select id from role where rolename ='System'),(select id from vuser where userid='sysop'));

 

17.2       实例

-- 主机: localhost 数据库 : XXXX

-- Create Database XXXX;

-- DROP DATABASE XXXX;

-- createdb -E EUC_CN XXXX

-- createlang plpgsql XXXX

--  CREATE USER XXXX WITH PASSWORD ''XXXXXX'';

 

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

--  'siteuser'

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

--DROP TABLE IF EXISTS siteuser;

DROP TABLE siteuser CASCADE;

DROP SEQUENCE siteuser_id_seq;

DROP INDEX siteuser_id_index;

 

CREATE TABLE siteuser (

     id integer DEFAULT nextval('siteuser_id_seq') NOT NULL,

     username varchar(20) DEFAULT '0' NOT NULL,

     Password       varchar(50) DEFAULT '0' NOT NULL,

     realname  varchar(10) DEFAULT '0' NOT NULL,

     email              varchar(50) DEFAULT '0' NOT NULL,

     create_date  timestamp DEFAULT now(),

     modify_date  timestamp DEFAULT now(),

     UNIQUE               (id,username),

       PRIMARY      KEY (id)

);

CREATE SEQUENCE siteuser_id_seq;

CREATE INDEX siteuser_id_index ON siteuser (id);

 

DROP FUNCTION siteuser_tri_func() CASCADE ;

CREATE OR REPLACE FUNCTION siteuser_tri_func () RETURNS opaque AS '

--    DECLARE

--         user_id CONSTANT INTEGER := OLD.id;

      BEGIN

             IF TG_OP = ''DELETE'' THEN

                  Delete from company where uid = OLD.id;

                 Delete from link where uid = OLD.id;

                 Delete from product_sort where uid = OLD.id;

                  Delete from news where uid = OLD.id;

                  Delete from count where uid = OLD.id;

                  Delete from guestbook where uid = OLD.id;

                  Delete from clientinfo where uid = OLD.id;

                  Delete from column_bar where uid = OLD.id;

                  Delete from drumbeating where uid = OLD.id;

           END IF;

           IF TG_OP = ''INSERT'' THEN

                  INSERT INTO company(uid) values(NEW.id);

                  INSERT INTO count(uid,number,fontcolor,backgroundcolor) values(NEW.id,0,''ffffff'',''000000'');

                  INSERT INTO drumbeating(uid,logourl,bannerurl) values(NEW.id,''default_logo.jpg'',''default_banner.jpg'');

           END IF;

    RETURN OLD;

      END;

' LANGUAGE 'plpgsql';

 

 

DROP TRIGGER siteuser_delete_tri on siteuser;

CREATE TRIGGER siteuser_delete_tri

       BEFORE Delete ON siteuser FOR EACH ROW

       EXECUTE PROCEDURE siteuser_tri_func ();

 

DROP TRIGGER siteuser_insert_tri on siteuser;

CREATE TRIGGER siteuser_insert_tri

       AFTER INSERT ON siteuser FOR EACH ROW

       EXECUTE PROCEDURE siteuser_tri_func ();

 

DROP FUNCTION adduser(varchar,varchar);

CREATE OR REPLACE FUNCTION adduser(varchar,varchar) RETURNS boolean AS '

       DECLARE

           bool boolean := false;

           name text;     

           uid   integer;

           user ALIAS FOR $1;

           pass ALIAS FOR $2;

           su    siteuser%ROWTYPE;

       BEGIN

           SELECT INTO name username FROM siteuser WHERE username = user;

             IF NOT FOUND then

              insert into siteuser(username,password) values(user,pass);

            SELECT INTO uid id FROM siteuser WHERE username = user;

              bool := true;

             ELSE

                     bool := false;

                     RAISE NOTICE ''Calling adduser() return %'',bool;

           END IF;

    RETURN bool;

      END;

' LANGUAGE 'plpgsql';

--select adduser('ccscc','eeee');

--select * from siteuser ;

--     record

DROP FUNCTION deluser(integer);

CREATE OR REPLACE FUNCTION deluser(integer) RETURNS boolean AS '

    DECLARE

           bool boolean := false;

           userid text;

       BEGIN

              SELECT INTO userid id FROM siteuser WHERE id = $1;

              IF FOUND then

                  delete from siteuser where id = $1;

                  bool := true;

           ELSE

           END IF;

           RETURN bool;

      END;

' LANGUAGE 'plpgsql';

--select deluser(28);

 

 

DROP VIEW vsiteuser;

CREATE VIEW vsiteuser AS

    SELECT su.id,su.username,

           to_char(su.create_date,'YYYY-MM-DD HH:MI:SS') as date

        FROM siteuser su

        ORDER BY su.id;

 

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

--  'style'

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

DROP TABLE style;

DROP SEQUENCE       style_id_seq;

DROP INDEX              style_id_index;

DROP VIEW vstyle;

 

CREATE TABLE style (

    id                   integer DEFAULT nextval('style_id_seq') NOT NULL,

--    uid                     integer   DEFAULT '1' NOT NULL,  -- with foreign key

    number         varchar(20) DEFAULT '' NOT NULL,       -- sytle number

    stylename       varchar(20) DEFAULT '' NOT NULL,

    miniature varchar(50) DEFAULT '' NOT NULL,       -- mini image

    url                varchar(50) DEFAULT '' NOT NULL,       -- link url  eg. /usr/local/apache/htdocs/autosite/style/n0001

    description      text              DEFAULT '' NOT NULL,   

     create_date  timestamp DEFAULT now() , 

     modify_date  timestamp DEFAULT now() ,  

    PRIMARY KEY (id),

    UNIQUE (id)

--  FOREIGN KEY (uid) REFERENCES siteuser (id)

);

CREATE SEQUENCE   style_id_seq;

CREATE INDEX          style_id_index ON style (id);

 

CREATE VIEW vstyle AS

    SELECT st.id,st.number,st.stylename,st.miniature,st.url,st.description,

           to_char(st.create_date,'YYYY-MM-DD HH:MI:SS') as date

        FROM style st

        ORDER BY st.id;

 

insert into style(number,stylename,miniature,url) values('0001','pink','../style/images/style0001.png','');

insert into style(number,stylename,miniature,url) values('0002','green','../style/images/style0002.png','');

insert into style(number,stylename,miniature,url) values('0003','cyan','../style/images/style0003.png','');

insert into style(number,stylename,miniature,url) values('0004','orange','../style/images/style0004.png','');

insert into style(number,stylename,miniature,url) values('0005','offwhite','../style/images/style0005.png','');

 

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

--  'company'

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

DROP TABLE company;

DROP SEQUENCE company_id_seq;

DROP INDEX company_id_index;

DROP VIEW vcompany;

 

CREATE TABLE company (

   id                    integer DEFAULT nextval('company_id_seq') NOT NULL,

   uid                   integer     DEFAULT '1' NOT NULL, -- with foreign key

   linkman            varchar(20)  DEFAULT '' NOT NULL,

   cncname         varchar(50)  DEFAULT '' NOT NULL,     -- Chinese Companyname

   encname         varchar(50)  DEFAULT '' NOT NULL,     -- English Companyname

   email       varchar(50)  DEFAULT '' NOT NULL,

   telephone  varchar(20)  DEFAULT '' NOT NULL,     -- telephone number

   fax                 varchar(20)  DEFAULT '' NOT NULL,     -- company fax

   Province_id      integer     DEFAULT '1' NOT NULL, -- with foreign key

   state        varchar(20)  DEFAULT '' NOT NULL,     -- company state

   city                 varchar(20)  DEFAULT '' NOT NULL,     -- company city

   address           varchar(50)  DEFAULT '' NOT NULL,     -- company address

   postalcode varchar(6)   DEFAULT '' NOT NULL,     -- post office code

   range       text DEFAULT '' NOT NULL,    

   details             text DEFAULT '' NOT NULL,     -- company details

   other        text ,                                        -- company other

   bank                varchar(20)   DEFAULT '' NOT NULL,   -- bank

   bankaccount     varchar(20)   DEFAULT '' NOT NULL,   -- Back Account 

   Category_id      integer     DEFAULT '1' NOT NULL,

   style_id            integer  DEFAULT '1' NOT NULL,

   create_date  timestamp DEFAULT now() ,

   modify_date  timestamp DEFAULT now() ,

   UNIQUE (id,uid),

   PRIMARY KEY (id),

   FOREIGN KEY (uid) REFERENCES siteuser (id),

   FOREIGN KEY (style_id) REFERENCES style (id),

   FOREIGN KEY (Province_id) REFERENCES Region (id),

   FOREIGN KEY (Category_id) REFERENCES Category (id)  

);

 

CREATE SEQUENCE company_id_seq;

CREATE INDEX company_id_index ON company (id);

 

CREATE VIEW vcompany AS

    SELECT cp.id,cp.uid,su.username,cp.linkman,cp.cncname,cp.encname,cp.email,cp.telephone,cp.fax,

           vpv.province,cp.city,cp.address,cp.postalcode,cp.bank,cp.bankaccount,cg.category,

           to_char(cp.create_date,'YYYY-MM-DD HH:MI:SS') as date

        FROM siteuser su,company cp,vProvince vpv,category cg

        where su.id = cp.uid and cp.province_id = vpv.id and cp.category_id = cg.id

        ORDER BY cp.id;

 

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

--  'link'

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

DROP TABLE link;

DROP SEQUENCE       link_id_seq;

DROP INDEX              link_id_index;

DROP VIEW vlink;

 

CREATE TABLE link (

    id                   integer DEFAULT nextval('link_id_seq') NOT NULL,

    uid                 integer   DEFAULT '1' NOT NULL,  -- with foreign key

    linkname         varchar(30) DEFAULT '' NOT NULL,       -- link name

    url                varchar(100) DEFAULT '' NOT NULL,      -- link url

    image            varchar(100) DEFAULT '' NOT NULL,      -- image(jpg,png,gif....)

     create_date  timestamp DEFAULT now() , 

     modify_date  timestamp DEFAULT now() ,  

     UNIQUE (id,uid),

    PRIMARY KEY (id),

    FOREIGN KEY (uid) REFERENCES siteuser (id)

);

CREATE SEQUENCE   link_id_seq;

CREATE INDEX          link_id_index ON company (id);

 

CREATE VIEW vlink AS

    SELECT l.id,l.uid,su.username,l.linkname,l.url,l.image,to_char(l.create_date,'YYYY/MM/DD HH:MI:SS') as date

        FROM siteuser su, link l

        WHERE su.id = l.uid

        ORDER BY l.id;

-- ORDER BY commit_log.commit_date  LIMIT 100;

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

--  'product_sort'

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

DROP TABLE product_sort;

DROP SEQUENCE       product_sort_id_seq;

DROP INDEX              product_sort_id_index;

DROP VIEW vproduct_sort;

 

CREATE TABLE product_sort (

    id                   integer DEFAULT nextval('product_sort_id_seq') NOT NULL,

    uid                 integer   DEFAULT '1' NOT NULL,  -- with foreign key

    plist       varchar(20) DEFAULT '' NOT NULL,       --

     create_date  timestamp DEFAULT now() , 

     modify_date  timestamp DEFAULT now() ,  

    PRIMARY KEY (id),

    UNIQUE (id,uid),

    FOREIGN KEY (uid) REFERENCES siteuser (id)

);

CREATE SEQUENCE   product_sort_id_seq;

CREATE INDEX          product_sort_id_index ON style (id);

 

CREATE VIEW vproduct_sort AS

    SELECT ps.id,ps.uid,su.username,ps.plist,to_char(ps.create_date,'YYYY-MM-DD HH:MI:SS') as date

        FROM siteuser su, product_sort ps

        WHERE su.id = ps.uid

        ORDER BY ps.id;

 

CREATE OR REPLACE FUNCTION product_sort_id_del_func () RETURNS opaque AS '

--  DECLARE

       BEGIN

          Delete from product where pid = OLD.id;

    RETURN OLD;

      END;

' LANGUAGE 'plpgsql';

 

DROP TRIGGER product_sort_tri on product_sort;

CREATE TRIGGER product_sort_tri

       BEFORE Delete

       --AFTER Delete

       ON product_sort FOR EACH ROW

       EXECUTE PROCEDURE product_sort_id_del_func ();

 

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

--  'product'

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

DROP TABLE product;

DROP SEQUENCE       product_id_seq;

DROP INDEX              product_id_index;

DROP VIEW vproduct;

 

CREATE TABLE product (

    id                   integer DEFAULT nextval('product_id_seq') NOT NULL,

    pid                 integer   DEFAULT '1' NOT NULL,  -- with foreign key

    pname           varchar(50) DEFAULT '' NOT NULL,       -- product name

    price             numeric(8,2) DEFAULT '0.00' NOT NULL,     

    newprice numeric(8,2) DEFAULT '0.00' NOT NULL,     

    amount           integer   DEFAULT '0' NOT NULL,

       image             varchar(100) DEFAULT 'default_product.jpg' NOT NULL,  -- image(jpg,png,gif....)

       height             integer DEFAULT '320' NOT NULL,

       width             integer DEFAULT '320' NOT NULL,

       description      text ,    

       isonline    boolean DEFAULT 'false' NOT NULL,

     create_date  timestamp DEFAULT now() , 

     modify_date  timestamp DEFAULT now() ,  

    PRIMARY KEY (id),

    UNIQUE (id,pid),

    FOREIGN KEY (pid) REFERENCES product_sort (id)

);

CREATE SEQUENCE   product_id_seq;

CREATE INDEX          product_id_index ON style (id);

 

CREATE VIEW vproduct AS

    SELECT p.id,ps.id as pid,ps.plist,p.pname,to_char(p.price,'999G999D99') as price,to_char(p.newprice,'999G999D99') as newprice,p.amount,p.image,p.height,p.width,p.description,

           CASE WHEN p.isonline=true THEN 'Y' ELSE 'N'       END       as isonline,

           to_char(p.create_date,'YYYY-MM-DD') as date

        FROM product_sort ps, product p

        WHERE ps.id = p.pid

        order by p.id;

       

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

--  'clientinfo'

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

DROP TABLE clientinfo;

DROP SEQUENCE       clientinfo_id_seq;

DROP INDEX              clientinfo_id_index;

DROP VIEW vclientinfo;

 

CREATE TABLE clientinfo (

    id                   integer DEFAULT nextval('clientinfo_id_seq') NOT NULL,

    uid                 integer   DEFAULT '1' NOT NULL,  -- with foreign key

    cname           varchar(20) DEFAULT '' NOT NULL,       -- link of friends

    telephone varchar(20) DEFAULT '' NOT NULL,      

    fax                varchar(20) DEFAULT '' NOT NULL,      

       email             varchar(50) DEFAULT '' NOT NULL,      

       address          varchar(50) DEFAULT '320' NOT NULL, 

       postalcode      varchar(50) DEFAULT '320' NOT NULL, 

       note       text              DEFAULT '' NOT NULL,

     create_date  timestamp DEFAULT now() , 

     modify_date  timestamp DEFAULT now() ,  

    PRIMARY KEY (id),

    UNIQUE (id),

       FOREIGN KEY (uid) REFERENCES siteuser (id)

);

CREATE SEQUENCE   clientinfo_id_seq;

CREATE INDEX          clientinfo_id_index ON style (id);

 

CREATE VIEW vclientinfo AS

    SELECT ci.id,ci.uid,su.username,ci.cname,ci.telephone as tel,ci.fax,ci.email,ci.address,ci.postalcode,ci.note,

    to_char(ci.create_date,'YYYY-MM-DD HH:MI:SS') as date

        FROM siteuser su, clientinfo ci

        WHERE su.id = ci.uid;       

 

CREATE OR REPLACE FUNCTION clientinfo_tri_func () RETURNS opaque AS '

--    DECLARE

--         user_id CONSTANT INTEGER := OLD.id;

      BEGIN

             IF TG_OP = ''DELETE'' THEN

                  Delete from prodorder where clientinfo_id = OLD.id;

           END IF;

    RETURN OLD;

      END;

' LANGUAGE 'plpgsql';

 

 

DROP TRIGGER clientinfo_tri on clientinfo;

CREATE TRIGGER clientinfo_tri

       BEFORE Delete ON clientinfo FOR EACH ROW

       EXECUTE PROCEDURE clientinfo_tri_func ();

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

--  'production order' 

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

DROP TABLE prodorder;

DROP SEQUENCE       prodorder_id_seq;

DROP INDEX              prodorder_id_index;

 

CREATE TABLE prodorder (

    id                   integer DEFAULT nextval('prodorder_id_seq') NOT NULL,

    pid                 integer   DEFAULT '1' NOT NULL,  -- foreign key

    amount           integer   DEFAULT '1' NOT NULL,

    clientinfo_id integer       DEFAULT '1' NOT NULL,  -- foreign key

     create_date  timestamp DEFAULT now() , 

     modify_date  timestamp DEFAULT now() ,  

    PRIMARY KEY (id),

    UNIQUE (id),

       FOREIGN KEY (pid) REFERENCES product (id),

       FOREIGN KEY (clientinfo_id) REFERENCES clientinfo (id)

);

CREATE SEQUENCE   prodorder_id_seq;

CREATE INDEX          prodorder_id_index ON style (id);

 

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

--  'drumbeating'

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

DROP TABLE drumbeating;

DROP SEQUENCE       drumbeating_id_seq;

DROP INDEX              drumbeating_id_index;

DROP VIEW vdrumbeating;

 

CREATE TABLE drumbeating (

    id                   integer DEFAULT nextval('drumbeating_id_seq') NOT NULL,

    uid                 integer   DEFAULT '1' NOT NULL,  -- with foreign key

    logourl          varchar(100) DEFAULT '' NOT NULL,      -- image(jpg,png,gif....)

       bannerurl varchar(100) DEFAULT '' NOT NULL,

       lheight            integer DEFAULT '60' NOT NULL,

       lwidth            integer DEFAULT '120' NOT NULL,

       bheight           integer DEFAULT '60' NOT NULL,

       bwidth           integer DEFAULT '468' NOT NULL,

       description      text ,    

     create_date  timestamp DEFAULT now() ,

     modify_date  timestamp DEFAULT now() ,

    PRIMARY KEY (id),

    UNIQUE (id,uid),

       FOREIGN KEY (uid) REFERENCES siteuser (id)

);

CREATE SEQUENCE   drumbeating_id_seq;

CREATE INDEX          drumbeating_id_index ON style (id);

 

CREATE VIEW vdrumbeating AS

    SELECT dr.id,su.username,dr.logourl,dr.bannerurl

        FROM siteuser su, drumbeating dr

        WHERE su.id = dr.uid;

               

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

--  'news' 

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

DROP TABLE news;

DROP SEQUENCE       news_id_seq;

DROP INDEX              news_id_index;

DROP VIEW vnews;

 

CREATE TABLE news (

    id                   integer DEFAULT nextval('news_id_seq') NOT NULL,

    uid                 integer   DEFAULT '1' NOT NULL,  -- with foreign key

    title        varchar(100) DEFAULT '' NOT NULL,      -- link of friends

    image            varchar(100) DEFAULT '' NOT NULL,            

    content           text              DEFAULT '' NOT NULL,   

     create_date  timestamp DEFAULT now() , 

     modify_date  timestamp DEFAULT now() ,  

    PRIMARY KEY (id),

    UNIQUE (id),

       FOREIGN KEY (uid) REFERENCES siteuser (id)

);

CREATE SEQUENCE   news_id_seq;

CREATE INDEX          news_id_index ON news (id);

 

CREATE VIEW vnews AS

    SELECT ns.id,ns.uid,su.username,ns.title,ns.image,ns.content,to_char(ns.create_date,'YYYY/MM/DD HH:MI:SS') as date

        FROM siteuser su, news ns

        WHERE su.id = ns.uid

        order by ns.id; 

 

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

--  'count' 

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

DROP TABLE count;

DROP SEQUENCE       count_id_seq;

DROP INDEX              count_id_index;

DROP VIEW vcount;

 

CREATE TABLE count (

    id                       integer DEFAULT nextval('count_id_seq') NOT NULL,

    uid                       integer   DEFAULT '1' NOT NULL,  -- with foreign key

    number               varchar(20) DEFAULT '' NOT NULL, 

    fontcolor             varchar(10) DEFAULT 'FFFFFF' NOT NULL,   

    backgroundcolor    varchar(10) DEFAULT '000000' NOT NULL,     

     create_date            timestamp DEFAULT now() ,      

     modify_date   timestamp DEFAULT now() ,  

    PRIMARY KEY (id),

    UNIQUE (id,uid),

      FOREIGN KEY (uid) REFERENCES siteuser (id)

);

 

CREATE SEQUENCE   count_id_seq;

CREATE INDEX          count_id_index ON count (id);

 

CREATE VIEW vcount AS

    SELECT c.id,su.username,c.number,c.fontcolor,c.backgroundcolor

        FROM siteuser su, count c

        WHERE su.id = c.uid;

       

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

--  'column_bar' 

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

DROP TABLE column_bar;

DROP SEQUENCE       column_bar_id_seq;

DROP INDEX              column_bar_id_index;

DROP VIEW vcolumn_bar;

 

CREATE TABLE column_bar (

    id                   integer DEFAULT nextval('column_bar_id_seq') NOT NULL,

    uid                 integer   DEFAULT '1' NOT NULL,  -- with foreign key

    colname        varchar(10) DEFAULT '' NOT NULL,       -- link of friends

    url                 varchar(50) DEFAULT '' NOT NULL,      

    title               varchar(50) DEFAULT '' NOT NULL,      

    image                   varchar(50) DEFAULT '' NOT NULL,      

    height                   varchar(50) DEFAULT '' NOT NULL,      

    width                   varchar(50) DEFAULT '' NOT NULL,      

    content                 text DEFAULT '' NOT NULL,    

     create_date  timestamp DEFAULT now() , 

     modify_date  timestamp DEFAULT now() ,  

    PRIMARY KEY (id),

    UNIQUE (id),

       FOREIGN KEY (uid) REFERENCES siteuser (id)

);

CREATE SEQUENCE   column_bar_id_seq;

CREATE INDEX          column_bar_id_index ON column_bar (id);

 

CREATE VIEW vcolumn_bar AS

    SELECT cb.id,cb.uid,su.username,cb.colname,cb.url,cb.title,cb.image,cb.content,to_char(cb.create_date,'YYYY-MM-DD HH:MI:SS') as date

        FROM siteuser su, column_bar cb

        WHERE su.id = cb.uid

        ORDER BY cb.id;

       

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

--  'guestbook' 

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

DROP TABLE guestbook;

DROP SEQUENCE       guestbook_id_seq;

DROP INDEX              guestbook_id_index;

DROP VIEW vguestbook;

 

CREATE TABLE guestbook (

    id                   integer DEFAULT nextval('guestbook_id_seq') NOT NULL,

    uid                 integer   DEFAULT '1' NOT NULL,  -- with foreign key

    name             varchar(20) DEFAULT '' NOT NULL,       -- link of friends

    email              varchar(50) DEFAULT '' NOT NULL,      

    telephone varchar(20) DEFAULT '' NOT NULL,      

    fax                varchar(20) ,

    homepage       varchar(50) ,

    title         varchar(50) DEFAULT '' NOT NULL,      

    content           text ,    

    style_id   integer   DEFAULT '1' NOT NULL,   

     create_date  timestamp DEFAULT now() , 

     modify_date  timestamp DEFAULT now() ,  

    PRIMARY KEY (id),

    UNIQUE (id),

       FOREIGN KEY (uid) REFERENCES siteuser (id),

       FOREIGN KEY (style_id) REFERENCES style (id)

);

CREATE SEQUENCE   guestbook_id_seq;

CREATE INDEX          guestbook_id_index ON guestbook (id);

 

CREATE VIEW vguestbook AS

    SELECT gb.id,gb.uid,su.username,gb.name,gb.email,gb.telephone as tel,gb.fax,gb.homepage,gb.title,gb.content,to_char(gb.create_date,'YYYY/MM/DD HH:MI:SS') as date

        FROM siteuser su, guestbook gb

        WHERE su.id = gb.uid

        ORDER BY gb.id;       

 

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

--  'Category' 

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

DROP TABLE Category;

DROP SEQUENCE       Category_id_seq;

DROP INDEX              Category_id_index;

DROP VIEW vCategory;

 

CREATE TABLE Category (

    id                   integer DEFAULT nextval('Category_id_seq') NOT NULL,

    Category         varchar(20) DEFAULT '' NOT NULL,

    description  text ,

    note        text ,

    remark          text ,

     create_date  timestamp DEFAULT now() , 

     modify_date  timestamp DEFAULT now() ,  

    PRIMARY KEY (id),

    UNIQUE (id,Category)

);

CREATE SEQUENCE   Category_id_seq;

CREATE INDEX          Category_id_index ON Category (id);

 

CREATE VIEW vCategory AS

    SELECT c.id,c.Category,c.description,c.note,c.remark,to_char(c.create_date,'YYYY-MM-DD HH:MI:SS') as date

        FROM Category c

        ORDER BY c.id;

  

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

--  'Region' 

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

DROP TABLE region;

DROP SEQUENCE       region_id_seq;

DROP INDEX              region_id_index;

DROP VIEW vregion;

 

CREATE TABLE region (

    id                   integer DEFAULT nextval('region_id_seq') NOT NULL,

    region      varchar(20) DEFAULT '' NOT NULL,

    description  text ,

    note        text ,

    remark          text ,

     create_date  timestamp DEFAULT now() , 

     modify_date  timestamp DEFAULT now() ,  

    PRIMARY KEY (id),

    UNIQUE (id,region)

);

CREATE SEQUENCE   region_id_seq;

CREATE INDEX          region_id_index ON region (id);

 

CREATE VIEW vregion AS

    SELECT pv.id,pv.region,pv.description,pv.note,pv.remark,to_char(pv.create_date,'YYYY-MM-DD HH:MI:SS') as date

        FROM region pv

        ORDER BY pv.id;   

 

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

--  'province'  VIEW

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

DROP VIEW vprovince;

CREATE VIEW vprovince AS

    SELECT pv.id,pv.region as province,pv.description,pv.note,pv.remark,to_char(pv.create_date,'YYYY-MM-DD HH:MI:SS') as date

        FROM region pv

        ORDER BY pv.id;       

       

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

--  'Country' 

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

DROP TABLE country;

DROP SEQUENCE       country_id_seq;

DROP INDEX              country_id_index;

DROP VIEW vcountry;

 

CREATE TABLE country (

    id                   integer DEFAULT nextval('country_id_seq') NOT NULL,

    country  varchar(20) DEFAULT '' NOT NULL,

    domain           varchar(2)  DEFAULT '' NOT NULL,

    Language varchar(20)  DEFAULT '' NOT NULL,

    description  text ,

    note        text ,

    remark          text ,

     create_date  timestamp DEFAULT now() , 

     modify_date  timestamp DEFAULT now() ,  

    PRIMARY KEY (id),

    UNIQUE (id,country)

);

CREATE SEQUENCE   country_id_seq;

CREATE INDEX          country_id_index ON country (id);

 

CREATE VIEW vcountry AS

    SELECT pv.id,pv.country,pv.domain,pv.description,pv.note,pv.remark,to_char(pv.create_date,'YYYY-MM-DD HH:MI:SS') as date

        FROM country pv

        ORDER BY pv.id;

 

begin;

 

insert into category(category) values('农业');

insert into category(category) values('交通运输');

insert into category(category) values('包装、印刷');

insert into category(category) values('食品');

insert into category(category) values('建筑与装饰');

insert into category(category) values('广告、策划');

insert into category(category) values('服装');

insert into category(category) values('工业设备');

insert into category(category) values('纺织');

insert into category(category) values('家居用品');

insert into category(category) values('信息咨询');

insert into category(category) values('电子');

insert into category(category) values('医药保健');

insert into category(category) values('商业代理');

insert into category(category) values('家用电器');

insert into category(category) values('艺术、工艺');

insert into category(category) values('服务业');

insert into category(category) values('电脑、软件');

insert into category(category) values('娱乐、休闲');

insert into category(category) values('经济技术合作');

insert into category(category) values('化工');

insert into category(category) values('摄影摄像');

insert into category(category) values('安全、保安');

insert into category(category) values('冶金矿产');

insert into category(category) values('体育用品');

insert into category(category) values('不动产');

insert into category(category) values('能源');

insert into category(category) values('办公、教育');

insert into category(category) values('库存积压');

insert into category(category) values('环保');

insert into category(category) values('媒体、传播');

insert into category(category) values('综合');

insert into category(category) values('域名注册');   

 

 

insert into region(region) values('安徽');

insert into region(region) values('北京');

insert into region(region) values('重庆');

insert into region(region) values('福建');

insert into region(region) values('甘肃');

insert into region(region) values('广东');

insert into region(region) values('广西');

insert into region(region) values('贵州');

insert into region(region) values('海南');

insert into region(region) values('河北');

insert into region(region) values('河南');

insert into region(region) values('黑龙江');

insert into region(region) values('湖北');

insert into region(region) values('湖南');

insert into region(region) values('江苏');

insert into region(region) values('江西');

insert into region(region) values('吉林');

insert into region(region) values('辽宁');

insert into region(region) values('内蒙古');

insert into region(region) values('宁夏');

insert into region(region) values('青海');

insert into region(region) values('山东');

insert into region(region) values('山西');

insert into region(region) values('陕西');

insert into region(region) values('上海');

insert into region(region) values('四川');

insert into region(region) values('天津');

insert into region(region) values('西藏');

insert into region(region) values('新疆');

insert into region(region) values('云南');

insert into region(region) values('浙江');

 

 

--insert into country(domain,country) values('','');

insert into country(domain,country) values('AL','阿尔巴尼亚');

insert into country(domain,country) values('DZ','阿尔及利亚');

insert into country(domain,country) values('AF','阿富汗');

insert into country(domain,country) values('AR','阿根廷');

insert into country(domain,country) values('AE','阿拉伯联合酋长国');

insert into country(domain,country) values('AW','阿鲁巴');

insert into country(domain,country) values('OM','阿曼');

insert into country(domain,country) values('AZ','阿塞拜疆');

insert into country(domain,country) values('EG','埃及');

insert into country(domain,country) values('ET','埃塞俄比亚');

insert into country(domain,country) values('IE','爱尔兰');

insert into country(domain,country) values('EE','爱沙尼亚');

insert into country(domain,country) values('AD','安道尔');

insert into country(domain,country) values('AO','安哥拉');

insert into country(domain,country) values('AI','安圭拉岛');

insert into country(domain,country) values('AG','安提瓜和巴布达');

insert into country(domain,country) values('AT','奥地利');

insert into country(domain,country) values('AU','澳大利亚');

insert into country(domain,country) values('MO','澳门特别行政区');

insert into country(domain,country) values('BB','巴巴多斯');

insert into country(domain,country) values('PG','巴布亚新几内亚');

insert into country(domain,country) values('BS','巴哈马');

insert into country(domain,country) values('PK','巴基斯坦');

insert into country(domain,country) values('PY','巴拉圭');

insert into country(domain,country) values('BH','巴林');

insert into country(domain,country) values('PA','巴拿马');

insert into country(domain,country) values('BR','巴西');

insert into country(domain,country) values('BY','白俄罗斯');

insert into country(domain,country) values('BM','百慕大群岛');

insert into country(domain,country) values('BG','保加利亚');

insert into country(domain,country) values('MP','北马里亚纳群岛');

insert into country(domain,country) values('BJ','贝宁');

insert into country(domain,country) values('BE','比利时');

insert into country(domain,country) values('IS','冰岛');

insert into country(domain,country) values('PR','波多黎各');

insert into country(domain,country) values('PL','波兰');

insert into country(domain,country) values('BA','波斯尼亚和黑塞哥维那');

insert into country(domain,country) values('BO','玻利维亚');

insert into country(domain,country) values('BZ','伯利兹');

insert into country(domain,country) values('BW','博茨瓦纳');

insert into country(domain,country) values('BT','不丹');

insert into country(domain,country) values('IO','不列颠印度洋属土');

insert into country(domain,country) values('BF','布基纳法索');

insert into country(domain,country) values('BI','布隆迪');

insert into country(domain,country) values('BV','布韦岛');

insert into country(domain,country) values('KP','朝鲜');

insert into country(domain,country) values('GQ','赤道几内亚');

insert into country(domain,country) values('DK','丹麦');

insert into country(domain,country) values('DE','德国');

insert into country(domain,country) values('TP','东帝汶');

insert into country(domain,country) values('TG','多哥');

insert into country(domain,country) values('DM','多米尼克');

insert into country(domain,country) values('DO','多米尼克共和国');

insert into country(domain,country) values('RU','俄罗斯');

insert into country(domain,country) values('EC','厄瓜多尔');

insert into country(domain,country) values('ER','厄立特里亚');

insert into country(domain,country) values('FR','法国');

insert into country(domain,country) values('TF','法国南部和南极州');

insert into country(domain,country) values('FO','法罗群岛');

insert into country(domain,country) values('PF','法属波利尼西亚');

insert into country(domain,country) values('GF','法属圭亚那');

insert into country(domain,country) values('VA','梵蒂冈');

insert into country(domain,country) values('PH','菲律宾');

insert into country(domain,country) values('FJ','斐济群岛');

insert into country(domain,country) values('FI','芬兰');

insert into country(domain,country) values('CV','佛得角群岛');

insert into country(domain,country) values('FK','福克兰群岛(马尔维纳斯群岛)');

insert into country(domain,country) values('GM','冈比亚');

insert into country(domain,country) values('CG','刚果');

insert into country(domain,country) values('CD','刚果民主共和国');

insert into country(domain,country) values('CO','哥伦比亚');

insert into country(domain,country) values('CR','哥斯达黎加');

insert into country(domain,country) values('GD','格林纳达');

insert into country(domain,country) values('GL','格陵兰');

insert into country(domain,country) values('GE','格鲁吉亚');

insert into country(domain,country) values('CU','古巴');

insert into country(domain,country) values('GP','瓜德罗普岛(法属)');

insert into country(domain,country) values('GU','关岛');

insert into country(domain,country) values('GY','圭亚那');

insert into country(domain,country) values('KZ','哈萨克斯坦');

insert into country(domain,country) values('HT','海地');

insert into country(domain,country) values('KR','韩国');

insert into country(domain,country) values('NL','荷兰');

insert into country(domain,country) values('AN','荷属安的列斯群岛');

insert into country(domain,country) values('HM','赫德和麦克唐纳群岛');

insert into country(domain,country) values('HN','洪都拉斯');

insert into country(domain,country) values('KI','基里巴斯');

insert into country(domain,country) values('DJ','吉布提');

insert into country(domain,country) values('KG','吉尔吉斯斯坦');

insert into country(domain,country) values('GN','几内亚');

insert into country(domain,country) values('GW','几内亚比绍');

insert into country(domain,country) values('CA','加拿大');

insert into country(domain,country) values('GH','加纳');

insert into country(domain,country) values('GA','加蓬');

insert into country(domain,country) values('KH','柬埔寨');

insert into country(domain,country) values('CZ','捷克共和国');

insert into country(domain,country) values('ZW','津巴布韦');

insert into country(domain,country) values('CM','喀麦隆');

insert into country(domain,country) values('QA','卡塔尔');

insert into country(domain,country) values('KY','开曼群岛');

insert into country(domain,country) values('CC','科科斯群岛');

insert into country(domain,country) values('KM','科摩罗');

insert into country(domain,country) values('CI','科特迪瓦');

insert into country(domain,country) values('KW','科威特');

insert into country(domain,country) values('HR','克罗地亚(赫尔瓦次卡)');

insert into country(domain,country) values('KE','肯尼亚');

insert into country(domain,country) values('CK','库克群岛');

insert into country(domain,country) values('LV','拉脱维亚');

insert into country(domain,country) values('LS','莱索托');

insert into country(domain,country) values('LA','老挝');

insert into country(domain,country) values('LB','黎巴嫩');

insert into country(domain,country) values('LT','立陶宛');

insert into country(domain,country) values('LR','利比里亚');

insert into country(domain,country) values('LY','利比亚');

insert into country(domain,country) values('LI','列支敦士登');

insert into country(domain,country) values('RE','留尼汪岛');

insert into country(domain,country) values('LU','卢森堡');

insert into country(domain,country) values('RW','卢旺达');

insert into country(domain,country) values('RO','罗马尼亚');

insert into country(domain,country) values('MG','马达加斯加岛');

insert into country(domain,country) values('MV','马尔代夫');

insert into country(domain,country) values('MT','马耳他');

insert into country(domain,country) values('MW','马拉维');

insert into country(domain,country) values('MY','马来西亚');

insert into country(domain,country) values('ML','马里');

insert into country(domain,country) values('MK','马其顿共和国');

insert into country(domain,country) values('MH','马绍尔群岛');

insert into country(domain,country) values('MQ','马提尼克岛');

insert into country(domain,country) values('YT','马约特岛');

insert into country(domain,country) values('MU','毛里求斯');

insert into country(domain,country) values('MR','毛里塔尼亚');

insert into country(domain,country) values('US','美国');

insert into country(domain,country) values('AS','美属萨摩亚');

insert into country(domain,country) values('VI','美属维尔京群岛');

insert into country(domain,country) values('UM','美属小奥特兰群岛');

insert into country(domain,country) values('MN','蒙古');

insert into country(domain,country) values('MS','蒙特塞拉特()');

insert into country(domain,country) values('BD','孟加拉国国');

insert into country(domain,country) values('PE','秘鲁');

insert into country(domain,country) values('FM','密克罗尼西亚');

insert into country(domain,country) values('MM','缅甸');

insert into country(domain,country) values('MD','摩尔多瓦');

insert into country(domain,country) values('MA','摩洛哥');

insert into country(domain,country) values('MC','摩纳哥');

insert into country(domain,country) values('MZ','莫桑比克');

insert into country(domain,country) values('MX','墨西哥');

insert into country(domain,country) values('NA','纳米比亚');

insert into country(domain,country) values('ZA','南非');

insert into country(domain,country) values('AQ','南极洲');

insert into country(domain,country) values('GS','南乔治亚和南桑德威奇群岛');

insert into country(domain,country) values('YU','南斯拉夫');

insert into country(domain,country) values('NR','瑙鲁');

insert into country(domain,country) values('NP','尼泊尔');

insert into country(domain,country) values('NI','尼加拉瓜');

insert into country(domain,country) values('NE','尼日尔');

insert into country(domain,country) values('NG','尼日利亚');

insert into country(domain,country) values('NU','纽埃');

insert into country(domain,country) values('NO','挪威');

insert into country(domain,country) values('NF','诺福克岛');

insert into country(domain,country) values('PW','帕劳');

insert into country(domain,country) values('PN','皮特克恩群岛');

insert into country(domain,country) values('PT','葡萄牙');

insert into country(domain,country) values('JP','日本');

insert into country(domain,country) values('SE','瑞典');

insert into country(domain,country) values('CH','瑞士');

insert into country(domain,country) values('SV','萨尔瓦多');

insert into country(domain,country) values('WS','萨摩亚');

insert into country(domain,country) values('SL','塞拉利昂');

insert into country(domain,country) values('SN','塞内加尔');

insert into country(domain,country) values('CY','塞浦路斯');

insert into country(domain,country) values('SC','塞舌尔群岛');

insert into country(domain,country) values('SA','沙特阿拉伯');

insert into country(domain,country) values('CX','圣诞岛');

insert into country(domain,country) values('ST','圣多美和普林西比');

insert into country(domain,country) values('SH','圣赫勒拿岛');

insert into country(domain,country) values('KN','圣基茨和尼维斯');

insert into country(domain,country) values('LC','圣卢西亚');

insert into country(domain,country) values('SM','圣马力诺');

insert into country(domain,country) values('PM','圣皮埃尔岛和密克隆岛');

insert into country(domain,country) values('VC','圣文森特和格林纳丁斯');

insert into country(domain,country) values('LK','斯里兰卡');

insert into country(domain,country) values('SK','斯洛伐克');

insert into country(domain,country) values('SI','斯洛文尼亚');

insert into country(domain,country) values('SJ','斯瓦尔巴群岛和扬马延');

insert into country(domain,country) values('SZ','斯威士兰');

insert into country(domain,country) values('SD','苏丹');

insert into country(domain,country) values('SR','苏里南');

insert into country(domain,country) values('SB','所罗门群岛');

insert into country(domain,country) values('SO','索马里');

insert into country(domain,country) values('TJ','塔吉克斯坦');

insert into country(domain,country) values('TH','泰国');

insert into country(domain,country) values('TZ','坦桑尼亚');

insert into country(domain,country) values('TO','汤加');

insert into country(domain,country) values('TC','特克斯群岛和凯科斯群岛');

insert into country(domain,country) values('TT','特立尼达和多巴哥');

insert into country(domain,country) values('TN','突尼斯');

insert into country(domain,country) values('TV','图瓦卢');

insert into country(domain,country) values('TR','土耳其');

insert into country(domain,country) values('TM','土库曼斯坦');

insert into country(domain,country) values('TK','托克劳');

insert into country(domain,country) values('WF','瓦利斯群岛和富图纳群岛');

insert into country(domain,country) values('VU','瓦努阿图');

insert into country(domain,country) values('GT','危地马拉');

insert into country(domain,country) values('VE','委内瑞拉');

insert into country(domain,country) values('BN','文莱');

insert into country(domain,country) values('UG','乌干达');

insert into country(domain,country) values('UA','乌克兰');

insert into country(domain,country) values('UY','乌拉圭');

insert into country(domain,country) values('UZ','乌兹别克斯坦');

insert into country(domain,country) values('ES','西班牙');

insert into country(domain,country) values('GR','希腊');

insert into country(domain,country) values('HK','香港特别行政区');

insert into country(domain,country) values('SG','新加坡');

insert into country(domain,country) values('NC','新喀里多尼亚');

insert into country(domain,country) values('NZ','新西兰');

insert into country(domain,country) values('HU','匈牙利');

insert into country(domain,country) values('SY','叙利亚');

insert into country(domain,country) values('JM','牙买加');

insert into country(domain,country) values('AM','亚美尼亚');

insert into country(domain,country) values('YE','也门');

insert into country(domain,country) values('IQ','伊拉克');

insert into country(domain,country) values('IR','伊朗');

insert into country(domain,country) values('IL','以色列');

insert into country(domain,country) values('IT','意大利');

insert into country(domain,country) values('IN','印度');

insert into country(domain,country) values('ID','印度尼西亚');

insert into country(domain,country) values('UK','英国');

insert into country(domain,country) values('VG','英属维尔京群岛');

insert into country(domain,country) values('JO','约旦');

insert into country(domain,country) values('VN','越南');

insert into country(domain,country) values('ZM','赞比亚');

insert into country(domain,country) values('TD','乍得');

insert into country(domain,country) values('GI','直布罗陀');

insert into country(domain,country) values('CL','智利');

insert into country(domain,country) values('CF','中非共和国');

insert into country(domain,country) values('CN','中国');

insert into country(domain,country) values('TW','中国台湾');

 

commit;

ROLLBACK;

 

17.3       安装脚本

17.3.1 setenv.sh

#=======================================================

# Author:Netkiller

# Script: setenv.sh

#=======================================================

 

SRCHOME=../src

BINARYHOME=../binary

RPMSHOME=../rpms

CONFHOME=../conf

# Install Portable Threads

PThreads=pth-2.0.0.tar.gz

 

# Shared Memory Allocation

SMemory=mm-1.3.0.tar.gz

 

APACHE_HOME=/usr/local/apache

APACHE=apache_1.3.27.tar.gz

MOD_SSL=mod_ssl-2.8.14-1.3.27.tar.gz

MOD_PERL=mod_perl-1.0-current.tar.tar

MOD_FASTCGI=mod_fastcgi-2.4.0.tar.gz

PHP=php-4.3.2.tar.gz

 

17.3.2 install.sh

#=======================================================

# Author:Netkiller

# Script:install.sh

#=======================================================

if [ -f setenv.sh ]; then

   . setenv.sh

fi

 

#rpms_location="$base_dir/"

 

POSTGRESQL=${RPMSHOME}

Install_PostgreSQL(){

    cd $POSTGRESQL

    rpm -Uvh --nodeps postgresql-libs-?.?.?-1PGDG.i386.rpm

    rpm -Uvh --nodeps postgresql-?.?.?-1PGDG.i386.rpm

    rpm -Uvh --nodeps postgresql-devel-?.?.?-1PGDG.i386.rpm

    rpm -Uvh --nodeps postgresql-server-?.?.?-1PGDG.i386.rpm

    rpm -Uvh --nodeps postgresql-contrib-?.?.?-1PGDG.i386.rpm

    rpm -Uvh --nodeps postgresql-docs-?.?.?-1PGDG.i386.rpm

    rpm -Uvh --nodeps postgresql-jdbc-?.?.?-1PGDG.i386.rpm

    rpm -Uvh --nodeps postgresql-pl-?.?.?-1PGDG.i386.rpm

    rpm -Uvh --nodeps postgresql-python-?.?.?-1PGDG.i386.rpm

    rpm -Uvh --nodeps postgresql-tcl-?.?.?-1PGDG.i386.rpm

    rpm -Uvh --nodeps postgresql-test-?.?.?-1PGDG.i386.rpm

    cd ..

    rpm -qa|grep post

}

 

Uninstall_PostgreSQL(){

    rpm -e --nodeps `rpm -qa |grep postgresql`

}

 

Status_PostgreSQL(){

    rpm -qa|grep postgresql

}

 

Install_Apache(){

    cd ${SRCHOME}

    tar zxf apache_?.?.??.tar.gz >/dev/null

    cd  apache_?.?.??

    ./configure --prefix=/usr/local/apache --enable-module=so

    make

    make install

    cd ..

    rm -rf apache_?.?.??

    echo "/usr/local/apache/bin/apachectl start" >> /etc/rc.d/rc.local

}

 

Install_PHP(){

    cd ${SRCHOME}

    tar zxf php-?.?.?.tar.gz

    cd php-?.?.?

    ./configure --prefix=/usr/local/php --with-apxs=/usr/local/apache/bin/apxs \

        --with-config-file-path=/usr/local/etc --enable-track-vars --with-xml \

        --with-pgsql --with-mysql \

       --with-ldap --enable-ftp --with-openssl --with-iconv --with-kerberos \

       --with-java=/usr/local/java

    make

    make install

    cp php.ini-dist /usr/local/etc/php.ini

    #LoadModule php4_module modules/libphp4.so

    #AddType application/x-httpd-php .php .php4 .php3 .phtml

}

 

Install_MySQL(){

    if ! rpm -qa|grep -q "mysql" ; then

       tar zxvf mysql-standard-4.0.12-pc-linux-i686.tar.gz  >/dev/null

       mv mysql-standard-4.0.12-pc-linux-i686 /usr/local/mysql

       cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld

       chkconfig mysqld reset

       chown mysql.mysql -R /usr/local/mysql

    else

        echo "mysql package is already installed"

    fi

#   echo "su mysql -c"cd /usr/local/mysql/ ;./configure">/dev/null">> /etc/rc.d/rc.local

}

 

Install_MySQL(){

cd ${RPMSHOME}

rpm -Uvh MySQL-server-4.0.13-0.i386.rpm

rpm -Uvh MySQL-client-4.0.13-0.i386.rpm

rpm -Uvh MySQL-devel-4.0.13-0.i386.rpm

rpm -Uvh MySQL-shared-4.0.13-0.i386.rpm

rpm -Uvh MySQL-shared-compat-4.0.13-0.i386.rpm

 

}

 

 

Install_Sun_J2sdk(){

    cd ${BINHOME}

    chmod 700 j2sdk-1_4_1_02-linux-i586.bin

    ./j2sdk-1_4_1_02-linux-i586.bin

    mv j2sdk1.4.1_02 /usr/local/java

    cp ../conf/profile.sh /etc/profile.d/java.sh

    chmod 755 /etc/profile.d/java.sh

}

 

Install_Tomcat(){

    cd ${BINARYHOME}

    tar zxvf tomcat-4.1.24.tar.gz >/dev/null

    mv jakarta-tomcat-4.1.24 /usr/local/jakarta-tomcat

#    echo "/usr/local/jakarta-tomcat/bin/startup.sh" >> /etc/rc.d/rc.local

}

 

Install_Ant(){

    cd ${BINARYHOME}

    tar zxvf apache-ant-1.5.3-1-bin.tar.gz >/dev/null

    mv apache-ant-1.5.3-1 /usr/local/apache-ant

}

 

Install_Zhcon(){

 

    tar zxvf zhcon-?.?.?.tar.gz

    ./configure

    make

    make install

}

 

usage()

{

    echo "Usage: $0 {install|uninstall|status|reinstall|config|} [base_dir]"

    echo "Usage: $0 {apache|php|mysql} [base_dir]"

    echo "Usage: $0 {j2sdk|tomcat|ant|jdbc|postgresql} [base_dir]"

#  echo "base_dir        the location of install disk, optional"

}

 

# --- main process starts ---

 

case "$1" in

  install)

        banner

        install

        ;;

  uninstall)

        banner

#        uninstall

#Uninstall_PostgreSQL

        ;;

  status)

        banner

        status

        ;;

  reinstall)

        banner

        uninstall

        install

        ;;

  config)

        banner

        config

        ;;

  apache)

       Install_Apache

       ;;

  php)

       Install_PHP

       ;;

  mysql)

        Install_MySQL

        ;;

  j2sdk)

       Install_Sun_J2sdk

       ;;

  tomcat)

       Install_Tomcat

       ;;

  ant)

       Install_Ant

       ;;

  postgresql)

       Install_PostgreSQL

       ;;

  *)

        usage

        exit 1

esac

 

# --- main process ends ---

17.4       附件

文档中用到的一些相关的文件可以去主页上下载

http://linux.9812.net/

17.5       其它

Mailing Lists

http://groups.yahoo.com/group/pgsql/

 

Post message: pgsql@yahoogroups.com

Subscribe:  pgsql-subscribe@yahoogroups.com

Unsubscribe:  pgsql-unsubscribe@yahoogroups.com

List owner:  pgsql-owner@yahoogroups.com

 

国产数据库:

http://www.dm2.com.cn/

 

latex

http://learn.tsinghua.edu.cn/homepage/2001315450/tex_frame.html

 

18             参考资料

http://www.postgresql.org

http://www.pgsqldb.org/pgsqldoc-cvs/index.html

http://www.oasis-open.org/

       http://www.linuxfocus.org/

http://www.opendocspublishing.com/

http://www.casestudio.com/  一个数据设计工具

http://www.datanamic.com/ 一个数据设计工具

http://www.commandprompt.com/

http://www.commandprompt.com/ppbook/

http://www.tldp.org/

 

 

 

19             版本、声明

声明:您可以随意转载,但请保持文档完整。

转载请注明作者的主页地址,因为文档经常更新,这样读者可以看到最新内容。

 

文件状态

文件标识

PostgreSQL 实用实例参考》

o草稿

当前版本

2.0

þ正式发布

   

Netkiller(陈景峰)

þ正在修改

开始日期

2003107星期二

2003-12-5

 

版本历史

版本/状态

作者

参与者

起止日期

备注

1.0.0/草稿

陈景峰

符乃晴

尚丽娜

2003-10-15

校对

1.1.0/修改

 

2003-10-17

PostgreSQL RPM 包安装

附件中安装脚本
Jsp/Java
汉字编码问题

1.1.1

 

2003-10-22

查询, 多个字段组合约束

1.1.2

 

2003-10-23

substring()函数截取部分汉字

PHP 字符编码问题

1.1.3

 

2003-10-24

共享内存

最大连接

1.2.3

 

2003-10-25

SSL,SSH

1.2.3

朱陪江

2003-10-29

校对

1.3.3

 

2003-11-1

序列

约束

1.4.3

 

2003-11-11

RPM 安装

1.4.4

 

2003-11-12

例子-分类目录

1.5.0

 

2003-11-25

函数,过程实例

1.6.0

 

2003-11-28

日期时间
“::”转换数据
性能提升-硬件

1.6.1

 

2003-11-29

用户,组,认证

1.6.2

 

2003-12-1

DWJSP开发环境
Java
汉字编码问题web.xml方案

正式/修正2.0.0

 

2003-12-5

Jbuilder+weblogic+postgresql

2.1.0

 

2003/12/12

取出字符如果超过20个在后尾加“…”
保证备份数据的安全-PGP/GPG加密

2.2.1

 

2003-12-27

数据库性能测试

2.2.0

 

2004-2-24

硬盘性能
过程例子
游标例子
解发器例子
检查check例子
替换字符串例子

2.3.0

 

2004-2-26

开发篇

2.3.1

 

Vvlinux(会游泳的鱼)

2004-3-4

校对

2.3.2

 

 

2004-3-5

文件存入数据库中

 

 

 

2004-3-12

函数返回结果集

 

 

 

2004-4-12

修改汉字编码

 

 

qzhou9887

2004-4-13

非常感谢qzhou9887校对文档

 

 

 

2004-5-20

Tomcat 连接池的配置方法

 

 

 

2004-6-30

修改视图小节

 

 

 

2004-7-8

APT安装