====== PostgreSQL Notes ======
Some notes as I learn PostgreSQL bit by bit.
===== Copy Table =====
1) Buat copy table asal ke temporary table
CREATE TABLE temp AS SELECT col1, col2 FROM table_lama
2) Drop table asal
DROP TABLE table_lama
3) Create structure table baru
CREATE TABLE table_baru ( col1 type(xx), col2 type(xx) );
4) insert data dari table temporary ke table baru
INSERT INTO table_baru SELECT FROM temp
http://forums.ittutor.net/index.php?showtopic=24587
===== Function =====
CREATE FUNCTION data_lpm(varchar) RETURNS SETOF lpm_pelajar AS '
SELECT * FROM lpm_pelajar WHERE no_kp_baru = $1;
' LANGUAGE SQL;
===== Trigger =====
First, create the function:-
create or replace function test() returns trigger as $test$
BEGIN
NEW.total_price := calc_itemprice(NEW.item_id, NEW.qty);
return NEW;
END;
$test$ language plpgsql;
create the trigger:-
create trigger calc_itemprice before insert or update
on order_items for each row
execute procedure test();
and this is the function that was called inside the trigger function:-
create or replace function calc_itemprice(integer, integer) returns float as
'select price * $2 from items where id = $1'
language sql immutable;
===== psql command =====
* \x turn on extended display. usefull if the result is too long
===== Alter Column Type =====
in postgres you can't so easily change column type.. the documentation of 'alter table' there's no word about changing column type, as if they didn't want to talk about it :)
for a long time i thought it was only possible by recreating the table, but i found something like this in the faq
To change the data type of a column, do this:
BEGIN;
ALTER TABLE tab ADD COLUMN new_col new_data_type;
UPDATE tab SET new_col = CAST(old_col AS new_data_type);
ALTER TABLE tab DROP COLUMN old_col;
COMMIT;
You might then want to do VACUUM FULL tab to reclaim the disk space used by the expired rows.
http://www.dbforums.com/archive/index.php/t-1051977.html
Just discover that we can't change type varchar to integer this way. you need to convert the varchar type to text first.
update table set colname = old_col::text::integer
===== Format Date =====
select to_char(date_column, 'DD-Mon-YYYY') from table_name;
===== Alternative to Not In =====
select * from user
where userid not in (
select userid from authorized_user
)
this query would become *slow* if authorized_user is a very
large table since seq scan is used for the inner query. the
alternate way is:
select * from user
where userid not exists (
select 1 from authorized_user
where userid = user.userid
)
in this query, rather than selecting the whole row of inner
query looking for one that do not exist, we just check for
true/false whether it exist or not. given table authorized_user
has an index on userid, this query would be faster since index scan
is used.
FIXME: The second form cannot be used if query (outer ??) has a
order by / limit clause.
Note: some guys on irc told me that this have been fixed in postgresql 8.0,
means Not In would be much faster.
===== Listing constraints =====
select n.nspname || '.' || c.relname as table_name,
con.conname as constraint_name,
pg_get_constraintdef( con.oid, false) as constraint_def
from pg_constraint con
join pg_namespace n on (n.oid = con.connamespace)
join pg_class c on (c.oid = con.conrelid)
where con.conrelid != 0 and
con.contype = 'f';
ref: http://www.varlena.com/varlena/GeneralBits/116.php