You are on page 1of 37

Copyright © 2009 by Peekanung                                                                                                     1

PostgreSQL 8.3
Manual
Copyright © 2009 by Peekanung                                                                                                     2

Page
1. เก่ียวกับ PostgreSQL 3
2. Installation PostgreSQL บน Ubuntu 4
2.1 เก่ียวกับ pg_hba.conf 6
2.2 เก่ียวกับ postgresql.conf 7
2.3 Install pgAdmin GUI Application 8
3. การใช้งาน PostgreSQL 10
3.1 postgreSQL-Client Application (psql) 10
3.2 การจัดการ Database 10
3.3 การจัดการ Table และ View 12
3.3.1 Table 12
3.3.2 View 14
3.4 การจัดการ Roles 15
3.5 Data type 19
3.6 การ Import/Export data 20
3.7 postgreSQL Functions 21
3.8 Partitioning Table 22
3.9 Materialized View 24
3.9.1 Snapshot 24
3.9.2 Eager 27
3.9.3 Lazy 32
3.9.4 Very Lazy 32
3.10 การสำารองข้อมูล 35
3.10.1 Backup 35
3.10.2 Restore 36
3.11 Database Maintenance 37
Copyright © 2009 by Peekanung                                                                                                     3

1. เก่ย
ี วกับ PostgreSQL
PostgreSQL เปน object-relational database management system (ORDBMS) พัฒนามาจาก POSTGRES
Version 4.2 โดย University of California at Berkeley ภาควิชา Computer Science
PostgreSQL เปนโปรแกรม Open source สามารถนำ าไปใช้งานได้โดยไมมีคาใช้จาย และสนั บสนุนมาตรฐาน SQL:2003
ซ่ึงมีความสามารถตางๆ เชน
 complex query
 foreign keys
 triggers
 views
 transactional integrity
 multiversion concurrency control

นอกจากนี้ PostgreSQL ยังให้ผู้ใช้งาน(User)กำาหนดการใช้งานเองได้ เชน


 Data types
 Functions
 Operators
 Aggregate functions
 Index methods
 Procedural languages

รายละเอียดทั่วไปเกี่ยวกับ PostgreSQL
 ขนาดฐานข้อมูล : ไมจำากัด
 ขนาดตารางข้อมูล(table) : ไมเกิน 32 TB
 ขนาดของข้อมูลแตละรายการ(row) : ไมเกิน 400 GB
 ขนาดของข้อมูลแตละ field : 1GB
 จำานวนรายการ(rows) ในตารางข้อมูล(table) : ไมจำากัด
 จำานวน columns ในตารางข้อมูล(table): 250-1600 columns ขึ้นอยูกับชนิ ด column
 จำานวน indexes ในตารางข้อมูล(table) : ไมจำากัด
 การตัง้ช่ ือ
 ขึ้นต้นด้วยตัวอักษรหรือ underscore(_)
 ความยาวไมเกิน 31 ตัวอักษร
 ไมซ้ำากับ reserve word หรือถ้าต้องการให้ใช้ Quote(“”)
 การใช้ Quote(“”) จะทำาให้ช่ือท่ีอยูใน Quote(“”)เปนแบบ Case Sensitive
 ช่ ือท่ีอยูในประเภทเดียวกันต้องไมซ้ำากัน เชน
■ ช่ ือ Database ท่ีอยูใน Cluster เดียวกันต้องไมซ้ำากัน
■ ช่ ือ Table ท่ีอยูใน Database เดียวกันต้องไมซ้ำากัน
■ ช่ ือ Column ท่ีอยูใน Table เดียวกันต้องไมซ้ำากัน
■ ช่ ือ Index ท่ีอยูใน Database เดียวกันต้องไมซ้ำากัน

รูปด้านลาง เป็ นโครงสร้างอยางงายของ PostgreSQL


Copyright © 2009 by Peekanung                                                                                                     4

2. Install PostgreSQL 8.3 บน Ubuntu


ในการติดตัง้ระบบฐานข้อมูล PostgreSQL นั ้นผู้ใช้งานทำาได้โดย Install Package Postgresql ด้วยคำาสัง่ตอไปนี้
$ sudo apt-get install postgresql

หลังจากท่ี Os ทำาการ install Package เสร็จเรียบร้อยแล้ว Home ของ PostgreSQL จะถูกติดตัง้อยูท่ี


/var/lib/postgres/ และจะมีกลุมของผู้ใช้งาน และ user ท่ีช่ือวา postgres ซ่ ึงใช้ในการเรียกใช้งานระบบฐานข้อมูล
PostgreSQL แตเพ่ ือความปลอดภัยในการใช้งานระบบฐานข้อมูล เราไมควรจะอนุญาติให้ใช้ username : postgres เข้าใช้งาน
ระบบจึงควรสร้าง user ใหมด้วยคำสัง่ (ตัวอยาง : user01)
$ createuser -P user01 //ใช้ -P เพ่ ือ assign password ให้ user
Enter password for new role:
Enter it again:
Shall the new role be a superuser? (y/n)
Shall the new role be allowed to create databases? (y/n)
Shall the new role be allowed to create more new roles? (y/n)

หลังจากท่ีผู้ใช้งานสร้าง user ได้แล้ว ผู้ใช้งานยังสามารถสร้าง database ด้วยคำาสัง่ (ตัวอยาง : mydb)


$ createdb mydb

สามารถเข้าใช้งาน Database ท่ีถูกสร้างไว้ด้วยคำาสัง่ตอไปนี้


$ psql -d mydb //ใช้ -d เพ่ ือระบุ ช่ ือ database
หรือ
$ psql -d mydb -U user01 //ใช้ -U เพ่ ือระบุ user ท่ีใช้ในการ connect (ถ้าไม่ระบุจะหมายถึง user :
postgres เสมอ )

   

หมายเหตุ
1. สามารถเข้าใช้งาน database โดยใช้คำาสัง่ psql ตามด้วยช่ ือ Database และช่ ือ User ตามลำาดับ โดยไมต้องระบุ option
เน่ ืองจาก default format เป็ น psql <database name> <user name>
เชน $ psql mydb user01
Copyright © 2009 by Peekanung                                                                                                     5

2. การเข้าใช้งานทุกครัง้ ต้องระบุข่ือ Database เสมอ ( ช่ ือ User จะกำาหนดหรือไมก็ได้)


เชน $ psql mydb // สามารถ connect ได้ โดย Database = mydb , User = postgres (default user)
$ psql -d mydb // สามารถ connect ได้ โดย Database = mydb , User = postgres (default user)
$ psql user01 // ไม่สามารถ connect ได้ เน่ อ ื งจากไม่มี database ช่ ือ user01
3. สามารถเข้าใช้งานโดยการระบุเฉพาะช่ ือ User โดยใช้ option -U ได้กรณี เดียวคือ ช่ ือ Database และช่ ือ ๊User เป็ นช่ ือ
เดียวกัน เชน
3.1 ช่ ือ Database และช่ ือ ๊User เป็ นช่ ือเดียวกัน คือ xyz
$ createuser -P xyz // สร้าง user ช่ ือ xyz โดยกำาหนดให้มี password
$ createdb xyz // สร้าง database ช่ ือ xyz
$ psql xyz xyz // สามารถ connect ได้ โดย Database = xyz , User = xyz
$ psql xyz // สามารถ connect ได้ โดย Database = xyz , User = postgres (default user)
$ psql -d xyz // สามารถ connect ได้ โดย Database = xyz , User = postgres (default user)
$ psql -U xyz // สามารถ connect ได้ โดย Database = xyz , User = xyz
3.2 ช่ ือ User ไมตรงกับช่ ือ Database
$ createuser -P abc // สร้าง user ช่ ือ abc โดยกำาหนดให้มี password
$ psql abc
error “psql: FATAL: database "abc" does not exist” เน่ ืองจากไม่มี Database ช่ ือ abc
$ psql -d abc
error “psql: FATAL: database "abc" does not exist” เน่ ืองจากไม่มี Database ช่ ือ abc
$ psql -U abc
Password for user abc: // ใส่ password ของ user abc
error “psql: FATAL: database "abc" does not exist” เน่ อ ื งจากไม่มี Database ช่ ือ abc

สามารถ connect โดยไมระบุ option ได้ แตต้องเรียงตามลำาดับดังนี้ : host (ถ้ามี), ช่ ือ database, ช่ ือ user เชน
$ psql mydb abc // สามารถ connect ได้ โดย Database = mydb , User = abc

โดยเราสามารถตรวจสอบรายช่ ือ Database ตางๆ ได้โดยใช้คำาสัง่


$ psql -l

แก้ไข Configuration file


1. แก้ไขไฟล์ postgresql.conf เพ่ ือให้สามารถ remote เข้ามาใช้งาน database ได้
$ sudo vi /etc/postgresql/8.3/main/postgresql.conf
แก้ไขในสวนของ ‘Connections and Authentication’ section… ดังนี
listen_addresses = '*' // อนุญาตให้เคร่ ือง Client ท่ีใช้ IP อ่ ืน นอกจาก localhost สามารถเช่ ือมต่อกับ database ได้
และ
password_encryption = on // กำาหนดให้มีการเข้ารหัส password ของทุก User ใน Database
Copyright © 2009 by Peekanung                                                                                                     6

Note: ไฟล์ postgresql.conf เป็ นไฟล์ท่ีใช้เก็บ Configuation ตางๆ ของ PostgreSQL ดังนี้ (เฉพาะ parameter ท่ีเปิ ดใช้อยูเทานั ้น)

# FILE LOCATIONS
data_directory = '/var/lib/postgresql/8.3/main' // Directory ท่ใี ช้เก็บ data และ configuration file ของ database
hba_file = '/etc/postgresql/8.3/main/pg_hba.conf' // Configuration file เก่ียวกับสิทธิก
์ ารเข้าถึง database
ident_file = '/etc/postgresql/8.3/main/pg_ident.conf' // Configuration file ท่ีใช้ map user กับ identifier user เพือใช้งานระบบ
external_pid_file = '/var/run/postgresql/8.3-main.pid' // path file ท่ีใช้บันทึก process id

# CONNECTIONS AND AUTHENTICATION


listen_addresses = '*' // อนุญาตให้เคร่ ือง Client ท่ีใช้ IP อ่ ืน นอกจาก localhost สามารถเช่ ือมตอกับ database ได้
port = 5432 // หมายเลข port ของ database server
max_connections = 100 // กำาหนดจำานวนสูงสุดของการเช่ ือมตอกับ database ในเวลาเดียวกัน (default = 32)
unix_socket_directory = '/var/run/postgresql' // Directory สำาหรับการเช่ ือมตอจาก Client Application
ssl = true // เปิ ดการใช้งาน SSL (Secure Sockets Layer)
password_encryption = on // กำาหนดให้มีการเข้ารหัส password ของทุก User ใน Database

# RESOURCE USAGE (except WAL)


shared_buffers = 24MB // กำาหนดขนาดของ share buffer สำาหรับการทำางานของ database (คาน้ อยสุดคือ 128 kB หรือ
max_connection*16 kB)
max_fsm_pages = 153600 // กำาหนดขนาดท่ีใช้เก็บ free space เพ่ ือนำ ากลับมาใช้ใหม (default = 10000 , คาน้ อยสุด คือ จำานวนrealtion*16)

# ERROR REPORTING AND LOGGING


log_line_prefix = '%t ' // รูปแบบของช่ ือ log file ท่ข
ี ึ้นต้นด้วยเวลาท่ไี มรวม millisecond

# CLIENT CONNECTION DEFAULTS


datestyle = 'iso, mdy' //รูปแบบของวันเวลาท่ีใช้ในระบบ
lc_messages = 'en_US.UTF-8' // รูปแบบของตัวอักษรบน error message
lc_monetary = 'en_US.UTF-8' // รูปแบบของตัวอักษรท่ีใช้กับข้อมูลจำานวนเงิน
lc_numeric = 'en_US.UTF-8' // รูปแบบของตัวอักษรท่ใี ช้กับข้อมูลประเภทตัวเลข
lc_time = 'en_US.UTF-8' //รูปแบบของตัวอักษรของเวลา
default_text_search_config = 'pg_catalog.english' //มาตราฐานรูปแบบของการเรียงข้อมูลตามตัวอักษร

2. แก้ไขไฟล์ /etc/postgresql/8.3/main/pg_hba.conf เป็ นการกำาหนดผ้้ที่มีสิทธิเ์ข้าถึง database โดยแก้ไขให้มีคาดังนี้

# Database administrative login by UNIX sockets


# local database user auth-method
local all postgres ident sameuser
local all all md5
# IPv4 local connections:
# host database user CIDR-address auth-method
host all all 127.0.0.1/32 md5
# IPv6 local connections:
host all all ::1/128 md5
อธิบาย
local all postgres ident sameuser
// กำานดให้ user : postgress บนเคร่ ือง local เข้าใช้งานได้ทุก database (ไม่ต้องใส่ password ของ database)
local all all md5
// กำาหนดให้ทุก user บนเคร่ ือง local เข้าใช้งานได้ทุก database โดยต้องใส่ password ของ database
host all all 127.0.0.1/32 md5
host all all ::1/128 md5
// กำาหนดให้ทุก user ในกลุ่ม IP ท่ีกำาหนด สามารถconnect ผ่าน TCP/IP โดยต้องใส่ password ของ database
หลังจากนั ้นให้ restart services ใหม $ service postgresql-8.3 restart [ start | stop | restart ]

2.1 เก่ียวกับ pg_hba.conf


การตรวจสอบสิทธิของเคร่ ืองลูกขายในการเข้าใช้งาน postgreSQL server จะถูกควบคุมโดยข้อความท่ีระบุในไฟล์
pg_hba.conf ท่ีอยูใน /etc/postgresql/8.3/main/pg_hba.conf. (HBA ยอมาจาก host-based authentication) ซ่ึงไฟล์
pg_hba.conf นี้จะถูกติดตัง้เม่ ือทำาการสร้าง database
รูปแบบทัว่ไปของไฟล์ pg_hba.conf คือกลุมของข้อความแยกตามบรรทัด หน่ ึงชุดของข้อความจะต้องจบลงในหน่งึ
บรรทัด บรรทัดวางจะถูกข้ามไปโดยไมมีการประมวลผล และข้อความท่ีอยูหลังเคร่ ืองหมาย # จะเปนคำาอธิบายและไมถูกประมวล
ผล เชนกัน แตละบรรทัดประกอบหลายข้อความท่ีถูกแยกจากกันด้วยชองวาง ในแตละข้อความสามารถมีชองวางได้ แตจะต้องค
รอม ด้วยเคร่ ืองหมาย " "
แตละบรรทัดจะระบุ ชนิ ดของการเช่ ือมตอชวงหมายเลข ip ของเคร่ ืองลูกขาย ช่ ือของฐานข้อมูลท่ีจะเข้าใช้งาน ช่ ือ user
และวิธีการตรวจสอบสิทธิ กรณี มีหลายบรรทัดท่ีเข้าเง่ ือนไข บรรทัดแรกท่ีสอดคล้องตามเง่ ือนไขท่ีเช่ ือมตอเข้ามาจะถูกเลือกมาใช้
เพ่ ือการตรวจสอบสิทธิ ถ้าสิทธิไมถูกต้องการเช่ ือมตอนั ้นจะถูกยกเลิก โดยไมสนใจบรรทัดอ่ ืนท่ีกำาหนดสิทธิแตกตางกัน
รูปแบบของแตละบรรทัดสามารเขียนได้หลายรูปแบบตามตัวอยาง
Copyright © 2009 by Peekanung                                                                                                     7

local DATABASE USER METHOD [OPTION]


host DATABASE USER CIDR-ADDRESS METHOD [OPTION]
hostssl DATABASE USER CIDR-ADDRESS METHOD [OPTION]
hostnossl DATABASE USER CIDR-ADDRESS METHOD [OPTION]

แตละข้อความ สามารถอธิบายได้ดังนี้
local เปนการเช่ ือมตอในรูปแบบท่ีเคร่ ืองลูกขาย (client) และฐานข้อมูลอยูในเคร่ ืองเดียวกัน
host เปนเช่ ือมตอของเคร่ ืองลูกขายโดยใช้ TCP/IP ซ่ึงข้อมูลเปนแบบเข้ารหัสหรือไมก็ได้
hostssl เปนเช่ ือมตอของเคร่ ืองลูกขายโดยใช้ TCP/IP ซ่ ึงข้อมูลเปนแบบเข้ารหัสเทานั ้น
hostnossl เปนเช่ ือมตอของเคร่ ืองลูกขายโดยใช้ TCP/IP ซ่ ึงข้อมูลเปนแบบไมเข้ารหัส

DATABASE กำาหนดวาจะอนุญาตให้เข้าใช้งานฐานข้อมูลไหนโดยระบุช่ือฐานข้อมูล หรือสามารถใช้คาตางๆเหลานี้


• all เพ่ ือระบุทุกฐานข้อมูล
• sameuser เพ่ ือกำาหนดวาฐานข้อมูลท่ีเข้าใช้งานมีช่ือตรงกับ user ท่ีเรียกเข้าใช้งาน
• samegroup กำาหนดวา user ท่ีขอเข้าใช้งานต้องเปนสมาชิกของกลุมท่ีมช ี ่ ือตรงกับฐานข้อมูลท่ีขอเข้าใช้งาน
• ถ้ากำาหนดหลายฐานข้อมูลให้คัน ่ ด้วยเคร่ ืองหมาย , (comma)
• ในกรณี ระบุเปนช่ ือไฟล์ให้นำาหน้ าช่ ือไฟล์ด้วยเคร่ ืองหมาย @ และไฟล์นี้จะต้องอยูไดเรคทอรีเดียวกับไฟล์ pg_hba.conf

USER ระบุช่ือของ user ท่ีจะอนุญาตให้เเข้าใช้งาน database สามารถใช้คาเหลานี้ แทนได้


• all เพ่ ือระบุทุก user สามารถเข้าใช้งาน database ได้
• ถ้ากำาหนดหลาย user ให้คัน ่ แตละ user ด้วยเคร่ ืองหมาย comma ( , )
• ถ้าระบุเปนช่ ือของกลุม user ให้นำาหน้ าช่ ือกลุมด้วยเครืองหมาย +

CIDR-ADDRESS (Classless Inter-Domain Routing ) ระบุหมายเลข ip ของเคร่ ือง client ท่ีจะอนุญาตให้เข้าใช้งาน (ไม
สามารถระบุเปน domain หรือ ช่ ือเคร่ ือง)

METHOD ระบุวิธีการตรวจสอบตัวตน ของ user ท่ีเช่ ือมตอเข้ามา สามารถใช้ตัวเลือกเหลานี้

 Trust ไมมีเง่ ือนไขในการในการตรวจสอบ ไมต้องใส password


 Reject ปฏิเสธทุกการเช่ ือมตอโดยไมมีเง่ ือนไข
 md5 เคร่ ือง client ท่ีเข้าขอเข้าใช้งานต้องใส password ของ database ในรูปแบบท่ีเข้ารหัสแบบ MD5
 crypt คล้ายๆแบบ MD5 ( สำาหรับ version 7.2 หรือ ตำ่ากวา )
 password คล้าย MD5 แต password จะถูกสงในรูปแบบท่ีไมมีการเข้ารหัส
 krb5 (Kerberos V5) เป็ นการตรวจสอบตัวตนของ user สำาหรับการเช่ ือมตอแบบ TCP/IP เทานั ้น
 ident รับคา user name ของเคร่ ือง client จากระบบปฏิบัติการ โดยเคร่ ือง client จะต้องมี ident server ทำางานอยู
กรณี Client อยูในเคร่ ืองเดียวกับ server ระบบปฏิบัติการจะต้อง Unix-domain socket credentials
 pam ตรวจสอบตัวตนของ user โดยใช้บริการ Pluggable Authentication Modules (PAM) ของบางระบบปฏิบัติ
การ เชน Unix

OPTION ใส option ขึ้นกับวาเลือกการพิสูจน์ตัวตน (authentication) แบบไหน เชนถ้าใช้ method แบบ ident หรือ pam ท่ี
option นี้จะต้องระบุช่ือผู้ให้บริการ

2.2 เก่ียวกับ postgresql.conf


ไฟล์ postgresq.conf เป็ นไฟล์ท่ีใช้เก็บ configuration ทัง้หมดของ postgreSQL ซ่ึีง parameter และคาตางๆ ท่ต
ี ้อง
เปิ ดใช้งาน มีดังนี้

 listen_addresses = ‘*’ : เพ่ ืออนุญาตให้เคร่ ือง Client ท่ีใช้หมายเลข IP (IP address) อ่ ืนๆ ท่ีไมใช localhost
สามารถติดตอเข้าใช้งานฐานข้อมูล
 data_directory : path directory ท่ีใช้เก็บโปรเเกรมระบบฐานข้อมูลและ configure file ของระบบ
 hba_file : path file ท่ีใช้ในการควบคุมการเข้าใช้งานระบบฐานข้อมูลของ host
 ident_file : path file ท่ีใช้ในการ map user กับ identifier user เพือใช้งานระบบ
 external_pid_file : '/var/run/postgresql/8.3-main.pid' > path file ท่ีใช้บันทึก process id
 port = 5432 : port ท่ีถูกเปิ ดใช้งานระบบฐานข้อมูล
 max_connections = 100 : requires สูงสุดท่ีสามารถให้บริการ
 unix_socket_directory = '/var/run/postgresql' : set path ในการเรียกใช้งานระบบ
 ssl = true : ระบุการสงข้อมูลในรูปแบบของการเข้ารหัส
 password_encryption = on : ระบุรูปแบบการสงข้อมูลวาจะมีการเข้ารหัสตัวข้อมูลด้วยหรือไม
 shared_buffers = 24MB : shared buffers มีขนาดให้ใช้งานเทากับ 24MB
Copyright © 2009 by Peekanung                                                                                                     8

 max_fsm_pages = 153600 : พ้ืนท่ีวางสูงสุดของ disk ใน shared free-space map


 log_line_prefix = '%t ' : รูปแบบของช่ ือ log file ท่ีขึ้นต้นด้วยเวลาท่ีไมรวม millisecond
 datestyle = 'iso, mdy' : รูปแบบของวันเวลาท่ีใช้ในระบบ
 lc_messages = 'en_US.UTF-8' : รูปแบบของตัวอักษรบน error message
 lc_monetary = 'en_US.UTF-8' : รูปแบบของตัวอักษรท่ีใช้กับข้อมูลจำานวนเงิน
 lc_numeric = 'en_US.UTF-8' : รูปแบบของตัวอักษรท่ีใช้กับข้อมูลประเภทตัวเลข
 lc_time = 'en_US.UTF-8' : รูปแบบของตัวอักษรของเวลา
 default_text_search_config = 'pg_catalog.english' : มาตราฐานรูปแบบของการเรียงข้อมูลตามตัวอักษร

2.3 Install pgAdmin GUI Application


ในการ Install pgAdmin ทำาได้โดยใช้คำาสัง่ตอไปนี้
$ sudo apt-get install pgadmin3

แล้ว Run scripts ตอไปนี้ เพ่ ือให้สามารถใช้งาน pgAdmin ได้


$ sudo su postgres -c psql < /usr/share/postgresql/8.3/contrib/adminpack.sql หรือ
$ cd /usr/share/postgresql/8.3/contrib
$ su postgres -c psql
postgres=# adminpack.sql

การเข้าใช้งาน
ไปท่ี Applications > Programming > pgAdmin III

คลิกป ุม 'Add a connection to a server' เพ่ ือสร้างการเช่ ือมตอ


Copyright © 2009 by Peekanung                                                                                                     9

ระบุคาตาง ๆ ของ Database เพ่ ือใช้ในการเช่ ือมตอ แล้วกด OK

จะปรากฎหน้ าตาของ pgAdmin ซ่ ึงแบงหน้ าตางออกเป็ น 2 สวน ดังนี้


1. Object browser ของแตละ Connection ( ด้านซ้าย )
2. Properties, Statistics, Dependencies และ Dependcents ของ Object ( ด้านขวา ) 
Copyright © 2009 by Peekanung                                                                                                     10

3. การใช้งาน PostgreSQL

3.1 PostgreSQL-Client Application (psql)


โปรแกรม PostgreSQL-Client คือ psql จะใช้โปรแกรมนี้ ได้ อยูใน Text Mode หรือ Command line
psql เปนโปรแกรมท่ีใช้ติดตอกับ Database Server แบบ command line โดยสามารถเรียกดู option ตางๆของ psql
ได้จาก

$ psql --help

Syntax : psql [options] [dbname [username]]

Options:
-d <ช่ ือฐานข้อมูล> กำาหนด database name ท่ีต้องการติดตอ (default: postgres)
-f <ช่ ือไฟล์> Execute queries จากไฟล์
-h <host> กำาหนด database server host (default: localhost)
-l แสดงรายการฐานข้อมูลท่ีมีอยูทัง้หมด
-p <port> กำาหนด database server port (default: 5432)
-q ทำางานโดยไมแสดงข้อความจากระบบ แสดงเฉพาะผลลัพธ์ท่ีได้จาก query
-U <username> กำาหนด database username (default: postgres)
-V แสดง version information
-W Prompt เพ่ ือใส password (ปกติจะต้อง ใส password อยูแล้ว)

การจัดการเกี่ยวกับ Service ของ PostgreSQL (ต้อง Login ด้วย root)


ตรวจสอบสถานะของ service $ service postgresql-8.3 status หรือ /etc/init.d/ postgresql-8.3 status
Start service $ service postgresql-8.3 start หรือ /etc/init.d/ postgresql-8.3 start
Stop service $ service postgresql-8.3 stop หรือ /etc/init.d/ postgresql-8.3 stop

3.2 การจัดการ Database


• เม่ ือใช้โปรแกรม psql คำาสัง่ท่ใี ช้คือภาษา SQL ตามมาตรฐาน SQL92/SQL99
• คำาสัง่ท่ีเปนภาษา SQL ให้ปดคำาสัง่ด้วย ; สัง่ทำางานด้วย <Enter>
• คำาสัง่ของ psql ท่ีขึ้นต้นด้วย \ ไมต้องปดคำาสัง่ด้วย ; สัง่ทำางานด้วย <Enter>

(1) สร้าง database ใหม

$ createdb [OPTION]... [DBNAME] [DESCRIPTION]

Options:
-D, --tablespace=TABLESPACE กำาหนด tablespace ให้กับ database
-E, --encoding=ENCODING กำาหนด encoding ให้กับ database
-O, --owner=OWNER กำาหนด user ท่ีจะเป็ นเจ้าของ database
-T, --template=TEMPLATE สร้าง database ตาม template ท่ีกำาหนด
-e, --echo กำาหนดให้แสดงคำาสัง่ท่จี ะถูกสงไป server
-q, --quiet กำาหนดให้ไมต้องแสดงผลจากการสัง่ create
--help แสดงตัวชวยเหลือเก่ียวกับการสร้าง database
--version แสดงเวอร์ชัน

Connection options:
-h, --host=HOSTNAME database server host หรือ socket directory
-p, --port=PORT database server port
-U, --username=USERNAME กำาหนด user name ท่ีใช้ connect
-W, --password กำาหนดให้ระบุ password ทันที
Copyright © 2009 by Peekanung                                                                                                     11

ตัวอยาง
$ createdb test with encoding='win874'
// สร้าง database ช่ ือ 'test' โดยกำาหนด encoding เป็ น 'win874'
$ createdb test –U postgres –E win874 –O user1
// สร้าง database ช่ ือ 'test' โดยกำาหนด username ท่ีใช้ connect เป็ น 'postgres' กำาหนด encoding
เป็ น 'win874' และให้ user1 เป็ นเจ้าของ database

หรือใช้ SQL Command


SQL > CREATE DATABASE database-name
[ WITH [ OWNER [=] {username|DEFAULT}]
[ TEMPLATE [=] {template-name|DEFAULT}]
[ ENCODING [=] {encoding|DEFAULT}]
[ TABLESPACE [=] tablespace ]]
ตัวอยาง
SQL > CREATE DATABASE test ENCODING 'win874';
// สร้าง database ช่ ือ 'test' โดยกำาหนด encoding เป็ น 'win874'
SQL > CREATE DATABASE test ENCODING 'win874' OWNER user1;
// สร้าง database ช่ ือ 'test' โกำาหนด encoding เป็ น 'win874' และให้ user1 เป็ นเจ้าของ database

หมายเหตุ ในการกำาหนด OWNER โดยปกติ(default) จะกำาหนดให้ผู้ท่ีสร้างเปน OWNER แตถ้าเปน superuser


เชน postgres จะสามารถกำาหนด OWNER ให้ user อ่ ืนได้

(2) ลบ database
$ dropdb [OPTION]... [DBNAME] [DESCRIPTION]

Options:
-e, --echo กำาหนดให้แสดงคำาสัง่ท่จี ะถูกสงไป server
-i ,--interactive กำาหนดให้ตรวจสอบความถูกต้องของคำาสัง่กอนทำางาน
-h, --host=HOSTNAME database server host หรือ socket directory
-p, --port=PORT database server port
-U, --username=USERNAME กำาหนด user name ท่ีใช้ drop database
-W, --password กำาหนดให้ระบุ password ทันที
ตัวอยาง
$ dropdb demo // ลบ database ช่ ือ 'demo'
$ dropdb -i demo –U postgres // ลบ database ข่ ือ 'domo' ด้วย user 'postgres'

หรือใช้ SQL Command


SQL > DROP DATABASE

ตัวอยาง
SQL > DROP DATABASE test; / ลบ database ช่ ือ 'test'
*หมายเหตุ ฐานข้อมูลท่ีเปดใช้อยู ไมสามารถลบได้ ต้องปดกอน โดยใช้คำาสัง่ \q หรือ เปิ ดฐานข้อมูลอ่ ืน เชน \c test

(3) ด้ database
$ psql -l

ตัวอยาง $ psql -l // คำาสัง่ psql -l จะแสดง Name,Owner,Encoding ของ database


List of databases
Name | Owner | Encoding
---------------+------------+----------
db01 | user01 | UTF8
mydb | postgres | UTF8
postgres | postgres | UTF8
Copyright © 2009 by Peekanung                                                                                                     12

template0 | postgres | UTF8


template1 | postgres | UTF8

หรือใช้ SQL Command


SQL > select * from pg_database; หรือ
SQL > \l

ตัวอยาง
SQL > SELECT * FROM pg_database ; // pg_database จะแสดงรายละเอียดทัง้หมดของ database
datname|datdba|encoding|datistemplate|datallowconn|datconnlimit|datlastsysoid|datfrozenxid| dattablespace | datconfig | datacl
----------+---------+-----------+-----------------+-----------------+---------------+-----------------+---------------+-------------------+-------------+------------
db01 |16535 | 6 |f |t | -1 | 11510 | 379 | 16538| |

SQL > \l // คำาสัง่ \l จะแสดงผลเหมือนคำาสัง่ psql -l

(4) แก้ไข database

SQL Command
SQL > ALTER DATABASE name [ [ WITH ] option [ ... ] ]
Options:
CONNECTION LIMIT connlimit จำากัดการเข้าถึง database โดยถ้ากำาหนดเป็ น -1 จะหมายถึง unlimit
RENAME TO newname เปล่ียนช่ ือ database
OWNER TO new_owner เปล่ียนเจ้าของ database
SET configuration_parameter {TO|=}{value|DEFAULT} แก้ไข parameter ของ database (กำาหนดเอง)
SET configuration_parameter FROM CURRENT แก้ไข paramter ให้เป็ นไปตาม session นี้
RESET configuration_parameter reset configuration ของ database
RESET ALL reset ทุก configuration ของ database

ตัวอยาง
SQL > ALTER DATABASE test RENAME TO test_01;
// แก้ไข database โดยเปล่ียนช่ ือจาก 'test' เป็ นช่ ือ 'test_01'
SQL > ALTER DATABASE test OWNER TO user01;
// แก้ไข database โดยเปล่ียนเจ้าของเป็ น 'user01'
SQL > ALTER DATABASE test SET enable_indexscan TO off;
// แก้ไข database 'test' โดยกำาหนดเป็ นแบบไม่ใช้ index scaning

(5) การ connect เข้าใช้งาน database


ใช้ SQL Command
SQL > \c <dabatase name> <user name>

เชน SQL > \c mydb user01


// connect เข้า database 'mydb' ด้วย user 'user01'
ถ้าไม่ระบุ user จะเป็ นการ connect ด้วย user ปั จจุบันท่ใี ข้อย่่

3.3 การจัดการ Table และ View


3.3.1 Table
(1) การสร้าง Table
SQL > CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE table_name ( [
{ column_name data_type [ DEFAULT default_expr ] [ column_constraint [ ... ] ]
| table_constraint
| LIKE parent_table [ { INCLUDING | EXCLUDING } { DEFAULTS | CONSTRAINTS |
INDEXES } ] ... }
[, ... ]
])
[ INHERITS ( parent_table [, ... ] ) ]
WITH ( storage_parameter [= value] [, ... ] ) | WITH OIDS | WITHOUT OIDS ]
[ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
[ TABLESPACE tablespace ]
Copyright © 2009 by Peekanung                                                                                                     13

หมายเหตุ
OIDs คือ Object Identifier เป็ น Internal ID ของ postgreSQL ถ้าระบุเป็ น WITH OIDS จะสามารถใช้คำาสัง่
SELECT เพ่ ือดู OIDs ได้ โดย
SQL > SELECT oid, * FROM a;
oid | a_id | v
----------+------+----
16880 | 1 | 11
16881 | 2 | 22
(2 rows)
ตัวอยาง
SQL > CREATE TABLE testtable (id int, name varchar(30));
SQL > CREATE TABLE person (
did integer,
name varchar(40),
PRIMARY KEY(did) );
SQL > CREATE TABLE distributors (
did integer PRIMARY KEY DEFAULT nextval(’serial’),
name varchar(40) NOT NULL CHECK (name <> ”) );

(2) การด้ Table


ด้ รายละเอียด Table ทัง้หมด
SQL > \d ; // คำาสัง่ \d จะแสดงผลทัง้ Table , View และ sequence
List of relations
Schema | Name | Type | Owner
------------+--------------------------+----------+----------
public |a | table | user01
public | arr | table | postgres
public | b_v | view | user01

หรือ
SQL > SELECT * FROM pg_tables ; // pg_tables จะแสดงผลเฉพาะ Table
หรือระบุช่ือ table
SQL > SELECT * FROM pg_tables where tablename = 'shipment';
schemaname | tablename | tableowner | tablespace | hasindexes | hasrules | hastriggers
-------------------+--------------+----------------+---------------+----------------+------------+-------------
public | shipment | user01 | |t |f |t
(1 row)

ด้โครงสร้างของ Table
SQL > \d table_name;
เชน SQL > \d shipment;
Table "public.shipment"
Column | Type | Modifiers
-------------------+-----------------------------+-------------------------------------------------------
id | integer | not null default nextval('shipment_id_seq'::regclass)
address | text | not null
shipping_date | timestamp without time zone | not null
Indexes:
"shipment_pkey" PRIMARY KEY, btree (id)
Triggers:
shipment_insert_trigger BEFORE INSERT ON shipment FOR EACH ROW EXECUTE PROCEDURE shipment_insert()

ด้ข้อม้ลใน Table SQL > SELECT * FROM table_name ;

(3) การลบ Table


SQL > DROP TABLE table_name;
เชน SQL > DROP TABLE testtable1;
Copyright © 2009 by Peekanung                                                                                                     14

(4) การแก้ไขโครงสร้าง Table (Alter Table)

 แก้ไขช่ ือ table SQL > ALTER TABLE tbtest RENAME TO tbdemo;


 แก้ไขช่ ือ column SQL > ALTER TABLE tbdemo RENAME COLUMN col1 TO democol;
 เพ่ิม column SQL > ALTER TABLE tbdemo ADD COLUMN col1;
 ลบ column SQL > ALTER TABLE tbdemo DROP COLUMN col1;
 เปล่ียน Owner SQL > ALTER TABLE tbdemo CHANGE OWNER TO ‘new user name’;
 กำาหนด default
SQL > ALTER TABLE tbdemo ADD COLUMN col2 SET DEFAULT ‘1’ ;
 ยกเลิก default
SQL > ALTER TABLE tbdemo ALTER COLUMN col2 DROP DEFAULT ;

(5) Temporary Tables


Temporary Tables เปนตารางชัว่คราว จะมีอยูใน database session ท่ีมีการกำาหนดขึ้นเทานั ้น เม่ ือมีการปด หรือ
ยกเลิกการทำางานของ database session นั ้น temporary tables ก็จะถูกลบโดยอัตโนมัติ
การใช้งาน Temporary Tables นั ้น จะใช้งานและมองเห็นได้เฉพาะผู้ท่ีสร้างใน database session นั ้นๆเทานั ้น ผู้ใช้
คนอ่ ืนๆไมสามารถมองเห็นได้ ดังนั ้นผู้ใช้งานแตละคนจึงสามารถสร้าง Temporary Tables ช่ ือเดียวกันได้
Temporary tables สวนมากจะถูกใช้ในกรณี ท่ีต้องการข้อมูล จาก Query ท่ีซับซ้อน ท่ีต้องการ execute คำาสัง่ในที
เดียว แล้วนำ าข้อมูลท่ีได้ไปเก็บไว้ท่ี Temporary Tables
ตัวอยาง
SQL > SELECT * INTO TEMPORARY position_doctor
FROM position WHERE postcode=60403;

3.3.2 View
Views เปนตารางข้อมูลเทียม ซ่ ึง view จะเกิดจากตารางข้อมูล(Table) ท่ีมีอยูในฐานข้อมูล โดยใช้คำาสัง่ SELECT
ข้อมูลมาแสดงตามท่ีกาำ หนด View จะมีการกำาหนดสิทธิตางๆแยกจาก ตาราง และสวนตางๆ ของฐานข้อมูล ดังนั ้นเราจึง
สามารถกำาหนดสิทธิให้ผู้ใช้ท่ีเราต้องการกำาหนดเห็นเฉพาะข้อมูลในสวนท่ีต้องการได้

(1) การสร้าง View

SQL > CREATE [ OR REPLACE ] [ TEMP | TEMPORARY ] VIEW name [ ( column_name [, ...] ) ]
AS query

ตัวอยาง
SQL > CREATE VIEW myview AS
SELECT city, temp_lo, temp_hi, prcp, date, location
FROM weather, cities
WHERE city = name;

(2) การด้View
ด้โครงสร้าง view SQL > \d view_name;
เชน SQL > \d myview;
View "public.myview"
Column | Type | Modifiers
------------+-----------------------+-----------
city | character varying(80) |
temp_lo | integer |
temp_hi | integer |
prcp | real |
date | date |
name | text |
population | real |
altitude | integer |
View definition:
SELECT weather.city, weather.temp_lo, weather.temp_hi, weather.prcp, weather.date, cities.name,

cities.population, cities.altitude
FROM weather, cities
WHERE weather.city::text = cities.name;
Copyright © 2009 by Peekanung                                                                                                     15

การด้ข้อม้ลใน View
SQL > SELECT * FROM myview;

(3) การลบ View

SQL > DROP VIEW [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]

Parameters:
IF EXISTS ถ้าไมมีช่ือ view ท่ีต้องการลบ ให้แสดง notice แทน error
name ช่ ือ view
CASCADE กรณี ท่ีมี objects ใดขึ้นอยูกับ view นี้ ให้ถูกลบโดยอัตโนมัติ
RESTRICT กรณี ท่ีมี objects ใดขึ้นอยูกับ view นี้ จะไมอนุญาตให้ drop view (เป็ นคา default)

ตัวอยาง
กรณี veiw 'v_myveiw' ไมมีอย้จริง
SQL > DROP view v_myview;
ERROR: view "v_myview" does not exist //ไม่สามารถลบ view ได้เน่ ืองจากไม่มีช่ือ view นี้อย่่จริง

SQL > DROP VIEW IF EXISTS v_myview;


NOTICE: view "v_myview" does not exist, skipping
DROP VIEW

(4) การแก้ไข View ทำาได้แคการเปล่ียนช่ ือ view เทานั ้น


SQL > ALTER VIEW name RENAME TO newname ;

เชน SQL > ALTER VIEW myview RENAME TO myview02;


// แก้ไข view โดยเปล่ียนช่ ือจาก 'myview' เป็ น 'myview02'

3.4 การจัดการ Roles

postgreSQL ใช้ 'roles' ในการจัดการ การเข้าถึง database สำาหรับ postgreSQL version 8.1 หรือน้ อยกวา
user และ group จะถือเป็ นคนละอยางกัน แตหลังจาก version 8.1 เป็ นต้นมา role สามารถเป็ นได้ทัง้ user , group หรือทัง้
สองอยาง

3.4.1 การสร้าง Roles

คำาสัง่ CREATE USER เป็ น alias ของคำาสัง่ CREATE ROLE สามารถใช้แทนกันได้ มีข้อแตกตางเพียงข้อเดียวคือ
CREATE USER จะมี option 'LOGIN' เป็ น default จึงสามารถใช้ในการ Log in ได้เลย
CREATE ROLE จะมี option 'NOLOGIN' เป็ น default ถ้าต้องการใช้ Log in ได้ด้วยต้องระบุ option 'LOGIN'

ผู้ท่ีมีสิทธิในการสร้าง Users จะต้องเปน Superuser เทานั ้น (default คือ user : postgres)


SQL > CREATE [USER|ROLE] name [ [ WITH ] option [...] ]
Options : SUPERUSER | NOSUPERUSER กำาหนดให้เป็ น superuser หรือไม่
| CREATEDB | NOCREATEDB กำาหนดให้สามารถ create database ได้หรือไม่
| CREATEROLE | NOCREATEROLE กำาหนดให้สามารถ create role ได้หรือไม่
| CREATEUSER | NOCREATEUSER กำาหนดให้สามารถ create user ได้หรือไม่
| INHERIT | NOINHERIT กำาหนดให้ได้รับ privileges จาก role ท่ีเป็ นสมาชิกอย่่หรือไม่
| LOGIN | NOLOGIN กำาหนดให้ใช้ในการ Log in ได้ด้วยหรือไม่
| CONNECTION LIMIT connlimit จำากัดจำานวนท่ีใช้ connect หรือไม่ (ค่า -1 หมายถึง unlimit)
(default คือ unlimit)
| [ ENCRYPTED | UNENCRYPTED ] PASSWORD 'password' encryp password หรือไม่
Copyright © 2009 by Peekanung                                                                                                     16

| VALID UNTIL 'timestamp' กำาหนดวัน และเวลา หมดอายุให้ password


| IN ROLE rolename [, ...] assign role ให้กับ user ท่ีสร้าง
| IN GROUP rolename [, ...] assign group ให้กับ user ท่ีสร้าง ( ปั จจุบันเลิกใช้แล้ว
ถ้ากำาหนด option นี้ จะหมายถึง option IN ROLE)
| ROLE rolename [, ...] กำาหนด user ให้กับ role ท่ีสร้าง
| ADMIN rolename [, ...] กำาหนด user ให้กับ role ท่ีสร้าง โดย user จะมี Admin option ด้วย
| USER rolename [, ...] ปั จจุบันเลิกใช้แล้ว ถ้ากำาหนด option นี้จะหมายถึง option ROLE
| SYSID uid ปั จจุบันเลิกใช้แล้ว

หมายเหตุ option ท่ีขีดเส้นใต้ไว้ หมายถึง คา default

ตัวอยาง
SQL > CREATE USER user01;
// สร้าง user ช่ ือ 'user01' แบบไม่ระบุ password ( ซ่ ึง user นี้จะยังเข้าใช้งาน database ไม่ได้ ต้อง
กำาหนด
password ให้กับ user ก่อน)
SQL > ALTER USER user01 WITH PASSWORD 'user0123' ;
// กำาหนด password ให้ user ท่ีสร้างไว้แล้ว
SQL > CREATE USER user01 WITH PASSWORD 'user0123';
// สร้าง user ช่ ือ 'user01' แบบระบุ password
SQL > CREATE USER user01 WITH PASSWORD 'user0123' CREATEDB;
// สร้าง user ท่ีสามารถสร้าง Database ได้
SQL > CREATE USER test1 role test2;
// assign role 'test1' ให้ user 'test2' เทียบเท่ากับ SQL > GRANT test1 TO test2 ;
ในกรณี นี้ test1 เป็ น role , test2 เป็ น user (หลัง option role จะเป็ น user)
SQL > CREATE USER test3 in role test2 ;
// assign role 'test2' ให้ user 'test3' เทียบเท่ากับ SQL > GRANT test2 TO test3;
ในกรณี นี้ test2 เป็ น role , test3 เป็ น user (หลัง option in role จะเป็ น role )
SQL > CREATE USER test4 admin test2 ;
// assign role 'test4' ให้ user 'test2' โดย 'test2' สามารถ grant privileges ให้ user อ่ ืนได้
เทียบเท่ากับ SQL > GRANT test2 TO test3 WITH ADMIN OPTION ;

3.4.2 การแก้ไข Roles


SQL > ALTER [USER|ROLE] user-name [[WITH] option ]...

Option : SUPERUSER | NOSUPERUSER


| CREATEDB | NOCREATEDB
| CREATEROLE | NOCREATEROLE
| CREATEUSER | NOCREATEUSER
| INHERIT | NOINHERIT
| LOGIN | NOLOGIN
| CONNECTION LIMIT connlimit
| [ ENCRYPTED | UNENCRYPTED ] PASSWORD 'password'
| VALID UNTIL 'timestamp'

3.4.3 การลบ Roles


SQL > DROP USER user-name

3.4.4 การด้ Roles


Copyright © 2009 by Peekanung                                                                                                     17

SQL > \du


List of roles
Role name | Superuser | Create role | Create DB | Connections | Member of
-----------+-----------+-------------+-----------+-------------+-----------
abc | yes | yes | yes | no limit | {}
postgres | yes | yes | yes | no limit | {}
test | no | yes | yes | no limit | {}
testuser | no | yes | yes | no limit | {}
user01 | no | yes | yes | no limit | {}
xyz | yes | yes | yes | no limit | {}
(6 rows)

SQL > SELECT * FROM pg_user;


usename | usesysid | usecreatedb | usesuper | usecatupd | passwd | valuntil | useconfig
----------+----------+-------------+----------+-----------+----------+----------+-----------
postgres | 10 |t |t |t | ******** | |
test | 16514 | t |f |f | ******** | |
testuser | 16532 | t |f |f | ******** | |
user01 | 16535 | t |f |f | ******** | |
xyz | 16582 | t |t |t | ******** | |
abc | 16587 | t |t |t | ******** | |
(6 rows)

3.4.5 การกำาหนดสิทธิการใช้งานข้อม้ล
เม่ ือมีการสร้างตารางข้อมูลขึ้นมา ผู้ท่ีสร้างตาราง(owner)เทานั ้นท่ีมีสิทธิในการใช้งาน ถ้าต้องการให้ผู้อ่ืนใช้งานได้ด้วย
จะต้องมีการแก้ไขสิทธิของตาราง(Table’s permission) โดยการใช้คำาสัง่ GRANT โดยคำาสัง่นี้ สามารถกำาหนดขอบเข
ตการใช้งาน SELECT, UPDATE, DELETE, RULE,ALL โดยท่ีกำาหนดการใช้ เปนรายบุคคล กลุม หรือทัง้หมด(Public)
และ REVOKE เปนคำาสัง่ ยกเลิกการกำาหนดสิทธิตางๆ ท่เี กิดจากคำาสัง่ GRANT

(1) GRANT
SQL > GRANT { { SELECT | INSERT | UPDATE | DELETE | REFERENCES | TRIGGER }
[,...] | ALL [ PRIVILEGES ] }
ON [ TABLE ] tablename [, ...]
TO { [ GROUP ] rolename | PUBLIC } [, ...] [ WITH GRANT OPTION ] ;

SQL > GRANT { { USAGE | SELECT | UPDATE }


[,...] | ALL [ PRIVILEGES ] }
ON SEQUENCE sequencename [, ...]
TO { [ GROUP ] rolename | PUBLIC } [, ...] [ WITH GRANT OPTION ]

SQL > GRANT { { CREATE | CONNECT | TEMPORARY | TEMP } [,...] | ALL [ PRIVILEGES ] }
ON DATABASE dbname [, ...]
TO { [ GROUP ] rolename | PUBLIC } [, ...] [ WITH GRANT OPTION ]

SQL > GRANT { EXECUTE | ALL [ PRIVILEGES ] }


ON FUNCTION funcname ( [ [ argmode ] [ argname ] argtype [, ...] ] ) [, ...]
TO { [ GROUP ] rolename | PUBLIC } [, ...] [ WITH GRANT OPTION ]

SQL > GRANT { USAGE | ALL [ PRIVILEGES ] }


ON LANGUAGE langname [, ...]
TO { [ GROUP ] rolename | PUBLIC } [, ...] [ WITH GRANT OPTION ]

SQL > GRANT { { CREATE | USAGE } [,...] | ALL [ PRIVILEGES ] }


ON SCHEMA schemaname [, ...]
TO { [ GROUP ] rolename | PUBLIC } [, ...] [ WITH GRANT OPTION ]

SQL > GRANT { CREATE | ALL [ PRIVILEGES ] }


ON TABLESPACE tablespacename [, ...]
TO { [ GROUP ] rolename | PUBLIC } [, ...] [ WITH GRANT OPTION ]

SQL > GRANT role [, ...] TO rolename [, ...] [ WITH ADMIN OPTION ]
Copyright © 2009 by Peekanung                                                                                                     18

ตัวอยาง
SQL > GRANT all ON DATABASE pis TO user1; // กำาหนดให้ user1 มีสิทธิท ์ ุกอย่างบน database pis
SQL > GRANT all ON person TO user1; // กำาหนดให้ user1 มีสิทธิท ์ ุกอย่างบน table person
SQL > GRANT select ON person TO user2; // กำาหนดให้ user2 มีสิทธิ ์ select บน table person

(2) REVOKE
SQL > REVOKE [ GRANT OPTION FOR ]
{ { SELECT | INSERT | UPDATE | DELETE | REFERENCES | TRIGGER }
[,...] | ALL [ PRIVILEGES ] }
ON [ TABLE ] tablename [, ...]
FROM { [ GROUP ] rolename | PUBLIC } [, ...]
[ CASCADE | RESTRICT ]

SQL > REVOKE [ GRANT OPTION FOR ]


{{ USAGE | SELECT | UPDATE }
[,...] | ALL [ PRIVILEGES ] }
ON SEQUENCE sequencename [, ...]
FROM { [ GROUP ] rolename | PUBLIC } [, ...]
[ CASCADE | RESTRICT ]

SQL > REVOKE [ GRANT OPTION FOR ]


{{ CREATE | CONNECT | TEMPORARY | TEMP } [,...] | ALL [ PREVILEGES]}
ON DATABASE dbname [, ...]
FROM { [ GROUP ] rolename | PUBLIC } [, ...]
[ CASCADE | RESTRICT ]

SQL > REVOKE [ GRANT OPTION FOR ]


{ EXECUTE | ALL [PRIVILEGES]}
ON FUNCTION funcname ( [ [ argmode ] [ argname ] argtype [, ...] ] ) [, ...]
FROM { [ GROUP ] rolename | PUBLIC } [, ...]
[ CASCADE | RESTRICT ]

SQL > REVOKE [ GRANT OPTION FOR ]


{ USAGE | ALL | PRIVILEGES ] }
ON LANGUAGE langname [, ...]
FROM { [ GROUP ] rolename | PUBLIC } [, ...]
[ CASCADE | RESTRICT ]
SQL >REVOKE [ GRANT OPTION FOR ]
{ { CREATE | USAGE } [,...] | ALL [ PRIVILEGES ] }
ON SCHEMA schemaname [, ...]
FROM { [ GROUP ] rolename | PUBLIC } [, ...]
[ CASCADE | RESTRICT ]

SQL >REVOKE [ GRANT OPTION FOR ]


{ CREATE | ALL [ PRIVILEGES ] }
ON TABLESPACE tablespacename [, ...]
FROM { [ GROUP ] rolename | PUBLIC } [, ...]
[ CASCADE | RESTRICT ]

SQL >REVOKE [ ADMIN OPTION FOR ]


role [, ...]
FROM rolename [, ...]
[ CASCADE | RESTRICT ]
ตัวอยาง
SQL > REVOKE all ON DATABASE pis FROM user1;
// ยกเลิกการให้สิทธิท
์ ุกอย่างบน database pis แก่ user1
SQL > REVOKE all ON person FROM user1; // ยกเลิกการให้สิทธิท ์ ุกอย่างบน table pis แก่ user1
SQL > REVOKE select ON person FROM user2; // ยกเลิกการให้สิทธิ ์ select บน table pis แก่ user2
Copyright © 2009 by Peekanung                                                                                                     19

3.5 Data type


เม่ ือสร้าง Table จะต้องมีการกำาหนดชนิ ดของข้อมูลท่ีจะเก็บไว้ในแตละคอลัมน์(Column) เชน ช่ ือเปนตัวอักษร วันเกิด
เก็บคาเปนวันท่ี เงินเดือนเปนตัวเลข
เป็ นต้น
ข้อมูลท่ีอยูใน PostgreSQL ถูกกำาหนดด้วยชนิ ดข้อมูล(data type) ซ่ ึงมีประเภทของชนิ ดข้อมูล(data type) หลาย
ประเภท ดังนี้

3.5.1 Character types

Data type Description


Character varying(n), varchar (n) variable-length with limit
Character (n) , char (n) fixed-length, blank padded
text variable unlimited length

3.5.2 Numberic types

Data type Size Description Range


smallint 2 bytes small range fixed- precision -32768 to +32767

integer 4 bytes usual choice for integer -2147483648 to +2147483647


bigint 8 bytes large-range integer -9223372036854775808 to
9223372036854775807
decimal variable user-specified precision, exact no limit
numeric variable user-specified precision, exact no limit
real 4 bytes variable-precision, inexact 6 decimal digits precision
double precision 8 bytes variable-precision, inexact 15 decimal digits precision
serial 4 bytes autoincrementing integer 1 to 2147483647
bigserial 8 bytes large autoincrementing integer 1 to 9223372036854775807

3.5.3 Date/Time types

Data type Size Description


timestamp [ (p) ] [ without time zone ] 8 bytes both date and time
timestamp [ (p) ] with time zone 8 bytes both date and time, with time zone
interval [ (p) ] 12 bytes time intervals
date 4 bytes dates only
time [ (p) ] [ without time zone ] 8 bytes times of day only
time [ (p) ] with time zone 12 bytes times of day only, with time zone
3.5.4 Logical types

Data type Description Renge


boolean(bool) TRUE, FALSE, or NULL true, 't', 'y', 'yes', 1
false, 'f', 'n', 'no', 0
Copyright © 2009 by Peekanung                                                                                                     20

3.6 การ Import / Export data


คำาสั่ง COPY
ในการนำ าข้อมูลเข้าและออกจากฐานข้อมูลโดยการใช้คำาสัง่ COPY ซ่ ึงคำาสัง่นี้ จะเขียนข้อมูลจากตารางเปนไฟล์ข้อมูลชนิ ด
ASCII และนำ าข้อมูลท่ีเปนไฟล์ข้อมูลชนิ ด ASCII เข้า table ได้
คำาสัง่นี้สามารถนำ าไปใช้ในการสำารองข้อมูล หรือสงผานข้อมูลระหวาง postgreSQL กับโปรแกรมอ่ ืนๆได้

COPY tablename [ ( column [, ...] ) ]


FROM { 'filename' | STDIN }
[ [ WITH ]
[ BINARY ]
[ OIDS ]
[ DELIMITER [ AS ] 'delimiter' ]
[ NULL [ AS ] 'null string' ]
[ CSV [ HEADER ]
[ QUOTE [ AS ] 'quote' ]
[ ESCAPE [ AS ] 'escape' ]
[ FORCE NOT NULL column [, ...] ]

COPY { tablename [ ( column [, ...] ) ] | ( query ) }


TO { 'filename' | STDOUT }
[ [ WITH ]
[ BINARY ]
[ OIDS ]
[ DELIMITER [ AS ] 'delimiter' ]
[ NULL [ AS ] 'null string' ]
[ CSV [ HEADER ]
[ QUOTE [ AS ] 'quote' ]
[ ESCAPE [ AS ] 'escape' ]
SQL >[COPY...TO
FORCE QUOTE column เป
[, น
...]คำา] สัง่สำาเนาข้อมูลในตารางไปเปนไฟล์ข้อมูล
SQL > COPY...FROM เปนคำาสัง่นำ าข้อมูลไฟล์เข้าตาราง
อธิบาย
BINARY ข้อม่ลจะเป็ น binary format ทำาให้ไม่สามาถใช้ option DELIMITER, NULL หรือ CSV ได้
OIDS ระบุให้เอาค่า OIDS ด้วย
DELIMITERS กำาหนดตัวคัน ่ ระหว่าง column (default จะเป็ น tab)
NULL กำาหนดค่าให้ฟิลด์ท่ีเป็ น null (default คือ \N สำาหรับ text file , เป็ นค่าว่างสำาหรับ csv file )
CSV กำาหนดให้เป็ น csv file format
HEADER สำาหรับ output ค่าจะเป็ นช่ ือ column , input เป็ นการบอกว่าบรรทัดแรกเป็ น header
QUOTE กำาหนด ASCII quotation character สำาหรับ csv file format (default คือ double-
quote)
ตัวอยาง
SQL > COPY country TO '/tmp/country.txt' WITH DELIMITER '|';
// copy ข้อม่ลใน table 'country' เก็บไว้ท่ี /tmp ช่ ือไฟล์ country.txt ข้อม่ลถ่กคัน
่ ด้วย |
SQL > COPY country TO '/tmp/country.txt' WITH NULL 'null data';
// copy ข้อม่ลใน table 'country' เก็บไว้ท่ี /tmp ช่ ือไฟล์ country.txt โดยข้อม่ลท่ีเป็ น null จะถ่กแทนท่ีด้วย
คำาว่า 'null data'
SQL > COPY country FROM '/tmp/country.txt' ;
// นำ าข้อม่ลในไฟล์ /tmp/country.txt เข้า table country
Copyright © 2009 by Peekanung                                                                                                     21

3.7 PostgreSQL function


PostgreSQL มีคุณสมบัติให้สร้าง Server-side Function ซ่ ึงบางครัง้เรียกวา Stored
procedures ได้ การท่ีเราสร้าง Server-side Function และ function จะติดไปกับ Database จะทำาให้นำาไปใช้งานได้กับโปร
แกรมอ่ ืนๆได้ โดยท่ีโปรแกรมเหลานั ้นไมต้องสร้างหรือสำาเนา function
เหลานั ้นไปอีก เราสามารถเรียกใช้ function จากคำาสัง่ SQL Queries ได้เลย และเม่ ือมีการแก้ไข function ทุกโปรแกรมท่ีเรียก
ใช้ function นี้กจ็ ะเปล่ียนไปตามท่ีแก้ไขด้วย

Server-side functions สามารถเขียนได้จากภาษาตางๆดังนี้


 SQL
 PL/PGSQL
 PL/TCL
 PL/Perl
 C

ตัวอยางการสร้าง SQL functions

ในการสร้าง function สามารถกำาหนดช่ ือและบันทึกเก็บไว้เพ่ ือเรียกใช้ในภายหลังได้อีก การสร้างใช้คำาสัง่ CREATE


FUNCTION และการลบใช้คำาสัง่ DROP FUNCTION

คำาสัง่ CREATE FUNCTION ต้องการข้อมูลตางๆท่ีใช้กำาหนดการสร้างดังนี้


− ช่ ือ Function
− จำานวน Argument
− ชนิ ดข้อมูลของแตละ Argument
− Function return type
− การทำางาน
− ภาษาท่ีใช้ในการทำางาน

เชน
SQL > CREATE FUNCTION tax(numeric)
RETURNS numeric
AS
'SELECT ($1*0.07::numeric(8,2))::numeric(8,2);'
LANGUAGE 'sql';

SQL > SELECT tax(20);


tax
------
1.40
(1 row)

อธิบาย
− ช่ ือ Function คือ tax
− จำานวน Argument 1 การเรียกใช้ argument กำาหนดตามลำาดับ $1 $2 $3
− ชนิ ดข้อมูลของแตละ Argument คือ numeric
− Function return type เป็ น numeric
− การทำางาน คือ SELECT ($1*0.07::nueric(8,2)):: nueric(8,2);
ในคำาสัง่การทำางานสามารถใช้ INSERT UPDATE DELETE ได้รวมทัง้ Multiple Queries แยกคำาสัง่โดยใช้
semicolons คัน ่ แตละคำาสัง่
− ภาษาท่ีใช้ในการทำางาน คือ SQL

การใช้ function ในการ SELECT Query จะชวยลดปญหาความผิดพลาดในการ join table แตก็ทำาให้ทำางานช้ากวา


เน่ ืองจากการใช้ function จะมีการ execution function ทุกๆรายการข้อมูล

** หมายเหตุ
ในกรณี ท่ีสร้าง Function แล้วเกิด error
ERROR: language "plpgsql" does not exist
HINT: Use CREATE LANGUAGE to load the language into the database.
วิธีแก้ไขคือ ต้อง Login ด้วย user ท่ีเป็ นเจ้าของ Database แล้วใช้คำาสัง่
Copyright © 2009 by Peekanung                                                                                                     22

SQL > CREATE LANGUAGE <ภาษาท่ีใช้>;


เชน
SQL > CREATE LANGUAGE plpgsql;
// เป็ นการ install PostgreSQL procedural languages (PL/pgSQL)

3.8 Partitioning table

การทำา Partitioning Table คือ การแบงข้อมูลใน Table ออกเป็ น Table ยอยหลายๆ Table เหมาะสำาหรับ Table ท่ีมีข้อมูล
จำานวนมาก ซ่ึงมีข้อดีตา งๆ ดังนี้
 Manageability
 สามารถจัดการกับข้อมูลสวนยอยได้โดยไมกระทบกับข้อมูลทัง้หมด
 การ Backup / Recovery สามารถแยกทำาแตละ partition ได้ ทำาให้การทำางานเร็วขึ้น และไมมีผลกระทบกับ
partition อ่ ืน
 สามารถแยก Tablespace ของแตละ Partition ได้ ทำาให้การจัดการ tablespace ทำาได้งายขึ้น
 Availability
 เม่ ือต้องมีการจัดการบางอยางเดียวกับ Disk เชน เปล่ียน หรือซอม disk ระบบยังสามารถทำางานตอไปได้ เน่ ืองจาก
ไมมีผลกระทบใดๆ ตอข้อมูลท่ีอยูตาง disk กัน (กรณี ท่ีแตละ partition มีการแยก disk กัน)
 Perfermance
 การ Query ข้อมูลจาก partition จะเร็วกวาการ query จาก master table เน่ ืองจากข้อมูลมีจำานวนน้ อยกวา

ชนิ ดของ Partitioning table ใน Postgresql


1. Range Partitioning : แบง partition ตามชวงของข้อมูล โดยไมมีการทับ
ซ้อน (overlap) ของข้อมูลในแตละ partition เชน แบงเป็ นชวงปี หรือ ชวงเดือน เป็ นต้น
2. List Partitioning : แบง partition ตามรายการ หรือหมวดหมู ตามคา
ของข้อมูลท่ีกำาหนด เชน แบงข้อมูลตามทวีปตางๆ ของโลก เป็ นต้น

ตัวอยาง การสร้าง Partition table


1. แก้ไขไฟล์ postgresql.conf โดย set constraint_exclusion = on
ซ่ึงจะทำาให้ query's planner สามารถใช้ constraints ในการเพ่ิมประสิทธิภาพของ query ได้

2. หลังจากนั ้นให้ restart service ของ database โดยต้อง log in ด้วย user : root แล้วใข้คำาสัง่
$ service postgresql-8.3 restart

3. สร้าง 'Master table'


SQL > CREATE TABLE shipment (
id SERIAL PRIMARY KEY,
address TEXT NOT NULL,
shipping_date TIMESTAMP NOT NULL);

4.สร้าง 'Child tables' เพ่ ือใช้เป็ น partition ของ Master table โดยมี Contraints เป็ นตัวข้อกำาหนด column key ในการ
แบง partition
SQL > CREATE TABLE shipment_part_2008 (
CHECK (shipping_date >= DATE '2008-01-01'
AND shipping_date < DATE '2009-01-01')
) INHERITS (shipment);

SQL > CREATE TABLE shipment_part_pre2008 (


CHECK (shipping_date < DATE '2008-01-01')
) INHERITS (shipment);

5. สร้าง Index ให้แตละ child table (โดยใช้ key เดียวกับ column key ของ constrains ดังตัวอยาง คือ shipping_date )
SQL > CREATE INDEX shipping_date_2008 ON shipment_part_2008 (shipping_date);
SQL > CREATE INDEX shipping_date_pre2008 ON shipment_part_pre2008 (shipping_date);
SQL > CREATE INDEX shipping_date_post2008 ON shipment_part_post2008 (shipping_date);

6. สร้าง Function เพ่ ือกำาหนดให้มีการจัดเก็บข้อมูลใน partition table ท่ีถูกต้อง ในท่ีนี้ต้องการแบงเป็ น 3 partition คือ
ปี 2008 (shipment_part_2008),กอนปี 2008 (shipment_part_pre2008) และหลังปี 2008 (shipment_part_post 2008)
Copyright © 2009 by Peekanung                                                                                                     23

โดยใช้ฟิลด์ shipping_date เป็ น key


SQL > CREATE OR REPLACE FUNCTION shipment_insert()
RETURNS TRIGGER AS $$
BEGIN
IF (NEW.shipping_date >= DATE '2008-01-01'
AND NEW.shipping_date < DATE '2009-01-01') THEN
INSERT INTO shipment_part_2008 VALUES (NEW.*);
ELSIF (NEW.shipping_date < DATE '2008-01-01') THEN
INSERT INTO shipment_part_pre2008 VALUES (NEW.*);
ELSEIF (NEW.shipping_date > DATE '2008-12-31') THEN
INSERT INTO shipment_part_post2008 VALUES (NEW.*);
ELSE
RAISE EXCEPTION 'Date out of range. Fix the shipment_insert()
function!';
END IF;
RETURN NULL;
END;
$$
LANGUAGE plpgsql;

7. สร้าง Trigger เพ่ ือเป็ นการสัง่ execute function กอนมีการ Insert data เข้า master table ทุกครัง้
SQL > CREATE TRIGGER shipment_insert_trigger
BEFORE INSERT ON shipment
FOR EACH ROW EXECUTE PROCEDURE shipment_insert();

8. ทดสอบโดยการ Insert ข้อมูลเข้า Master table


SQL > INSERT INTO shipment (address, shipping_date) VALUES ('Alaska', '2008-08-08');
SQL > INSERT INTO shipment (address, shipping_date) VALUES ('Texas', '2007-07-07');
SQL > INSERT INTO shipment (address, shipping_date) VALUES ('Alaska', '2009-08-08');

SQL > SELECT * FROM shipment ;


id | address | shipping_date
----+---------+---------------------
1 | Dakota | 2008-08-08 00:00:00
2 | Texas | 2007-07-07 00:00:00
3 | Alaska | 2009-08-08 00:00:00
(3 rows)

SQL > SELECT * FROM shipment_part_2008;


id | address | shipping_date
----+---------+---------------------
1 | Dakota | 2008-08-08 00:00:00
(1 row)

SQL > SELECT * FROM shipment_part_pre2008;


id | address | shipping_date
----+---------+---------------------
2 | Texas | 2007-07-07 00:00:00
(1 row)

SQL > SELECT * FROM shipment_part_post2008 ;


id | address | shipping_date
----+---------+---------------------
6 | Alaska | 2009-08-08 00:00:00
(1 rows)
จะเห็นวา ข้อมูลถูก Insert เข้า partition table ท่ีถูกต้อง ตามข้อกำาหนดแล้ว
Copyright © 2009 by Peekanung                                                                                                     24

3.9 Materialized view

Materialized view (mview) เหมือน View ตรงท่ีมี link definition อยูกับ base table และเหมือน table ตรงท่ีมันจะเก็บ
ข้อมูลไว้ท่ต
ี ัวเอง DBA จะเป็ นผู้กำาหนดวาจะมีการ refresh data บอยแคไหน โดยท่ี user ไมจำาเป็ นต้องรู้วามี mview อยู เพราะ
สามารถ select statement ผาน base table ได้เหมือนเดิม

ข้อแตกตางระหวาง materialized view กับ view

View Materialized view


ไมมีข้อมูลอยูจริง มีแต statement ท่ีเอาไว้เรียกข้อมูลจาก เป็ นการ duplicate data จาก base table ทำาให้มีข้อมูล
base table (logical representation of table) จริงเก็บไว้ท่ี mview เลย ทำาให้การ access data เร็วกวา
view
Select ได้อยางเดียว ไมสามารถใช้คำาสัง่ Insert, Update, นอกจาก Select แล้ว สามารถใช้คำาสัง่ Insert, Update,
Delete ข้อมูลใน view ได้ Delete ข้อมูลใน view ได้

หมายเหตุ
 Postgresql ไมสามารถใช้ Insert, Update, Delete กับ view ได้
 Oracle สามารถใช้คำาสัง่ Insert, Update, Delete ได้ ในกรณี ท่ี view ไมได้เกิดจากการ join table การคำานวณ
หรือ virtual column ตัวอยาง virtual column เชน
SQL > create view v1 as select id, 'abc' as name from table1;
//name เป็ น virtual column ไม่สามารถใช้คำาสัง่ Insert, Update, Delete กับ column 'name' ได้
(แต่ใช้กับ 'id' โดยไม่ระบุ 'name'ได้)
SQL > insert into v1(id,name) values (2,'name02') ;
// insert ไม่ได้ เน่ ืองจาก name เป็ น virtual column
SQL > insert into v1(id) values (2) ;
// insert ได้เน่ ืองจากระบุเฉพาะ column 'id' ซ่ ึงเป็ น column ท่ีมีอย่่จริง

ขนิ ดของ materialized view


1. Snapshot
■ ข้อมูลจะเปล่ียนแปลงตาม base table เม่ ือมีการสัง่ให้ refresh data (Manual)
■ เหมาะสำาหรับข้อมูลท่ีมีการเปล่ียนแปลงครัง้ละจำานวนมาก แตไมเหมาะกับข้อมูลท่ีมีการเปล่ียนแปลงบอย
2. Eager
■ ข้อมูลจะเปล่ียนแปลงทุก transaction เม่ ือ base table มีการเปล่ียนแปลง
■ ถ้า base table มีการเปล่ียนแปลงบอยครัง้ จะเกิดการเปล่ียนแปลงท่ี mview อยูเสมอ ทำาให้สิน ้ เปลือง
ทรัพยากร
■ เหมาะสำาหรับข้อมูลท่ี base table มีการเปล่ียนแปลงน้ อย แตไมเหมาะกับการ import หรือ เปล่ียนแปลง
ข้อมูลจำานวนมาก

3. Lazy
■ ข้อมูลจะเปล่ียนแปลงตาม base table เม่ ือมีการ commit เทานั ้น ดังนั ้นข้อมูลจะไมมีการเปล่ียนแปลงบอย
เทาแบบ Eager แตข้อมูลจะถูกต้องตรงกับ base table มากกวาแบบ snapshot เน่ ืองจากไมต้องรอให้มีการ
สัง่ refresh
■ ข้อมูลใน mview กับ base table อาจจะไมตรงกันชัว ่ ขณะ (ขณะท่ียังอยูใน transaction แตยังไมได้
commit)
4. Very lazy
■ คล้ายแบบ snapshot คือข้อมูลจะเปล่ียนแปลงเม่ ือมีการสัง่ refresh data แตการ update ข้อมูลจะทำาได้เร็ว
กวา และใช้ทรัพยากรน้ อยกวา

วิธีการทำา Materialized view


3.9.1 Snapshot
ข้อมูลใน materialized view จะมีการเปล่ียนแปลง เม่ ือถูกสัง่ refresh data เทานั ้น
1.1 สร้าง table matviews เพ่ ือเก็บข้อมูลเก่ียวกับ materialized view
SQL > CREATE TABLE matviews (
mv_name NAME NOT NULL PRIMARY KEY, --ช่ ือ mveiws
v_name NAME NOT NULL, -- ช่ ือ view ท่ีเป็ น base
last_refresh TIMESTAMP WITH TIME ZONE) -- วันเวลาท่ีมีการสัง่ refresh data
Copyright © 2009 by Peekanung                                                                                                     25

WITH OIDS;

1.2 สร้าง Function create_matview เพ่ ือให้เก็บข้อมูลลง table matviews ทุกครัง้ท่ีมีการสัง่ refresh data
พร้อมเช็ควาช่ ือ mviews ต้องไมซำา้
SQL > CREATE OR REPLACE FUNCTION create_matview(NAME, NAME)
RETURNS VOID
SECURITY DEFINER
LANGUAGE plpgsql AS
'DECLARE
matview ALIAS FOR $1;
view_name ALIAS FOR $2;
entry matviews%ROWTYPE;
BEGIN
SELECT * INTO entry FROM matviews WHERE mv_name = matview;

IF FOUND THEN
RAISE EXCEPTION ''Materialized view ''''%'''' already exists.'',
matview;
END IF;
EXECUTE ''REVOKE ALL ON '' || view_name || '' FROM PUBLIC'';
EXECUTE ''GRANT SELECT ON '' || view_name || '' TO PUBLIC'';
EXECUTE ''CREATE TABLE '' || matview || '' AS SELECT * FROM '' || view_name;
EXECUTE ''REVOKE ALL ON '' || matview || '' FROM PUBLIC'';
EXECUTE ''GRANT SELECT ON '' || matview || '' TO PUBLIC'';
INSERT INTO matviews (mv_name, v_name, last_refresh)
VALUES (matview, view_name, CURRENT_TIMESTAMP);
RETURN;
END ';
1.3 สร้าง Function drop_matview เพ่ ือให้ลบ materialized view ออกจาก table matviews
SQL > CREATE OR REPLACE FUNCTION drop_matview(NAME) RETURNS VOID
SECURITY DEFINER
LANGUAGE plpgsql AS
'DECLARE
matview ALIAS FOR $1;
entry matviews%ROWTYPE;
BEGIN
SELECT * INTO entry FROM matviews WHERE mv_name = matview;
IF NOT FOUND THEN
RAISE EXCEPTION ''Materialized view % does not exist.'',
matview;
END IF;
EXECUTE ''DROP TABLE '' || matview;
DELETE FROM matviews WHERE mv_name=matview;
RETURN;
END';
1.4 สร้าง Function refresh_matview เพ่ ือสัง่ refresh data โดยในการสัง่ refresh data ต้องมีการระบุช่ือ
materialized view ด้วยเสมอ
SQL > CREATE OR REPLACE FUNCTION refresh_matview(name) RETURNS VOID
SECURITY DEFINER
LANGUAGE plpgsql AS '
DECLARE
matview ALIAS FOR $1;
entry matviews%ROWTYPE;
BEGIN
SELECT * INTO entry FROM matviews WHERE mv_name = matview;
IF NOT FOUND THEN
RAISE EXCEPTION ''Materialized view % does not exist.'',
matview;
END IF;
EXECUTE ''DELETE FROM '' || matview;
Copyright © 2009 by Peekanung                                                                                                     26

EXECUTE ''INSERT INTO '' || matview || '' SELECT * FROM '' || entry.v_name;

UPDATE matviews
SET last_refresh=CURRENT_TIMESTAMP
WHERE mv_name=matview;

RETURN;
END';

1.5 ตอไปเป็ นการสร้างตัวอยาง table และ view สำาหรับทำา materialized view


SQL > CREATE TABLE player ( pname VARCHAR(255) PRIMARY KEY ); //table เก็บรายละเอียดผ้่
เล่น

SQL > CREATE TABLE game_score ( //table เก็บรายละเอียดคะแนน


pname VARCHAR(255) NOT NULL,
score INTEGER NOT NULL);

SQL > CREATE VIEW player_total_score_v AS //view เก็บรายละเอียดคะแนนสะสมของผ้่เล่น


SELECT
pname,
sum(score) AS total_score
FROM game_score
GROUP BY pname;

SQL > INSERT INTO player VALUES ('player01');


SQL > INSERT INTO player VALUES ('player02');
SQL > INSERT INTO game_score VALUES ('player01','20');
SQL > INSERT INTO game_score VALUES ('player01','10');
SQL > INSERT INTO game_score VALUES ('player02','5');
SQL > INSERT INTO game_score VALUES ('player02','10');
SQL > INSERT INTO game_score VALUES ('player02','5');

SQL > SELECT * from player;


pname
----------
player01
player02
(2 rows)

SQL > SELECT * from game_score ;


pname | score
----------+-------
player01 | 20
player01 | 10
player02 | 5
player02 | 10
player02 | 5
(5 rows)

SQL > SELECT * from player_total_score_v ;


pname | total_score
----------+-------------
player01 | 30
player02 | 20
(2 rows)

1.6 สร้าง materialized views ช่ ือ player_total_score_mv โดยใช้ function create_matview


SQL > SELECT create_matview('player_total_score_mv', 'player_total_score_v');
// player_total_score_mv เป็ นช่ ื่อ materialized view ซ่ ึงต้องกำาหนดเองในแต่ละครัง้ท่ีสร้าง
Copyright © 2009 by Peekanung                                                                                                     27

// player_total_score_v เป็ นช่ ือ view ท่ีได้สร้างไว้ตัง้แต่แรก


SQL > CREATE INDEX pname_idx ON player_total_score_mv(pname);
// สร้าง index ให้กับ materialized view โดยใช้ pname เป็ น ่key

1.7 เม่ ือต้องการ Refresh data ใช้ function refresh_matviews ซ่ ึงการ refresh ทุกครัง้ ต้อง drop index เดิมกอน
เพ่ ือให้การ refresh ทำาได้เร็วขึ้น แล้วคอยสร้าง index ใหม
SQL > DROP INDEX pname_idx ON player_total_score_mv;
SQL > SELECT refresh_matview('player_total_score_mv');
SQL > CREATE INDEX pname_idx ON player_total_score_mv(pname);

*หมายเหตุ : ข้อมูลบน player_total_score_mv จะยังไมมีการเปล่ียนแปลงแม้วา base table มีการเปล่ียนแปลง


แล้ว จนกระทัง่มีการสัง่ refresh data เกิดขึ้น

3.9.2 Eager
ข้อมูลของ materialized view จะเปล่ียนแปลงทุกครัง้ท่ี table เปล่ียนแปลง โดยใช้ความสามารถของ trigger ท่ีอยูบน
table ในการจัดการ ซ่ ึง table นี้ เรียกวา 'Underlying table'

ประเภทของความสัมพันธ์ระหวาง underlying table กับ materialized view


(1) One-to-one
 ข้อมูลใน view อาจ select มาจากบางคอลัมน์ หรือทัง้หมดของ underlying table
 rows ใน view อาจไมขึ้นอยูกับ underlying table
 ตัวอยางเชน เม่ ือ user 1 คนเปล่ียน password จะสงผลตอข้อมูลใน view แค 1 row เทานั ้น
(2) Many-to-one
 ข้อมูลหลายๆ rows ใน view ขึ้นอยูกับ 1 rows บน underlying table ซ่ ึงเป็ นแบบท่ีเจอคอนข้างบอยในการ
join table
 เชน ถ้ามีการเปล่ียน group name จะสงผลตอข้อมูลใน view หลาย row
(3) One-to-many
 ข้อมูลใน view 1 rows มาจากหลาย row ใน underlying table
 เชน ผลรวมของคะแนน ท่ีได้มาจากคะแนนยอยในแตละครัง้
(4) Many-to-many
 เป็ นกรณี ท่ีเจอไมบอยนั ก คือ หลายๆ rows ใน view มาจากหลายๆ rows ใน underlying table ซ่ ึงอาจมา
จากการรวมกันของแตละ relation หลายๆแบบ

การทำา Eager materialized view


2.1 สร้าง function mv_refresh_row โดย ซ่ ึงมีขัน
้ ตอนกา่รทำางานคราวๆ ดังนี้
 ระบุ Primary key ให้ materialized veiw
 delete row ท่ีมีอยูเดิมใน function โดยระบุจาก primary key ท่ีได้กำาหนดไว้
 หลังจากนั ้น select ข้อมูลมาจาก base view แล้ว insert เข้า materialized view
2.2 สร้าง function mv_refresh
mv_refresh จะ refresh เฉพาะ row ท่ีมีการเปล่ียนแปลง ซ่ ึงจะทำางานตามเวลาท่ีได้กำาหนดไว้
2.3 สร้าง trigger ซ่ ึงมีขัน
้ ตอนการทำางาน คราวๆ ดังนี้
 ระบุ Primary key ให้ materialized view
 สำาหรับการ delete และ insert ให้เรียกใช้ function mv_refresh_row
 สำาหรับการ update ต้องมีการระบุ row ท่ีจะมีการเปล่ียนแปลงข้อมูล
ตัวอยาง
SQL > CREATE TABLE a ( -- สร้าง table a
a_id INT PRIMARY KEY,
v INT) WITH OIDS;

SQL > CREATE TABLE b ( -- สร้าง table b


b_id INT PRIMARY KEY,
a_id INT REFERENCES a,
v INT,
Copyright © 2009 by Peekanung                                                                                                     28

expires TIMESTAMP ) WITH OIDS;

SQL > CREATE TABLE c ( --สร้าง table c


c_id INT PRIMARY KEY,
b_id INT REFERENCES b,
v INT) WITH OIDS;

SQL > CREATE VIEW b_v AS -- สร้าง view b_v ซ่ ึงมาจากการ join table a, b และ c
SELECT b.b_id AS b_id,
a.v AS a_v,
b.v AS b_v,
sum(c.v) AS sum_c_v
FROM a JOIN b USING (a_id) JOIN c USING (b_id)
WHERE (b.expires IS NULL OR b.expires >= now())
GROUP BY b.b_id, a.v, b.v;

SQL > SELECT create_matview('b_mv', 'b_v');// สร้าง materialized view โดยใช้ function
create_matview

จากตัวอยาง ข้อมูลใน table a 1 แถว อาจมีผลกับหลายแถวใน view b_v ( 1 : m) , ใน table b 1 แถว มีผลกับ 1
แถวใน view b_v (1:1) และหลาย rows ใน table c มีผลกับ view b_v เพียง 1 แถว (m : 1)

สร้าง function b_mv_refresh_row


SQL > CREATE FUNCTION b_mv_refresh_row(b_mv.b_id%TYPE) RETURNS VOID
SECURITY DEFINER LANGUAGE 'plpgsql' AS
'BEGIN
DELETE FROM b_mv WHERE b_id = $1;
INSERT INTO b_mv SELECT * FROM b_v WHERE b_id = $1;
RETURN;
END';

สร้าง function b_mv_refresh


SQL > CREATE FUNCTION b_mv_refresh() RETURNS VOID
SECURITY DEFINER
LANGUAGE 'plpgsql' AS
'BEGIN
PERFORM b_mv_refresh_row(b_id) //calling a function that has side-effects but no useful result value
FROM b, matviews
WHERE matviews.mv_name = ''b_mv''
AND b.expires >= matviews.last_refresh
AND b.expires < now();

UPDATE matviews
Copyright © 2009 by Peekanung                                                                                                     29

SET last_refresh = now()


WHERE mv_name = ''b_mv'';

RETURN;
END ';

สร้าง trigger ให้ table a, b และ c


1. trigger ของ table a มีดงั นี้
1.1 trigger b_mv_ut จะทำางานหลังจากมีการ update data ใน table a โดยเรียกใช้ function b_mv_a_ut
(ซ่ึงจะเรียกใช้ function b_mv_refresh_row อีกที)
SQL > CREATE FUNCTION b_mv_a_ut() RETURNS TRIGGER
SECURITY DEFINER LANGUAGE 'plpgsql' AS
'BEGIN
IF OLD.a_id = NEW.a_id THEN
PERFORM b_mv_refresh_row(b.b_id) FROM b WHERE b.a_id = NEW.a_id;
ELSE
PERFORM b_mv_refresh_row(b.b_id) FROM b WHERE b.a_id = OLD.a_id;
PERFORM b_mv_refresh_row(b.b_id) FROM b WHERE b.a_id = NEW.a_id;
END IF;
RETURN NULL;
END ';

SQL > CREATE TRIGGER b_mv_ut AFTER UPDATE ON a


FOR EACH ROW EXECUTE PROCEDURE b_mv_a_ut();

1.2 trigger b_mv_dt จะทำางานหลังจากมีการ delete data ใน table a โดยเรียกใช้ function b_mv_a_dt (ซ่ึงจะ
เรียกใช้ function b_mv_refresh_row อีกที)
SQL > CREATE FUNCTION b_mv_a_dt() RETURNS TRIGGER
SECURITY DEFINER LANGUAGE 'plpgsql' AS '
BEGIN
PERFORM b_mv_refresh_row(b.b_id) FROM b WHERE b.a_id = OLD.a_id;
RETURN NULL;
END ';

SQL > CREATE TRIGGER b_mv_dt AFTER DELETE ON a


FOR EACH ROW EXECUTE PROCEDURE b_mv_a_dt();

1.3 trigger b_mv_it จะทำางานหลังจากมีการ insert data ใน table a โดยเรียกใช้ function b_mv_a_it (ซ่ึงจะ
เรียกใช้ function b_mv_refresh_row อีกที)
SQL > CREATE FUNCTION b_mv_a_it() RETURNS TRIGGER
SECURITY DEFINER LANGUAGE 'plpgsql' AS '
BEGIN
PERFORM b_mv_refresh_row(b.b_id) FROM b WHERE b.a_id = NEW.a_id;
RETURN NULL;
END';

SQL > CREATE TRIGGER b_mv_it AFTER INSERT ON a


FOR EACH ROW EXECUTE PROCEDURE b_mv_a_it();

2. trigger ของ table b มีดงั นี้


2.1 trigger b_mv_ut จะทำางานหลังจากมีการ update data ใน table b โดยเรียกใช้ function b_mv_b_ut (ซ่ึงจะ
เรียกใช้ function b_mv_refresh_row อีกที)
SQL > CREATE FUNCTION b_mv_b_ut() RETURNS TRIGGER
SECURITY DEFINER LANGUAGE 'plpgsql' AS '
BEGIN
IF OLD.b_id = NEW.b_id THEN
PERFORM b_mv_refresh_row(NEW.b_id);
Copyright © 2009 by Peekanung                                                                                                     30

ELSE
PERFORM b_mv_refresh_row(OLD.b_id);
PERFORM b_mv_refresh_row(NEW.b_id);
END IF;
RETURN NULL;
END';

SQL > CREATE TRIGGER b_mv_ut AFTER UPDATE ON b


FOR EACH ROW EXECUTE PROCEDURE b_mv_b_ut();
2.2 trigger b_mv_dt จะทำางานหลังจากมีการ delete data ใน table b โดยเรียกใช้ function b_mv_b_dt (ซ่ึงจะ
เรียกใช้ function b_mv_refresh_row อีกที)

SQL > CREATE FUNCTION b_mv_b_dt() RETURNS TRIGGER


SECURITY DEFINER LANGUAGE 'plpgsql' AS '
BEGIN
PERFORM b_mv_refresh_row(OLD.b_id);
RETURN NULL;
END';
SQL > CREATE TRIGGER b_mv_dt AFTER DELETE ON b
FOR EACH ROW EXECUTE PROCEDURE b_mv_b_dt();

2.3 trigger b_mv_it จะทำางานหลังจากมีการ insert data ใน table b โดยเรียกใช้ function b_mv_b_it (ซ่ึงจะ
เรียกใช้ function b_mv_refresh_row อีกที)

SQL > CREATE FUNCTION b_mv_b_it() RETURNS TRIGGER


SECURITY DEFINER LANGUAGE 'plpgsql' AS '
BEGIN
PERFORM b_mv_refresh_row(NEW.b_id);
RETURN NULL;
END';
SQL > CREATE TRIGGER b_mv_it AFTER INSERT ON b
FOR EACH ROW EXECUTE PROCEDURE b_mv_b_it();

3. trigger ของ table c


3.1 trigger b_mv_ut จะทำางานหลังจากมีการ update data ใน table c โดยเรียกใช้ function b_mv_c_ut (ซ่ึงจะ
เรียกใช้ function b_mv_refresh_row อีกที)
SQL > CREATE FUNCTION b_mv_c_ut() RETURNS TRIGGER
SECURITY DEFINER LANGUAGE 'plpgsql' AS '
BEGIN
IF OLD.b_id = NEW.b_id THEN
PERFORM b_mv_refresh_row(NEW.b_id);
ELSE
PERFORM b_mv_refresh_row(OLD.b_id);
PERFORM b_mv_refresh_row(NEW.b_id);
END IF;
RETURN NULL;
END';

SQL > CREATE TRIGGER b_mv_ut AFTER UPDATE ON c


FOR EACH ROW EXECUTE PROCEDURE b_mv_c_ut();

3.2 trigger b_mv_dt จะทำางานหลังจากมีการ delete data ใน table c โดยเรียกใช้ function b_mv_c_dt (ซ่ึงจะ
เรียกใช้ function b_mv_refresh_row อีกที)
SQL >CREATE FUNCTION b_mv_c_dt() RETURNS TRIGGER
SECURITY DEFINER LANGUAGE 'plpgsql' AS '
BEGIN
PERFORM b_mv_refresh_row(OLD.b_id);
Copyright © 2009 by Peekanung                                                                                                     31

RETURN NULL;
END';

SQL > CREATE TRIGGER b_mv_dt AFTER DELETE ON c


FOR EACH ROW EXECUTE PROCEDURE b_mv_c_dt();

3.3 trigger b_mv_it จะทำางานหลังจากมีการ insert data ใน table c โดยเรียกใช้ function b_mv_c_it (ซ่ ึงจะ
เรียกใช้ function b_mv_refresh_row อีกที)

SQL > CREATE FUNCTION b_mv_c_it() RETURNS TRIGGER


SECURITY DEFINER LANGUAGE 'plpgsql' AS '
BEGIN
PERFORM b_mv_refresh_row(NEW.b_id);
RETURN NULL;
END';
SQL > CREATE TRIGGER b_mv_it AFTER INSERT ON c
FOR EACH ROW EXECUTE PROCEDURE b_mv_c_it();

ทดลอง Insert ข้อมูลเข้า table a, b และ c ตามลำาดับ


SQL > INSERT INTO a VALUES (1,11);
SQL > INSERT INTO a VALUES (2,22);
SQL > INSERT INTO b VALUES (1,1,111,'2009-06-01');
SQL > INSERT INTO b VALUES (2,2,222,'2009-06-01');
SQL > INSERT INTO c VALUES (1,1,1111);
SQL > INSERT INTO c VALUES (2,2,2222);
SQL > INSERT INTO c VALUES(2,2,3333);

ทดลอง Select ข้อมูลจาก table และ view


SQL > SELECT * FROM a;
a_id | v
------+----
1 | 11
2 | 22
(2 rows)

SQL > SELECT * FROM b;


b_id | a_id | v | expires
------+------+-----+---------------------
1 | 1 | 111 | 2009-04-25 00:00:00
2 | 2 | 222 | 2009-04-25 00:00:00
(2 rows)

SQL > SELECT * FROM c;


c_id | b_id | v
------+------+------
1 | 1 | 1111
2 | 2 | 2222
3 | 2 | 3333
(3 rows)

SQL > SELECT * FROM b_mv;


b_id | a_v | b_v | sum_c_v
------+-----+-----+---------
1 | 11 | 111 | 1111
2 | 22 | 222 | 5555
(2 rows)
Copyright © 2009 by Peekanung                                                                                                     32

3.9.3 Lazy
Lazy materialized view จะ update เม่ ือ transaction commit แล้ว ซ่ ึงจะเหมาะกับกรณี ท่ีข้อมูลในบาง row มีการ
เปล่ียนแปลงบอย

3.9.4 Very lazy


Very lazy materialized view จะ update เม่ ือมีการสัง่ refresh data แตการ update ข้อมูลจะทำาได้เร็วกวา และใช้
ทรัพยากรน้ อยกวา

(1) สร้าง table matview_changes เพ่ ือเก็บข้อมูลการเปล่ียนแปลง materialized view ซ่ ึงประกอบด้วยข้อมูล


OID และ primary key ของ materialized view
SQL > CREATE TABLE matview_changes (
mv_oid OID PRIMARY KEY,
pkey INTEGER NOT NULL );

(2) สร้าง function matview_queue_refresh_row เพ่ ือ insert oid และ primary key เข้า table
matview_changes
SQL > CREATE FUNCTION matview_queue_refresh_row(NAME, INTEGER) RETURNS VOID
SECURITY DEFINER LANGUAGE 'plpgsql' AS '
DECLARE
mv OID;
test INTEGER;
BEGIN
SELECT INTO mv oid FROM matviews WHERE mv_name = $1;

SELECT INTO test pkey FROM matview_changes


WHERE matview_changes.mv_oid = mv
AND matview_changes.pkey = $2;

IF NOT FOUND THEN


INSERT INTO matview_changes (mv_oid, pkey) VALUES (mv, $2);
END IF;

RETURN ;
END ';

(3) สร้าง function b_mv_refresh


SQL > CREATE OR REPLACE FUNCTION b_mv_refresh() RETURNS VOID
SECURITY DEFINER LANGUAGE 'plpgsql' AS '
DECLARE
mv OID;
BEGIN
SELECT INTO mv oid FROM matviews WHERE mv_name = ''b_mv'';

PERFORM b_mv_refresh_row(b_id)
FROM b, matviews
WHERE matviews.oid = mv
AND b.expires >= matviews.last_refresh
AND b.expires < now();

PERFORM b_mv_refresh_row(pkey)
FROM matview_changes
WHERE mv_oid = mv;

UPDATE matviews
SET last_refresh = now()
WHERE mv_name = ''b_mv'';

END ';
Copyright © 2009 by Peekanung                                                                                                     33

สร้าง trigger ให้ table a, b และ c


1. trigger ของ table a มีดงั นี้
1.1 trigger b_mv_ut จะทำางานหลังจากมีการ update data ใน table a โดยเรียกใช้ function b_mv_a_ut
(ซ่ึงจะเรียกใช้ function b_mv_refresh_row อีกที)
SQL > CREATE OR REPLACE FUNCTION b_mv_a_ut() RETURNS TRIGGER
SECURITY DEFINER LANGUAGE 'plpgsql' AS '
BEGIN
IF OLD.a_id = NEW.a_id THEN
PERFORM matview_queue_refresh_row(''b_mv'', b.b_id)
FROM b WHERE b.a_id = NEW.a_id;
ELSE
PERFORM matview_queue_refresh_row(''b_mv'', b.b_id)
FROM b WHERE b.a_id = OLD.a_id;
PERFORM matview_queue_refresh_row(''b_mv'', b.b_id)
FROM b WHERE b.a_id = NEW.a_id;
END IF;
RETURN NULL;
END ';
SQL > CREATE TRIGGER b_mv_ut AFTER UPDATE ON a
FOR EACH ROW EXECUTE PROCEDURE b_mv_a_ut();

1.2 trigger b_mv_dt จะทำางานหลังจากมีการ delete data ใน table a โดยเรียกใช้ function b_mv_a_dt (ซ่ึงจะ
เรียกใช้ function b_mv_refresh_row อีกที)
SQL > CREATE OR REPLACE FUNCTION b_mv_a_dt() RETURNS TRIGGER
SECURITY DEFINER LANGUAGE 'plpgsql' AS '
BEGIN
PERFORM matview_queue_refresh_row(''b_mv'', b.b_id)
FROM b WHERE b.a_id = OLD.a_id;
RETURN NULL;
END ';
SQL > CREATE TRIGGER b_mv_dt AFTER DELETE ON a
FOR EACH ROW EXECUTE PROCEDURE b_mv_a_dt();

1.3 trigger b_mv_it จะทำางานหลังจากมีการ insert data ใน table a โดยเรียกใช้ function b_mv_a_it (ซ่ึงจะ
เรียกใช้ function b_mv_refresh_row อีกที)
SQL > CREATE OR REPLACE FUNCTION b_mv_a_it() RETURNS TRIGGER
SECURITY DEFINER LANGUAGE 'plpgsql' AS '
BEGIN
PERFORM matview_queue_refresh_row(''b_mv'', b.b_id)
FROM b WHERE b.a_id = NEW.a_id;
RETURN NULL;
END ';
SQL > CREATE TRIGGER b_mv_it AFTER INSERT ON a
FOR EACH ROW EXECUTE PROCEDURE b_mv_a_it();
2. trigger ของ table b มีดังนี้
2.1 trigger b_mv_ut จะทำางานหลังจากมีการ update data ใน table b โดยเรียกใช้ function b_mv_b_ut (ซ่ึงจะ
เรียกใช้ function b_mv_refresh_row อีกที)
SQL > CREATE OR REPLACE FUNCTION b_mv_b_ut() RETURNS TRIGGER
SECURITY DEFINER LANGUAGE 'plpgsql' AS '
BEGIN
IF OLD.b_id = NEW.b_id THEN
PERFORM matview_queue_refresh_row(''b_mv'', NEW.b_id);
ELSE
PERFORM matview_queue_refresh_row(''b_mv'', OLD.b_id);
PERFORM matview_queue_refresh_row(''b_mv'', NEW.b_id);
END IF;
RETURN NULL;
END ';
Copyright © 2009 by Peekanung                                                                                                     34

SQL > CREATE TRIGGER b_mv_ut AFTER UPDATE ON b


FOR EACH ROW EXECUTE PROCEDURE b_mv_b_ut();

2.2 trigger b_mv_dt จะทำางานหลังจากมีการ delete data ใน table b โดยเรียกใช้ function b_mv_b_dt (ซ่ึงจะ
เรียกใช้ function b_mv_refresh_row อีกที)

SQL > CREATE OR REPLACE FUNCTION b_mv_b_dt() RETURNS TRIGGER


SECURITY DEFINER LANGUAGE 'plpgsql' AS '
BEGIN
PERFORM matview_queue_refresh_row(''b_mv'', OLD.b_id);
RETURN NULL;
END ';
SQL > CREATE TRIGGER b_mv_dt AFTER DELETE ON b
FOR EACH ROW EXECUTE PROCEDURE b_mv_b_dt();

2.3 trigger b_mv_it จะทำางานหลังจากมีการ insert data ใน table b โดยเรียกใช้ function b_mv_b_it (ซ่ึงจะ
เรียกใช้ function b_mv_refresh_row อีกที)

SQL > CREATE OR REPLACE FUNCTION b_mv_b_it() RETURNS TRIGGER


SECURITY DEFINER LANGUAGE 'plpgsql' AS '
BEGIN
PERFORM matview_queue_refresh_row(''b_mv'', NEW.b_id);
RETURN NULL;
END ';
SQL > CREATE TRIGGER b_mv_it AFTER INSERT ON b
FOR EACH ROW EXECUTE PROCEDURE b_mv_b_it();

3. trigger ของ table c


3.1 trigger b_mv_ut จะทำางานหลังจากมีการ update data ใน table c โดยเรียกใช้ function b_mv_c_ut (ซ่ึงจะ
เรียกใช้ function b_mv_refresh_row อีกที)
SQL > CREATE OR REPLACE FUNCTION b_mv_c_ut() RETURNS TRIGGER
SECURITY DEFINER LANGUAGE 'plpgsql' AS '
BEGIN
IF OLD.b_id = NEW.b_id THEN
PERFORM matview_queue_refresh_row(''b_mv'', NEW.b_id);
ELSE
PERFORM matview_queue_refresh_row(''b_mv'', OLD.b_id);
PERFORM matview_queue_refresh_row(''b_mv'', NEW.b_id);
END IF;
RETURN NULL;
END ';

SQL > CREATE TRIGGER b_mv_ut AFTER UPDATE ON c


FOR EACH ROW EXECUTE PROCEDURE b_mv_c_ut();

3.2 trigger b_mv_dt จะทำางานหลังจากมีการ delete data ใน table c โดยเรียกใช้ function b_mv_c_dt (ซ่ึงจะ
เรียกใช้ function b_mv_refresh_row อีกที)
SQL > CREATE OR REPLACE FUNCTION b_mv_c_dt() RETURNS TRIGGER
SECURITY DEFINER LANGUAGE 'plpgsql' AS '
BEGIN
PERFORM matview_queue_refresh_row(''b_mv'', OLD.b_id);
RETURN NULL;
END ';
SQL > CREATE TRIGGER b_mv_dt AFTER DELETE ON c
FOR EACH ROW EXECUTE PROCEDURE b_mv_c_dt();
Copyright © 2009 by Peekanung                                                                                                     35

3.3 trigger b_mv_it จะทำางานหลังจากมีการ insert data ใน table c โดยเรียกใช้ function b_mv_c_it (ซ่ ึงจะ
เรียกใช้ function b_mv_refresh_row อีกที)
SQL > CREATE OR REPLACE FUNCTION b_mv_c_it() RETURNS TRIGGER
SECURITY DEFINER LANGUAGE 'plpgsql' AS '
BEGIN
PERFORM matview_queue_refresh_row(''b_mv'', NEW.b_id);
RETURN NULL;
END ';
SQL > CREATE TRIGGER b_mv_it AFTER INSERT ON c
FOR EACH ROW EXECUTE PROCEDURE b_mv_c_it();

3.10 การสำารองข้อม้ล (ฺBackup / Restore)


การสำารองข้อมูล เปนส่ิงท่ค
ี วรทำาอยางสมำาเสมอในการใช้งานฐานข้อมูล ย่งิ ทำาการสำารองข้อมูลบอยเทาไร ก็จะสามา
รถปองกันความเสียหายท่ีอาจจะเกิดขึ้นกับฐานข้อมูล และสามารถนำ าข้อมูลท่ีมีความทันสมัยกลับคืนมาได้มากเทานั ้น โดยมีวิธีการ
ในการสำารองข้อมูลได้ 3 วิธี คือ

• SQL dump
• File system level backup
• On-line backup

ซ่ึงในท่ีนี้จะกลาวถึงเพียงวิธีเดียวคือ SQL dump

3.10.1 Backup
คำาสัง่ pg_dump เปนคำาสัง่ท่ีนำาเอาฐานข้อมูลท่ีระบุออกมาเปน Text File หรือรูปแบบอ่ ืนๆท่ีระบุ
คำาสัง่ pg_dumpall เป็ นคำาสัง่ท่ีสำารองทุกฐานข้อมูล ออกมาเป็ น Text File หรือรูปแบบอ่ ืนๆ ท่ีระบุ

$ PG_DUMP [options] dbname > outfile

$ PG_DUMPALL [options] > outfile

Options:
-a --data-only สำาเนาเฉพาะข้อมูล ไมเอาโครงสร้าง
-b --blob สำาเนา large objects ด้วย (จะเป็ นคา default เม่ ือระบุ--schema, --table, or –schema-only)
-c --clean กำาหนดให้ output สร้างคำาสัง่ drop database กอน create
(ใช้ได้เฉพาะกรณี ท่ี output เป็ น plain-text format เทานั ้น)
-C --create กำาหนดให้ output สร้างคำาสัง่สำาหรับสร้าง database ไว้ด้วย
(ใช้ได้เฉพาะกรณี ท่ี output เป็ น plain-text format เทานั ้น)
-d --insert ให้นำาข้อมูลเข้าโดยใช้คำาสัง่ INSERT แทนคำาสัง่ COPY ของ PostgreSQL ซ่ ึงจะทำาให้นำาไปใช้กับ
ระบบฐานข้อมูลอ่ ืน เชน oracle ได้
-D --column-inserts เหมือน -d แตมีการระบุ Column ด้วย
-E --encoding ระบุ character set encoding (default คาจะเป็ นคาเดียวกับ database ท่ี dump)
-f --file=file เก็บข้อมูลลงแฟมท่ีกำาหนด
-F, format {c|t|p} เก็บข้อมูลลงแฟมตามรูปแบบท่ีกำาหนด โดย
c (custom) : กำาหนด output เอง (เป็ น default)เชน output.dmp , output.dump ,...
t ( tar) : กำาหนดเป็ น tar archive
p (plain) : เป็ นคา default, output เป็ น plain-text SQL scripts
-h --host database server host name
-n --schema สำาเนาเฉพาะ schema ท่ีกำาหนด
-N --exclude schema ไมสำาเนา schema ท่ีกำาหนด
-O --no owner ไมตัง้คาเจ้าของ ให้ใช้เหมือนเจ้าของเดิม
-o --oids สำาเนา oids ออกมาด้วย
-p --port ระบุหมายเลข port ของ database server
-s --schema-only สำาเนาเฉพาะโครงสร้าง schema ไมสำาเนาข้อมูล
-S --superuser ระบุ superuser เพ่ ือใช้ disable trigger (กรณี ท่ีต้องมีการ disable trigger)
-t --table สำาเนาเฉพาะ table ท่ีกำาหนด
-T --exclude table ไมสำาเนา table ท่ีกำาหนด
Copyright © 2009 by Peekanung                                                                                                     36

-U --username กำาหนดช่ ือ user ท่ีใช้ในการติดตอ


-v --verbose กำาหนดให้ dump file แสดงรายละเอียดตางๆของการ dump ด้วยเชน message , start/stop time
-W --password กำาหนดให้มีการใส password กอน connect เข้า database
-x --no privileges ไมสำาเนาคำาสัง่เก่ียวกับสิทธิการใช้งาน (grant/revoke)
-z --compress 0..9 ระบุการบีบอัด โดย 0 คือไมมีการบีบอัด (default คือ ไมบีบอัด) และ 9 คือระดับสูงสุด

ตัวอยาง
$ pg_dump pis -f /tmp/pis.dump
// dump database 'pis' ออกมาโดยเก็บไว้ท่ี /tmp ช่ ือไฟล์ pis.dump
$ pg_dump –c –Fc –Z9 pis > pis.dump
// dump database 'pis' ออกมาโดยใช้ช่ือไฟล์ pis.dump โดยเพ่ิมคำาสัง่ drop database ก่อน
สัง่ create , กำาหนด output file แบบกำาหนดเอง และให้มีการบีบอัดแบบส่งสุด
$ pg_dump –U postgres –c –Fc –Z9 pis > pis.dump
// dump database 'pis' ออกมา โดยใช้ช่ือไฟล์ pis.dump กำาหนด username ท่ีใช้ติดตอคือ postgres
กำาหนด output file แบบกำาหนดเอง และให้มีการบีบอัดแบบส่งสุด

3.10.2 Restore
การนำ าข้อมูลสำารองท่ีได้จาก pg_dump ติดตัง้กลับเข้าฐานข้อมูลนั ้น ต้องพิจารณาใช้คำาสัง่ ท่ีใช้ในการนำ าเข้าจากชนิ ดของ
แฟมข้อมูลสำารอง คือ
• ถ้าแฟมข้อมูลสำารองอยูในรูปบีบอัด(สร้างจาก option –Fc หรือ –Ft) ให้ใช้คำาสัง่
$ PG_RESTORE [options..] [filename]

• นอกจากนั ้นใช้คำาสัง่ psql


$ psql dbname < infile

Options:
-a --data-only restore เฉพาะข้อมูล ไมเอาโครงสร้าง
-c --clean กำาหนดให้ drop database กอนทำาการ restore
- C --create create database กอน install
-d --database-name connect เข้า database ท่ีกำาหนดไว้แล้ว restore ลงใน database นั ้น
-e --exit-on-error ออกจากการทำางานทันทีเม่ ือเกิด error
(default คือ ทำางานตอไปแล้่วแสดง error ออกมา)
-f --file ระบุ output จากการ restore ออกมาเป็ นไฟล์
-F, format {c|t|} restore ข้อมูล ตามรูปแบบท่ีกำาหนด
ปกติถ้าไมกำาหนดคำาสัง่ pg_restore จะตรวจสอบให้อัตโนมัติ
-i --ignore-version ไมตรวจสอบ version ของ database
-I --index restore เฉพาะ index เทานั ้น
-l --list แสดงรายละเอียดของไฟล์
-n --namespace restore เฉพาะ object ท่ีอยูใน schema ท่ีระบุไว้
-O --no-owner ไมต้องตัง้คาเจ้าของให้เหมือนเจ้าของเดิม
-h --host ระบุ database server host name
-p --port ระบุหมายเลข port ของ database server
-s --schema-only restore เฉพาะโครงสร้าง schema ไมสำาเนาข้อมูล
-S --superuser ระบุ superuser เพ่ ือใช้ disable trigger
-t --table restore เฉพาะ table ท่ีกำาหนด
-U --username กำาหนดช่ ือ user ท่ีใช้ในการติดตอ
-W --password กำาหนดให้มีการใส password กอน connect เข้า database
-x --no privileges ไม restore คำาสัง่เก่ียวกับสิทธิการใช้งาน (grant/revoke)

ตัวอยาง
$ pg_restore -C -d postgres db.dump
// restore database โดยสัง่ให้มีการ create database ก่อน restore และระบุช่ือ database เป็ น postgres

ตัวอยางการ backup และ restore


$ pg_dump test > /tmp/test.dump
// backup database ข่ ือ 'test' ไว้ท่ี /tmp/test.dump
Copyright © 2009 by Peekanung                                                                                                     37

$ createdb newtest
// สร้าง database รอไว้ ช่ ือ newtest
$ psql newtest < /tmp/test.dump
// restore เข้า database 'newtest' จากท่ี backup ไว้

3.11 Database Maintenance

การบำารุงรักษา Database ด้วย Routine Vacuuming มีวัตถุประสงค์ดังนี้


1. เพ่ ือให้ database ทำางานได้ตามปกติ
2. เพ่มิ ความเร็วในการทำางานของ database
3. กู้คนื พ้ืนท่ี disk ท่ีถูกใช้ในการ Update/Delete

เม่ ือมีการ Update/Delete ข้อมูล postgreSQL จะยังคงเก็บข้อมูล version เกาๆเอาไว้ (เป็ นการทำางานของ
Multiversion Concurrency Control : MVCC) ข้อมูลเกาท่ีถูกเก็บไว้นี้จะใช้พ้ืนท่ี disk เพ่ิ่มขึ้นเร่ ือยๆ ซ่ ึงจำาเป็ นต้องมีการกู้
พ้ืนท่ี disk ออกมาเพ่ ือใช้สำาหรับข้อมูลใหม และเพ่ ือป้ องกันการโตขึ้นของพ้ืนท่ี disk สามารถทำาได้โดยการรัน VACUUM
การรัน VACUUM เหมาะสำาหรับ table ท่ีมีการ update/delete ข้อมูลจำานวนมาก หรือบอยครัง้ ซ่ ึงไมมีความจำาเป็ น
นั กสำาหรับ table เล็กๆ หรือ table ท่ีไมคอยมีการเปล่ียนแปลงข้อมูล
VACUUM แบงออกเป็ น 2 ประเภท คือ LAZY VACUUM และ VACUUM FULL
1. LAZY VACUUM
lazy vacuum หรือ vacuum จะทำางานโดยการกำาหนด expire data เกาใน table และ index เพ่ ือใช้งานใหมใน
อนาคต พ้ืนท่ี disk จะไมถูกคืนให้แก OS ข้อดีของ vacuum คือสามารถรันไปพร้อมๆกับการทำางานอ่ ืนๆของ
database ได้ vacuum จึงเหมาะสำาหรับการสัง่ run แบบ routine เพราะไมมีผลกระทบตอการทำางานของ databa
se และใข้ทรัพยากรในการ run น้ อย

2. VACUUM FULL
เป็ นการเรียกคืนพ้ืนท่ีจากการ expire row version ซ่ ึงพ้ืนท่ีจากการสัง่ vacuum full นี้จะถูกคืนให้กับ OS ด้วย แตข้อ
เสียคือ table ท่ีกำาลังทำา VACUUM FULL จะถูก lock จนกวาจะทำางานเสร็จ vacuum full เหมาะสำาหรับกรณี ท่ีต้องการคืน
พ้ืนท่ีให้แก OS หรือกรณี ท่ีมีการ update/delete ข้อมูลจำานวนมาก ซ่ ึงการทำา VACUUM FULL จะใช้เวลาทำานานกวา
VACUUM

คำาสั่ง
SQL > VACUUM [FULL] [FREEZE] [VERBOSE] [ tablename]
SQL > VACUUM [FULL] [FREEZE] [VERBOSE] ANALYZE [ tablename] [(column [,...] )]]

กรณี ท่ีไมระบุช่ือ table จะหมายถึงสัง่ VACUUM ทุก ๆ table ใน database แตสำาหรับคำาสัง่ VACUUM
ANALYZE จะต้องระบุช่ือ table ด้วยเสมอ

parameters

FREEZE เทียบเทากับการ set parameters 'vacuum_freeze_min_age' = 0 เป็ นการสัง่ cutoff age


ของ transaction
VERBOSE แสดงรายละเอียดการทำางานของ VACUUM ในแตละ table
ANALYZE update คาสถิติเพ่ ือใช้ในการตัดสินใจเก่ียวกับประสิทธิภาพของ query

You might also like