PostgreSQL實例參考
陳景峰(netkiller)
經過三個月的努力《PostgreSQL 實用實例參考》正式版終於推出了。因為最近換了工作,新公司的工作也很忙所以文檔進展很慢,從最初幾十頁寫到現在200頁的文檔,每天寫文檔的時間越來越少,有時一周也就只寫2頁,甚至一週一字未對。
正式版推出了,然後就是不斷的修正。可能這段時間《PostgreSQL
實用實例參考》更新會更慢些。因為我還有其他文檔要寫:《OpenLDAP
文檔》、《PHP
+ Corba + Python文檔》、《JBuilder + Weblogic + PostgreSQL 開發EJB》。。。。。
文檔中所有例子,都是在工作總結出來的,如有錯誤請指正。本人愛寫錯別字(哈哈)如果你發現了有錯字,請發郵糽ang=EN-US style='mso-fareast-font-family:PMingLiU;mso-fareast-language:ZH-TW'>netkiller(at)9812(dot)net修正文檔。
300頁之後不再推出HTML格式的文檔了,之後的文檔以PDF、PS(PostScript)格式為主,我是使用Microsoft
Word寫文檔,處理300頁的文檔很困難,在保存文檔或將doc檔轉成其他格式的檔時經常會出現無回應。我也考慮過使用docbook
/ latex,或Page Maker。前者非所見即所得,要用戶使用XML撰寫,通過make一類的命令可以生成多種格式的文檔,docbook也是UNIX手冊的標準格式。後者Page
Maker不用說了,Adobe出品,生成PDF更好些。
這是我第一次寫一篇如此長的文檔,沒有經驗,寫的不好,不敢稱為“書”,所以我叫它“文檔”。
文檔面向有一定資料庫基礎用戶。在這裏我假設你對資料有一定認識,能夠使用create創建資料與表,能夠使用select、insert、update等語句操作資料庫記錄。
不管是誰,我希望這本文檔都能對你有所幫助。
第一章 主要介紹PostgreSQL
第二章 是開發中遇到的一些問題
附錄中一些SQL腳本文件,可供用戶參考。
邊看、邊做、邊試驗,然後總結,多動腦。有問題先查查這本文檔,如果文檔中沒有提到,再考慮其他方式,或與我聯繫。
作者資訊:
陳景峰,昵稱:netkiller, UNIX like愛好者,研究方向群集系統、網路安全、資料倉庫與資料挖掘、LDAP、J2EE,Corba,企業解決方案。
主頁地址:
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:
2.4 PostgreSQL
8.0 beta for windows版本安裝
13.2.3.1 setCharacterEncoding()
方案
13.3 Tomcat JNDI Datasource 配置
13.5.1 Create Java
Entity Bean (not EJB CMP)
14.2 set
CLIENT_ENCODING TO 'GB18030';方案...
14.5 在標準I/O上使用 Linux
iconv 命令方案
15.1 Macromedia
Dreamweaver MX 2004 JSP開發環境的配置
15.4 JBuilder +
Weblogic + PostgreSQL開發環境
16.5 PostgreSQL
RPM 包安裝後,為何沒有5432埠
16.6 PostgreSQL
7.4.2 rhel3(高級伺服器版,俗稱AS3)
16.9 OpenLDAP-PostgreSQL
HOWTO
PostgreSQL Wins Linux Journal Editors
Choice Award
Posted on
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.
我接觸PostgreSQL是2000年,但項目中使用PostgreSQL是2003年,2000當時應該是5.x,6.x版本我並沒有深入地研究這個資料庫,還是主要使用MS Sql Server 7/2000 、Oracle 8。
因為很多企業難以支付MS Sql Server 7/2000 、Oracle 8這筆費用,所以Free Database是最佳選擇。但大多免費的資料庫,功能有限、性能也差,跟本不能滿足我們的需求。
有一段時間裏我們使用MySQL,實在不好用,功能太少,它只實現了SQL92
中不到30%的功能。除了select、insert、update、delete還有什麼功能?一味強調速度快,真的是這樣嗎?MySQL資料量增加很大時,速度下劃很快。
幾萬條記錄時速度最快,幾十萬記錄時速度不同了,幾百萬時就開始慢了。PostgreSQL 隨著資料量增大時,速度變化差距不象MySQL那麼大。
有些朋友在網上說(觸發器、游標、外鍵、視圖)影響性能。這裏要說明一下如果適當的使用視圖、子查詢、觸發器、游標……會讓你開發更輕鬆。
注:關於游標,很多SQL書中這樣寫“游標就是指向一行的指標”在PostgreSQL有些不同,它是返回一個結果集,對結果集next 操作返回一行。
Phpbuilder上有一篇文章是寫PostgreSQL 與 MySQL 大家可以去看看。
1.
技術領先:
很多新技術都是它提出的
如:pl過程語言.在其他資料系統中都有自己的專用PL語言。而PostgreSQL中支援很多種PL語言(pl/tcl,pl/python,pl/perl,pl/php,pl/shell/pl/pgsql,pl/java.......)
還有面象物件(ORDBMS)他實現的也很早.
他的資料類型支援很全.如幾何型,陣列...在其他RDBMS中是沒有的.
總是有新的技術、思想加入其中
2. 在開源ORDBMS中PostgreSQL功能最強.也最完善
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詳細請登錄網站查看。
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
/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]$ |
[root@linux software]# ls -1 postgresql- postgresql-contrib- postgresql-debuginfo- postgresql-devel- postgresql-docs- postgresql-jdbc- postgresql-libs- postgresql-pl- postgresql-python- postgresql-server- postgresql-tcl- postgresql-test- [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- postgresql- postgresql-python- postgresql-contrib- postgresql-jdbc- postgresql-server- postgresql-debuginfo- postgresql-libs- postgresql-tcl- postgresql-test- postgresql-pl- postgresql-docs- [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 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 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 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`
安裝一定要加—nodeps,ls
-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
Apt 是Debian Linux安裝風格
去下而網站可以找到APT套裝軟體
輸入: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- warning:
apt- 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 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 Fetched
609kB in 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 |
PostgreSQL 8.0 beta版windows版本安裝包下載地址:
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
Ø 開始à所有程式àPostgreSQL 8.0-beta1àpgAdmin III
pgAdmin III的一般操作順序是:
1. 新建一個用戶(用於tcp/ip socket的PostgreSQL帳號,而非系統用戶postgres是一個系統帳號,不能用於tcp/ip連接,它是用來管理資料的用戶)
2. 新建一個表空間,用於存放資料
3. 新建一個資料庫實例
4. 新建一個PL過程語言(一般是pl/pgsql)
5. 新建一個模式(Schema)
6. 創建表,視圖,觸發器等等
網上有很多朋友問我,PostgreSQL 8.0的psql在那,他默認打開template1資料庫,如何打開其他資料等等問題。
步驟,開始à所有程式àPostgreSQL 8.0-beta1à psql to template1進入PostgreSQL 8.0 psql控制臺,輸入postgres用戶的密碼登錄。
使用“\l”列出資料
使用“\c”連接到其他資料庫。
\c 資料庫
資料庫所有者,接提示輸入密碼即可。
Password: Welcome
to psql.exe 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=# |
1. 開始à控制面板à管理工具à數據源 (ODBC)
2. 單擊“添加”按鈕
3. 列表中選擇PostgreSQLà單擊“完成”按鈕
4. 單擊Save保存
5. 單擊“確定”按鈕
[root@linux root]# psql -h 192.168.0.254 -U chen netkiller Password: Welcome
to psql 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=# |
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=> |
腳本功能是,首先備份資料庫、然後打包、壓縮為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]# |
[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]# |
資料庫中的內容有些是不能提供給用戶的,如其它用戶的資料,密碼。在資料庫中的資料,你可以通過許可權來限制用戶操作。將資料庫備份(導出)到本地SQL文字檔案中(xxxx.sql包括DDL,DML) ,一但備份落入他手,後果不可設想,他很容易得用你的資料,因為你備份的資料是文字檔案,沒有任何加密措施。
這裏介紹GnuPG 以下簡稱GPG,GPG與PGP相容。由於PGP使用了許多專利演算法,屬於美國加密出口限制之列。而GnuPG是GPL軟體。
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 v 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 v mQGiBD/ZuhgRBACBRuWYRtJ8+8VmnYUgNy7TS/nVl0sHrsGD2kgIWVUuZYgKSUoM vT4MUHWdd52yesovAV61qsVCfUz+O76ovhQrUzv4jp+bkIOKcc7E07Z2MZmc1BqR +Gavb3gsJM6DmOLcRiU 5WS1CIGnvGDFUiGY6VhdamsD/jdiqSIcwFt2x6VMjzeWkHHM5wNYHuBJnp9DPd rn3uEq+tSex8ZXRyzHGj+N4SKezhEYal1D762kDxjGYltk5Xce5dXQBn9fulEDhD OzOp78GvIvJ/m33D/J6xECbXUz8XsFFhxJ6QnVh/RURY+EvHE1Tmz/fRG69Rc1Uc JBqCA/0faHEkyDv+FWEsmFKjflDNqN5NHtdWzJZQZKD1Vb64oJ5CK6r fVpfk5OVXnfMSpLKc7aGA9X+mUMuNrGRNzzzsmVK6urWQovL/BfeukMgDBZXkLd8 fO7aA53XeBhmVC49atFPH8hsOeMdd0mombrzcvKczjMp0ThP9rQzbmV ICjpmYjmma/ls7DnmoTlr4bpkqUpIDxuZXRraWxsZXJAOTgxMi5uZXQ+iFkEExEC ABkFAj/ZuhgECwcDAgMVAgMDFgIBAh4BAheAAAoJEKwHyHOwCEfFBqMAn0HoK9Xc zvzVkFODVZPWUskzwAhqAJ4rbgYEjSN1/CrdUBzTMtecGu9P+7kBDQQ/2boaEAQA zhoIDY866/GWUUpuarpVKcN1ijn+ 6V4zZwP5PcBScYxQpM 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
(郵約tyle='mso-bookmark:AEN1755'>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]$ 因為每天淩晨1:00-5:00這段時間訪問的人比較少,所以我選擇伺服器端每天淩晨3:00開始備份,您也可以在其他時間段備份,根據您的需求而定。 [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 用戶端每天零晨4:00點開始下載備份資料。為什麼是4:00下載呢?因為伺服器備份要一段時間,如果伺服器還沒有備份完成,這邊是不能下載的。所以計畫在3:00伺服器開始備份,4:00時用戶端開始下載已經備份好的資料。 [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 [root@linux root]# su postgres bash-2.05b$ psql member -f pgsql-backup.xxxx-xx-xx.xx:xx:xx.dmp 在 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. 跟據你的需要來配置最大連接數,系統默認是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:00優化、3:00備份、4:00下載備份資料 [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]# 1.
分組插入資料 向資料庫做大量Insert 操作時(注:非導入,在某些特殊環境中要做大量的插入操作,而 不是導入資料),如你有10000條記錄要插入到資料庫中,建議你將10000記錄分組插入 第一組 begin; insert
into …… insert
into …… insert
into …… ……. 1000條insert
into ……. insert
into …… commit; 第二組 begin; insert
into …… ……. 1000條insert
into ……. insert
into …… commit; 第十組 begin; insert
into …… ……. 1000條insert
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.
操作之後使用重建索引 1.
一般伺服器 PC伺服器有條件建議使用SATA(串列)硬碟。 沒有條件可以買時下最快的ATA硬碟(也不是越快越好,還要穩定) 正常情況下幾塊ATA 66 (5400rpm)硬碟做RAID 0,要比一塊ATA100(7200rpm)還要快。 RAID
是解決伺服器硬碟瓶頸最佳方案。建議使用RAID0,RAID0速度最快,不安全,但速度誘人,只要做好備份,是沒有問題的。 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,14或16 6,8,10,12,14或16 跨越3個陣列 6 9,12或15 9,12或15 跨越4個陣列 8 12或16 12或16 可用容量 最小 中間 中間 減少容量 50% 每個陣列中一個磁片 每個陣列中一個磁片 讀性能 中間 高 高 隨機寫性能 中間 最低 低 連續寫性能 中間 低 最低 典型應用 允許故障高速度小檔、亂數據寫入 允許故障高速度大檔、連續資料傳輸 允許故障高速度小檔、隨機資料傳輸 可用容量 磁片容量的50% n-2/2的磁片容量。其中n為磁片數目 n-2/n的磁片容量。其中n為磁片數 3.
網路,光纖存儲我沒使用過,這裏也不談了。 注: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: CPU:P4
2.6G 硬碟: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: CPU:P4
2.4G 記憶體:1GB ATA RAID 0 :120G(ATA100)*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是半年前配置的,從對比可以看出兩塊ATA100的RAID0,與單塊ATA133。前者慢,但我想如果用4塊硬碟做RAID 0 性能一定會超過A 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:
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 lang=ZH-TW style='font-size:9.0pt;font-family:PMingLiU;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman";mso-fareast-language:
ZH-TW'>駯‑Bd煒i$??ギ箿L)郟?v趬?)鈕媧徨?髛T詄?$
看來是二制的,哈哈。 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:
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.key,server.crt)必須放在data目前中,即與postgresql.conf同在一個目錄中 2.
server.key許可權必須設為600,所有者為postgres,否則會提示你許可權或用戶、組不正確。 3.
刪除privkey.pem文件 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 本地埠:連接PostgreSQL的host: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環境: IP:192.168.0.1 功能變數名稱:client.9812.net server2環境: IP:192.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 控制臺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 current_date netkiller=>
select current_date; date ------------ 2003-11-28 (1 row) netkiller=> current_time netkiller=>
select current_time; timetz -------------------- 19:38:47.270235+08 (1 row) netkiller=> current_timestamp netkiller=>
select current_timestamp;
timestamptz ------------------------------- 2003-11-28 19:39:25.548505+08 (1 row) netkiller=> 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=> 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) netkiller=>
select to_date('2003-12-6','yyyy-mm-dd')+12 ; 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上的文檔。 PostgreSQL是支援“區域”,“字元集支援”的,允許你使用本區域的字元集做為欄位名。但要注意,你的終端要支援該字元集支援。我這裏使用UNICODE,EUC_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都支援非英文的編碼。 PostgreSQL
資料之間的轉換可以使用“::”操作符。 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=# -- ------------------------------------------------------ -- '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; 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) 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) 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) CREATE
SEQUENCE region_id_seq INCREMENT n2 START n1; 例子1: 有這樣一個需求,在很多電子商務網站上都要對用戶進行誠信評估,誠信分為五級(五個星),這樣就要求某欄位插入的資料0,1,2,3,4,5。“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" 顯示的有note欄位為空的記錄: member=>
select * from vregion where note is null; 這個例子對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唯一約束成功。 UNIQUE
(rid,uid)中有多個參數,是對rid,uid組合約束。 例如: 1,1 1,2 是正確的 1,1 2,1 也是正確的 2,1 1,1 2,2 1,2 1,1 不正確的不允許插入資料“1,1”,資料“1,1”出現了兩次,所以要同時滿足rid,uid兩個條件。 三個欄位以上組合: 1,1,1 1,1,2 1,2,1 2,1,2 2,1,1 2,2,2 正確可以插入資料 1,2,1 2,1,2 2,2,1 1,1,2 2,2,1 “2,2,1”,“2,2,1”出現兩次,違反約束條件,所以不能再次插入資料“2,2,1”。 --
====================================================== --
'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 這個例子對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 下面書寫方式,推薦第二種,比較清晰。 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) ); 下面第前兩種寫法不推薦。第三、四種寫法較清晰。 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; 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 實現一個無限向下分類的目錄,例如: 電腦與互聯網 免費資源 軟體下載(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 CASCADE當pk刪除時關聯的fk自動刪除 name 目錄名 status 狀態true可用,false不可用 created 創建時間 modified 修改時間 注意: 因為使用了關聯欄位,所以不能在create
table 中使用 因為插入記錄做參考表中的“id”欄位,創建表的中沒有資料,所以無法插入資料。 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顯示器 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顯示器 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.
刪除子目錄:電腦/顯示器 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。 分類目錄的例子中使用了ON
DELETE CASCADE,方便了操作,但也有危險。如果不用ON DELETE CASCADE而用程式來實現,需要使用遞迴演算法,非常麻煩。 一些用戶為了使某些模組的表看起來清晰,一般他們採用“模組名_表名”: Auth_user Auth_group Bbs_topic Bbs_message PostgreSQL不必這樣命名,可以使用Schema(模式)如: Auth.user Auth.group Bbs.topic Bbs.message CREATE SCHEMA your_schema; 例: CREATE SCHEMA btob; CREATE SCHEMA auction; DROP SCHEMA your_schema; 刪除模式,並且同時刪除模式下的(表,視圖,觸發器,過程……) DROP SCHEMA your_schema CASCADE; 例: DROP SCHEMA btob CASCADE; DROP SCHEMA btob CASCADE; 查看當前模式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"); 在關聯資料庫中,關係能防止冗餘的資料。例如,如果正在設計一個資料庫來跟蹤有關書的資訊,而每本書的資訊(如書名、出版日期和出版商)都保存在一個名為
titles 的表中。同時還有一些想保存的有關出版商的資訊,例如出版商的電話號碼、地址和郵遞區號。如果將所有這些資訊都保存在
titles 表中,則對於某個出版商出版的每本書,出版商的電話號碼將是重複的。 一個更好的解決方案是,單獨在一個名為
publishers 的表中只保存一次出版商資訊。然後在 titles 表中設置指標,以引用
publishers 表中的項。 若要確保資料同步,可以在
titles 表和 publishers 表之間強制引用完整性。引用完整性關係能確保某個表中的資訊與另一個表中的資訊相匹配。例如,titles
表中的每個書名必須和
publishers 表的特定出版商相關聯。不能在資料庫中添加資料庫中不存在的出版商的書名。 為更好地理解表關係,請參見: l
表關係類型 表與表之間存在三種類型的關係。所創建的關係類型取決於相關聯的列是如何定義的。 n
一對多關係 n
多對多關係 n
一對一關係 l
引用完整性概述 l
表關係類型 關係是通過匹配鍵列中的資料而工作的,而鍵列通常是兩個表中具有相同名稱的列。在大多數情況下,關係將一個表中為每個行提供唯一識別字的主鍵與另一個表中外鍵內的項相匹配。例如,通過在
titles 表的 title_id 列(主鍵)和 sales 表的 title_id 列(外鍵)之間創建一個關係,可以使銷售額與特定的銷售書名相關聯。 PostgreSQL本身沒有GUI(圖形用戶介面)管理工具,其他GUI工具也沒有E-R圖功能,如pgAdmin
III。這裏我給在各位介紹一個很好的資料庫設計工具“CASE Studio 2”, 1.
實體關係設計 2.
能過E-R圖產生SQL(DDL)腳本 3.
已經存在資料庫的逆向工程 4.
產生非常詳細的HTML和RTF報告 5.
用戶定義Add-ins和範本 6.
版本管理,Galery,To-Do列表 7.
資料流程程設計 8.
介面見附錄。
一對多關係是最常見的關係類型。在這種關係類型中,表
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; 在多對多關係中,表 A 中的一行可與表
B 中的多行相匹配,反之亦然。通過定義稱為連接表的第三方表創建這樣的關係,該連接表的主鍵包括表 A 和表
B 中的外鍵。 例如,authors 表和
books 表是多對多關係,該關係通過從這些表中的每個表與 bookauthors 表的一對多關係定義。bookauthors
表的主鍵由
author_id 列(authors 表的主鍵)和 book_id 列(books 表的主鍵)組成。 注意:Case Studio 2 產生的SQL(DDL)腳本並不完全正確。所以還要加以修改才可以使用。
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; 在一對一關係中,表 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; 引用完整性是一種規則系統,這些規則可確保相關表中各行間關係的有效性,並確保不會意外刪除或更改相關的資料。 在強制引用完整性時必須遵循以下規則: 如果在相關表的主鍵中不存在某個值,則不能在相關表的外鍵列中輸入該值。但是,可以在外鍵列中輸入空值。例如,在
employee 表中沒有包括某職員,則不能指明分配給該職員的工作,但是可在 employee 表的 job_id 列輸入空值來指明沒有給該職員分配工作。 如果在相關表中存在與某行匹配的行,則不能從主表中刪除該行。例如,如果在
employee 表中給多個職員分配了由 jobs 表中某行所代表的工作時,則不能刪除該行。 當主表的某行有相關行時,則不能更改主鍵值。例如,如果將
jobs 表中的一項工作分配給某職員,則不能從 employee 表中刪除該職員。 當滿足下述所有條件時,可以設置引用完整性: 1.
主表中相匹配的列是主鍵或具有唯一約束 。 2.
相關列具有相同的資料類型和長度。 3.
兩個表屬於同一個資料庫。 4.
資料庫關係圖中的已強制關係和未強制關係 在資料庫關係圖中創建關係線將在相關表上創建外鍵約束,從而自動強制引用完整性。在資料庫關係圖中,已強制關係用實線表示。例如:
在關係圖中,未強制關係用虛線表示,這種關係的外鍵約束被禁用。例如:
下面是一個子查詢的例子表groupmember、rolemember是存儲組成員、角色成員的表。 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) (組ID為3的用戶列表) 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.
取用戶id,select id
from vuser where userid='sysop' 2.
取組名id,select 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號難懂,不易查看,這裏使用了一個視圖。 要截取漢字的首要條件是資料庫編碼必須是UNICODE。UNICODE中英文一個字母=中文一個漢字長度。 如果使用非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) 如果讓你對表中的某一列求和,你可能會想到使用sum()函數。 Select num(field) from table; 或 Select num(field) from table where field …..; 如果我在表中選擇一些記錄,這記錄之間沒有規律可循,讓你計算出這組資料的的和。 你可能馬上想到用一個迴圈,然後相加結果,而不是使用sum()。 例如:我要求id等於1,4,10,8,2這幾個記錄的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=> 在網上很多朋友問我,如何合併兩個結構一樣的表,答案有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 將兩個表中重複的行,只輸出一次。如果想全部輸出可以使用 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 視圖 試圖是關係型數據庫系統提供給用戶以多種角度觀察資料庫中資料的重要機制。 試圖是從一個或幾個基本表(或視圖)導出的表,它與基本表不同,是一個虛擬表。資料庫中只存放視圖的定義,而不存放視圖對應的資料,這些資料仍存放在原來的基本表中。所以基本表中的資料發生變化時,從視圖中查詢出的資料也就隨之改變了。也就是說,試圖就像一個視窗,透過它可以看到資料庫中自己感興趣的資料及變化。 試圖一經定義,就可以像基本表一樣被查詢、被刪除,我們也可以在一個視圖之上再定義新的視圖,但對視圖的更新(添加、刪除、修改)操作則有一定的限制。 本節專門討論視圖的定義、操作及優點。 試圖的作用: 1.
視圖能夠簡化用戶的操作 2.
視圖使用戶能以多種角度看待同一資料 3.
視圖對重構資料庫提供了一定程度的邏輯獨立性 4.
視圖能夠對機密資料提供安全保護 我在工作中發現很多程式師開發資料應該程式。SQL語句寫了五六行,每行最少100個字元。好比如下: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 這麼一大堆 !@%%#@%@^#$&$&%*&^*%^(&)(*) faint 寫這麼長主要的操作是“,”號join操作。 我的習慣是先使用VIEW做第一次的過濾,然後在做第秎ang=EN-US> 這是一個最基本用法。這裏主要用於格式化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; --
====================================================== --
'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,'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; 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 | 2003年09月24日
11:23:29 | 2003年09月24 11時23分29秒 <center>2</center> | <font
color=red>admin</font> | chen | chen | 禁用 |
chen@chen.com | xxxxxxx | xxxx | 2003年09月24日
11:23:29 | 2003年09月30 11時23分29秒 下面有一下更大膽的用法。 --
====================================================== --
'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 就可以,而不必關心頁面與程式。 下面是一個使用漢字做欄位名的例子,輸出類似表格: 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=# 實現方法: 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; 在下面的例子中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; 在其他資料中分別存在過程與函數,它們的功能沒有區別,為什麼要分為成過程與函數呢。因為過程是沒有返回值的,而函數是要通過RETURN返回值的。返回值可以是任意一個符合SQL
資料類型的值或結果集,在PostgreSQL中過程與函數都是使用CREATE FUNCTION語句來創建。 我們創建一個名為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) 這裏有兩個例子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); 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'; 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'; 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,因為游標更方便。 例子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'; http://developer.postgresql.org/~petere/pgplsh/pgplsh-1.0-7.3.tar.gz 這裏有兩上規則例子role_rule、group_rule。它們功能都是刪除其他表中受外鍵約束的記錄。用觸發器也可以實現同樣功能,觸發器繁瑣,要寫一個過程。而規則靈巧得多。 如果是單一的Select、Update、Insert、
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; -- ====================================================== --
'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; 下面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; 這是一個多個觸發器使用同一個函數例子。 觸發器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表中插入記錄時同時向company、count、drumbeating……表中增加一條記錄。 --
------------------------------------------------------ -- '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 (); 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 定時觸發器與週期觸發器。的不同是定時,只運行一次,而週期是有規律的運行。 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
今晚8:00運行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天后的淩晨1:00運行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 l
每天的淩晨3:00運行一次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
每個月的星期一17:00點運行 function.sh 0 17 * * mon root
/usr/local/pgsql/function.sh 例子不再舉了,請參考作業系統手冊。 例子1: Id other Status 1 False 2 False 3 False 4 True 需求:要求插入資料之前,將資料庫中某個表的status些欄位值設為false,然後再插入,使表中最後一條記錄的status欄位為true。 這個例子可以應用在競價拍賣的過程中。Status為false表示出局,為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=> 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 這是一個在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|登錄 例子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; 對資料進行批量的插入、更新、刪除操作,建議使用事務處理。 1.
降低對物理磁片的讀寫操作,提高性能 2.
保持資料完整、一至 請看下面的例子 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(); } } } 當刪除A表中一條記錄,同時刪除B,C,D,E,F……等表中的相關資料,當然你可以使用RULE、TRIGGER來完成,我這是只是舉個例子。 由程式完成這樣的刪除作操,如果不使用事務處理,中途中斷運算元據就會不一至。 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; 需求例子 某公司經營虛擬主機,資料庫等業務,需求如下 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" 如果不想使用雙引號,給用戶添麻煩。也可以命名為: 9812net,xusernet,kdeopencom 或不用尾碼直接 9812,xuser,kdeopen 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=# DROP GROUP groupname; postgres=# DROP GROUP vhost; DROP GROUP 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=# DROP USER username; postgres=# DROP USER dbuser1; DROP USER postgres=# 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=> 創建資料庫,並指定所有者: 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=# #
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 [root@linux data]# cat pg_hba.conf host all
all
0.0.0.0
0.0.0.0
md5 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
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'; 過幾天寫 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 字串替換 update crm.customer set details =
replace(details,'客戶','
customer') where id >20; 傳統漢字編碼是由兩個位元組組成(Hz,Hzk
國標GB2312,GBK)的,最新版是GB18030相容(GB2312,GBK
2位元組),其餘的字元是4位元組。其他一些過度標準還有GB 2311、GB 11383、GB 12345、GB 13000.1、GB17000。 採用UTF-8編碼會多佔用一些空間(英文1個位元組,一個漢字等其他字元需3個位元組),但解決了國際化問題,UTF-8相容GB2312、BIG5、EUC_CN、EUC_TW、GB18030等多種國家的語言編碼。 解決了國際化字元問題條件是創建資料庫的編碼必須是UNICODE。UNICODE中英文一個字母=中文一個漢字長度。 控制臺(顯示/輸出)
:UTF-8
參考FAQ
Putty 要解決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。否則你看到的還是亂碼。 我常在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; } } 筆者不贊成使用這種方法,因為無論GBK,還是GB2312只限于英文字母、漢字存儲。我推薦使用Unicode(UTF-8)
編碼,可以存儲任何資料。創建資料庫編碼採用EUC_CN或Unicode編碼都可以(建議使用Unicode)。Jsp頁面中要加入下面幾行代碼。加入代碼之後不需要對字元(包括漢字)做認任轉換處理。全部採用UTF-8編碼存儲資料。 <%@ 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> 上面的方法在跨頁面提交時有問題,漢字還是出亂碼。但提交給自身是沒有問題的。 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> 漢字編碼的解決方案完成。 jdbc:postgresql://localhost:5432/database?charSet=UTF-8 首先下載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 java.sql.DriverManager.getConnection("jdbc:postgresql://db.example.com/testdb?ssl","netkiller","password") http://home.9812.net/linux/article/postgres/python/ 這是我寫的一個小程式。可以將PostgreSQL 資料庫中的表。導出為javabean。 package netkiller.database; /** * Title
PostgreSQL database JDBC interface. * @author: netkiller (陳景峰) * Company: none * Homepage: http://www.xuser.net * Copyright: Copyright (c) 2003 *
@version 1.0 * @since *
@PostgreSQL database JDBC interface. * @see */ 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"); */ } } 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()); } } 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()+"> </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)
+" </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)+" </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)+" </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)+" </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> </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); //排序,DESC,ASC 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>
</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(); } } 關於這個問題網上討論的貼子很多…… 將檔存在資料中優勢: 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> 編譯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]# 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 例表中沒有GB2312,SET 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'尾部的“;”符號加不加都可以。 另一種方法是使用convert()函數: select convert(描述,'UNICODE','GBK')as
desc from 組; select convert(組名 using
utf_8_to_gb18030) from 組; 在資料外部轉碼,使用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; }; 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, OSF 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()函數實現的 新建站點:
1
選擇Manage Sites…
2
單擊New…,然後選擇Site
3
輸入站點名稱:mySite,下一步
4
選擇我想使用伺服器技術,在列表中選擇“JSP”,下一步
5
選擇,編輯、測試一台電腦上。選擇一個站點目錄。下一步 注:我的z:是使用net use z: \\192.168.0.1\web
映射的。\\192.168.0.1\web是linux伺服器,web是Samba
共用/var/www/html/webapps,而/var/www/html/webapps是netkiller.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 按鈕。 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”à彈出下麵對話方塊
關於Eclipse 的配置方法這裏就不談了。網上文檔很多
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.
輸入資料 Name:連接池名 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 directory:d:/bea JDK Installation directory:你的JDK安裝目錄 Domain directory:D:/bea/user_projects/domains/netkiller 輸入密碼:******** 勾去Add an Console item to the Tools menu 單擊OK完成 新建項目
單擊OK 新建
OK
OK
這是一個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上遠端管理,還是比較方便的。 下面你會看到更高級,複雜的管理工具。 下載:http://www.pgadmin.org/pgadmin3/download.php 中文:http://www.pgadmin.org/pgadmin3/download.php?locale=zh_CN
下載:http://www.casestudio.com/enu/download.aspx
CASE Studio 2 - Feature LITE FULL Entity relationship diagrams Clipper (older version) DBISAM 3 IBM DB2 UDB ver. 8.1 IBM DB2 UDB ver. 7.1 Informix (older version) Informix 9 Ingres (older version) InterBase 7 InterBase 6 SQL 3 InterBase 6 SQL 1 InterBase 5 InterBase 4 MS Access 2000 MS Access 97 MS SQL 2000 MS SQL 7 MS SQL 6.5 MySQL 4 (incl. innoDB) MySQL 3.23 Oracle 9 Oracle 8 Oracle 7 Paradox (older version) Pervasive PostgreSQL 7.3 BETA PostgreSQL 7 Sybase 12.5 Data flow diagram Data flows Data stores Processes Terminators Reverse engineering Clipper (older version) DBISAM 3 IBM DB2 UDB ver. 7 IBM DB2 UDB ver. 8 Informix (older version) Informix 9 Ingres (older version) InterBase 7 InterBase 6 SQL 3, InterBase 6
SQL 1 InterBase 5 InterBase 4 MS Access 2000 MS Access 97 MS SQL 2000 MS SQL 7 MS SQL 6.5 MySQL 4 (incl. innoDB) MySQL 3.23 Oracle 9 Oracle 8 Oracle 7 Paradox (older version) Pervasive PostgreSQL 7.3 BETA PostgreSQL 7 Sybase 12.5 Reports & export possibilities RTF reports HTML reports Export into JPG, BMP or PNG Export into XML Features After script items Alternate keys Alter scripts Autolayout Before script items Cardinality Data dictionary (domains) Descriptions Drops generation Foreign keys definition Functions Indexes Informative relationships Internal clipboard M:N relationships Network features New user defined data types Non-identifying relationships Notes Object type bodies* Object types* Package bodies* Packages* Patterns for views, procedures and triggers Primary keys definition Referential integrity Rough uppercase/lowercase selection Self relationships Sequences* SQL script generation Storages Stored procedures Support of compound foreign keys Synonyms* Triggers User permissions (in models) Users (in models) Users group (in models) Views Model maintenance Database/Model conversion** Gallery Model check Submodels To-Do list Version comparsion Version manager Scripting and user defined templates OLE Automation objects Large COM interface MS Scripting Jscript support VB script support Templates editor Templates export Templates import User defined variables editor Displaying Visual creation of DFD Visual creation of ERD Alignment in columns Attributes syntax highlighting Entity background color selection Font selection Logical model Physical model Logical view / physical view Model background color selection Shadows Stamp Straight relationship lines Text descriptions Variable display level Support Free email support Free updates of CASE Studio 2 主頁:http://ems-hitech.com/pgmanager/ 下載:http://ems-hitech.com/pgmanager/download.phtml 圖1 主介面 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! 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; Powerful
tools to work with PostgreSQL server • Database
Explorer featuring Multiple database connections • SQL processing and watching tools, including: Powerful SQL Editor • Powerful data manipulation tools, including: Powerful BLOB Viewer/Editor with several types of viewing BLOB data:
And some
other useful features, including: Customizable program options: windows, fonts, grid colors, etc 下載: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. 資料管理 維護 設計(建模) 逆向工程 最好得分 phpPgAdmin ñ ò ò PgAdmin III ñ ò õ Case Studio 2 ó ô õõ DeZign for Databases ó ô õõõ PostgreSQL Manager ñ ò ó ô õõõõ 我個人對PostgreSQL
Manager的評價是,它完全可以與Oracle DBA Studio,MS SQL
Server 2000的圖形介面管理工具相媲美。 '' = \0 這麼說吧. 一個杯子,杯是空的嗎??? NO,裏面還有空氣呢.這就是"" 讓他中空就是null 關於測試大家去看一下TPC-C,TPC-W,TPC-H,TPC-R 網上有很多文章評論PostgreSQL ,MySQL
,Oracle
, Sybase , MS Sql Server……而且還做了測試。結果當然是MySQL快了。還有一些無聊人醜化PostgreSQL,說它不穩定,愛宕機…… 我要問測試過程得出的結果是否公平? n
做測試的人是做什麼的。是資料方面高手嗎?或DBA嗎? n
他對數據優化了嗎? n
記錄多少? n
存儲大小? n
測試結果是應用於什麼領域? n
使用什麼API(jdbc,odbc,c++
api……) 如果你看過這類文章你會發現他們基本上是如下套路:
1.
創建資料 2.
創建表 3.
取當前時間,開始時間 4.
使用程式迴圈對test表分別插入、刪除、更新資料 5.
取當前時間,結束時間 6.
兩次時間差,得出結果 7.
這樣可以得出三個結果,插入、刪除、更新 這樣的測試結果一點也不公平。 我這裏有幾種測試資料庫性能方法。只供參考,不一定正確、準確。 測試環境和件條: n
相同配置的電腦 n
相同作業系統 n
使用同一種語言和資料庫介面(最公平的是使用C++ API連接資料庫) n
注意索引 n
在win平測試結果不准 測試實例: 1.
首先進行單表的插入、刪除、更新測試。得出結果(流程同上) 2.
進行事務處理單表的插入、刪除、更新測試,每100,1000,5000等為一個組做事務,得出結果
圖
(一) 3.
多表測試 4.
對於大型資料庫是不能光看記錄多少,還要看資料庫容量。從5G起步,10G,50G,100G,200G……
使用上面的多表測試方法將其中某欄位改為大物件。得出結果 5.
子查詢性能測試 6.
壓力測試 要自己寫一個小程式,多線程連接資料。 圖 (一)
圖(二)
主頁:http://www.chiark.greenend.org.uk/~sgtatham/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]$ 可能出現的幾種問題: 1、Server refused our key 公匙和私匙不匹配,或者沒有 authorized_keys 檔 2、Unable to use key file (SSH1 private key) 私匙檔的格式不正確,你可以分別試一下ssh,ssh2 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中輸入中文。任何輸入法都可以。
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- [root@linux zhcon-0.2.3]# make [root@linux zhcon-0.2.3]# make install 運行: [root@linux root]#zhcon 安裝:
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=# [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- postgresql-devel- postgresql- postgresql-docs- postgresql-python- postgresql-contrib- postgresql-jdbc- postgresql-server- postgresql-debuginfo- postgresql-tcl- postgresql-test-7.4.2-1PGDG postgresql-pl-7.4.2-1PGDG [root@linuxas3 postgres]# Pure-FTPd + LDAP + MySQL + PGSQL + Virtual-Users +
Quota How To http://home.9812.net/linux/article/pureftpd/ vsftpd的虛擬用戶配置:PAM + PgSQL + FreeBSD-4 連接:http://www.freebsdchina.org/forum/digest_4589.html http://www.samse.fr/GPL/ldap_pg/HOWTO/ 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: /* ######################################################### 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')); -- 主機: 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','聖文森特和格林納丁斯群島St.Vincent'); 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; #======================================================= # 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_ 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 #======================================================= # 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- 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 --- 文檔中用到的一些相關的檔可以去主頁上下載 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 國產資料庫: latex http://learn.tsinghua.edu.cn/homepage/2001315450/tex_frame.html http://www.pgsqldb.org/pgsqldoc-cvs/index.html http://www.opendocspublishing.com/ http://www.casestudio.com/ 一個資料設計工具 http://www.datanamic.com/
一個資料設計工具 http://www.commandprompt.com/ppbook/ 聲明:您可以隨意轉載,但請保持文檔完整。 轉載請注明作者的主頁位址,因為文檔經常更新,這樣讀者可以看到最新內容。 檔狀態 檔標識 《PostgreSQL 實用實例參考》 o草稿 當前版本 2.0 þ正式發佈 作 者 Netkiller(陳景峰) þ正在修改 開始日期 2003年10月7日星期二 2003-12-5 版本歷史 版本/狀態 作者 參與者 起止日期 備註 1.0.0/草稿 陳景峰 符乃晴 尚麗娜 2003-10-15 校對 1.1.0/修改 2003-10-17 PostgreSQL RPM 包安裝 附件中安裝腳本 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 DW的JSP開發環境 正式/修正2.0.0 2003-12-5 Jbuilder+weblogic+postgresql 2.1.0 2003/12/12 取出字元如果超過20個在後尾加“…” 2.2.1 2003-12-27 資料庫性能測試 2.2.0 2004-2-24 硬碟性能 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 修改漢字編碼 2004-4-13 非常感謝qzhou9887校對文檔 2004-5-20 Tomcat 連接池的配置方法 2004-6-30 修改視圖小節 2004-7-8 APT安裝
2.6
備份計畫
2.6.1
伺服器端計畫
2.6.2
用戶端計畫
2.7 資料恢復
2.8
性能提升
2.8.1
共用記憶體
2.8.2
最大連接
2.8.3
vacuumdb
2.8.4
資料庫操作與性能
vacuumdb
-hlocalhost -p5432 -Upostgres -a -f -z2.8.5
硬體方面
目前PC上ATA只能做RAID0(條帶)和RAID1(鏡像)。SATA可以做RAID0,1,5,10,50。不過我還沒見過STAT 的RAID卡,深圳賽格也沒得賣。
2.8.6
磁片性能
記憶體:512MB
2.9
安全的TCP/IP聯接
2.9.1
使用SSL進行安全的TCP/IP聯接
庰a賞銷葩
J1耤*_D霩h0D?
[1]亐
破
嫅I\拊獨硒椒?槲uY┄啄竄8梕偲 lang=ZH-TW style='font-size:9.0pt;font-family:PMingLiU;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman";mso-fareast-language:
ZH-TW'>奐A禚‑mH璂揙gE驃芵墄墜wN黗丅l??秳船G%|A蒖傗K 斷?毜1]T~tQ紑禜焿鴟殎笀砬?鋂閔溪aq衻?[1]A詊篶:??浢
?匔贍,鄯E??拗 G濜b?虣>x?篙C<洅漢??\?[1]A?B b"璼ijJ筷?Q lang=EN-US style='font-size:9.0pt;mso-fareast-font-family:PMingLiU;
mso-fareast-language:ZH-TW'>?B罌廅榻MVw?遝?頹竡w?鑞堓A@儖玁?[1]@=>葹蟊b?黅.,烕爮?熩([1]灡埍扴?F F懐Ho?嫹t
8卣耟@d??喅?@V6┢ 稷.麳W;踕Pc嬬G? 詔K2wZN$]Bok?
?膠來:矡s浥o愝[1]Q[1]A?瀇Y H翌收,xW?艱 Mn浗?io?o銃W,4甴 eZ諿BDc襪X挐x省圡
2.9.2
使用SSH進行安全TCP/IP聯接
2.10
連接ipv6主機
3
資料定義(DDL)
3.1
日期時間常量
3.1.1
當前日期
3.1.2
當前時間
3.1.3
當前日期時間
3.1.4
除去時區
3.1.5
計算時間差
3.1.6
計算時間和
?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
3.2
漢字做欄位名
3.3
“::”資料轉換
3.3.1
text to varchar
3.4
序列
3.4.1
等差列
3.4.2
“1,2,3,4,5,6,7,8,9…”
3.4.3
“1,3,5,7,9…”
3.4.4
“2,4,6,8,10…”
3.4.5
n1+n2
3.5
約束
3.6
檢查約束
3.7
非空約束
3.8
唯一約束
3.8.1 單字段約束
3.8.2 多個欄位組合約束
3.8.3 唯一約束的注意事項
唯一約束成功。3.9
主鍵/外鍵
3.9.1 主鍵
3.9.2 外鍵約束
3.9.3
PostgreSQL
7.3.x 新增功能
3.9.4 層次遞迴-分類目錄
FOREIGN
KEY (root_id) REFERENCES directory (id) ON DELETE CASCADE
先創建表,不定義FOREIGN
KEY,然後初始化插入第一條資料:
CRT顯示器的id是9
SQL:DELETE FROM directory WHERE id=9;
LG顯示器目錄下的子目錄:液晶顯示器、鑽石隆顯示器也將被刪除
顯示器目錄下的子目錄:
下有目錄LG顯示器/
CRT顯示器、SONY顯示器/……、LG顯示器/……
刪除顯示器目錄後,下的所有子目錄將被刪除。
3.9.5 總結
3.10
模式
3.10.1 創建模式
3.10.2 刪除模式
3.10.3 模式搜索路徑
4 實體關係(Entity-Relation)
4.1
E-R圖(Entity-Relation)
4.2
一對多關係
4.3
多對多關係
4.4
一對一關係
4.5
引用完整性
5 查詢SQL(DML)
5.1
子查詢
5.2
substring()函數截取部分漢字
5.3
sum()使用技巧
5.4
集合查詢 (合併n個表)
UNION ALL
6 視圖
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAA
Select * from table where xxx = xxxx order by xxxx ASC limit x offset x 操作讀出想要的記錄。6.1
VIEW基本使用實例
6.2
使用HTML格式化VIEW的實例
6.3
view中使用漢字做欄位名
6.4
取出字元如果超過20個在後尾加“…”
6.5
視圖中使用子查詢
7 過程與函數
7.1
基本使用實例
7.2
過程中使用Select Into
7.3
返回integer
7.4
返回void
7.5
返回結果集record
7.6
例子
7.7
shell 過程語言
8 規則
8.1
規則實例
9 觸發器
9.1
一般用法
9.2
多個觸發器使用同一個過程
9.3
時間調度觸發器
9.3.1 定時觸發器
9.3.2
週期觸發器
9.4
其他例子
10
游標
10.1
游標結果集
10.2
例子
11
事務處理
11.1
批量插入、更新、刪除
11.1.1 批量插入操作-例1
11.2
保持資料完整-例2
12
用戶許可權
12.1.1 組
12.1.1.1
創建組
12.1.1.2
刪除組
12.1.2 用戶
12.1.2.1
創建用戶
12.1.2.2
刪除用戶
12.1.2.3
修改密碼
12.1.3 創建資料
12.1.4 用戶認證
12.1.4.1
本地連接
12.1.4.2
允許任何IP連接主機
12.1.5 腳本例子
12.1.6 許可權
13
其他技巧例子
第二章 開發篇
13.1
漢字編碼問題
13.2
JDBC
13.2.1 Jsp/Java
13.2.2 toChinese() 方法
13.2.3 Unicode
(UTF-8) 完全解決方案
13.2.3.1
setCharacterEncoding() 方案
13.2.3.2
Web.xml Filter過濾方案:
13.2.3.3
Jdbc
url charSet方案
13.3
Tomcat
JNDI Datasource 配置
13.4
JDBC通過SSL安全連接資料庫
13.5
開發相關
13.5.1 Create
Java Entity Bean (not EJB CMP)
13.5.2 連接資料庫
13.5.3 處理SQL 語句
13.5.4 處理HTML表格
13.5.5 什麼時候應該把檔存在資料庫中
14
PHP
14.1
PHP 連接PostgreSQL
14.2
set CLIENT_ENCODING TO 'GB18030';方案
14.3
convert()方案
14.4
PHP iconv() 函數方案
14.5
在標準I/O上使用
Linux iconv 命令方案
15
開發工具/開發環境
15.1
Macromedia Dreamweaver MX 2004 JSP開發環境的配置
15.2
Jcreator
15.3
Eclipse
15.4
JBuilder + Weblogic + PostgreSQL開發環境
15.5
GUI資料庫管理與設計(建模)工具
15.5.1 phpPgAdmin
15.5.2 PgAdmin III
15.5.3 Case
Studio 2
15.5.4 PostgreSQL
Manager
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...
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
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
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
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
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
15.5.6 GUI工具比較
16
FAQ
16.1
關於“”與null
16.2
Postgresql與其他資料庫
創建一個實表,有11欄位,id欄位為PK主鍵,在表中插入10條記錄
然後創建維表,有11欄位,id欄位為FK外建,參考實表id欄位(一對多),插入10條記錄,
以此類推。見
圖(二)使用join測試分別在不同維度時的結果,更高級測試請參看《資料倉庫》
然後幾台機上運行這個程式5幾進程,每個進程中有10個線程16.3
Putty
16.3.1 Putty密鑰認證
16.3.2 中輸入漢字的問題
16.4
控制臺下輸入漢字
16.5
PostgreSQL RPM 包安裝後,為何沒有5432埠
16.6
PostgreSQL 7.4.2 rhel3(高級伺服器版,俗稱AS3)
16.7
Pureftpd pgsql認證模組
16.8
Vsftpd pgsql認證
16.9
OpenLDAP-PostgreSQL HOWTO
16.10
PostgreSQL
成功案例與解決方案
17
附錄
17.1
實例
17.2
實例
17.3
安裝腳本
17.3.1 setenv.sh
17.3.2 install.sh
17.4
附件
17.5
其他
18
參考資料
19
版本、聲明
Jsp/Java 漢字編碼問題
“::”轉換資料
性能提升-硬體
Java 漢字編碼問題web.xml方案
保證備份資料的安全-PGP/GPG加密
過程例子
游標例子
解發器例子
檢查check例子
替換字串例子