Yet another scripting article - LINK

Monday, November 03, 2008

Old article, but worth the read, gives a brief intro to using local os scripts from db2 udfs.

http://www.ibm.com/developerworks/db2/library/techarticle/0211yip/0211yip4.html

Wednesday, October 08, 2008

One of the junior DBAs asked me this question. I thought it was a good enough reason to blog.

I am not touching what primary key helps us achieve, but what's difference in executing just

create unique index x.y on table xx.yy allow reverse scans;

than

create unique index x.y on table xx.yy allow reverse scans;
alter table xx.yy add constraint -- and give the columns in the above defined unique index


unique index can have one row with null value in either of columns, while primary key disallows it :)

Question on syscat.keycoluse.colseq

Monday, June 30, 2008

Just to link with a usenet group's thread reg. the colseq column in keycoluse catalog view. I always thought this was supposed to list the foreign key columns and it's relation with the parent columns. But it seems db2 has a bug w.r.t this view.

Here is a list of statements I ran.
DROP TABLE ARUN.TEST2;
DROP TABLE ARUN.TEST1;
create table arun.test1 (a char(1) not null, b char(1) not null);
create unique index arun.test1_idx2 on arun.test1(b,a) CLUSTER;
create unique index arun.test1_idx1 on arun.test1(a,b) ;

alter table arun.test1 add constraint pk_test1 primary key(a,b);

create table arun.test2(a2 char(1),b2 char(1));
create unique index arun.test2_idx1 on arun.test2(a2,b2) cluster;

alter table arun.test2 ADD constraint fk_test2 foreign key(b2,a2) references arun.test1;



--The below statement gives the relation between foreign key columns and their corresponding parents

SELECT
SUBSTR(R.CONSTNAME, 1, 18) AS KEYNAME,
SUBSTR(KF.COLNAME, 1, 18) AS COLNAME,
SUBSTR(KP.COLNAME, 1, 18) AS REFCOLNAME
FROM
SYSCAT.REFERENCES R
INNER JOIN SYSCAT.KEYCOLUSE KF
ON R.TABSCHEMA = KF.TABSCHEMA
AND R.TABNAME = KF.TABNAME
AND R.CONSTNAME = KF.CONSTNAME
INNER JOIN SYSCAT.KEYCOLUSE KP
ON R.REFTABSCHEMA = KP.TABSCHEMA
AND R.REFTABNAME = KP.TABNAME
AND R.REFKEYNAME = KP.CONSTNAME
WHERE
R.TABSCHEMA = 'ARUN' AND
R.TABNAME = 'TEST2'
AND KF.COLSEQ = KP.COLSEQ
ORDER BY
R.TABSCHEMA,
R.TABNAME,
R.CONSTNAME,
KF.COLSEQ
WITH UR;

I hoped for this output, which is what I wanted..

Keyname Colname Refcolname

'FK_TEST2 ' 'A2 ' 'A '
'FK_TEST2 ' 'B2 ' 'B '

Instead I was blessed with

Keyname Colname Refcolname

'FK_TEST2 ' 'B2 ' 'A '
'FK_TEST2 ' 'A2 ' 'B '

Link to the usenet group's thread..

Deleting limited number of rows and still using Joins (mimicing, actually)

Wednesday, June 04, 2008

Everybody loves the new flavor DB2 introduced to the delete command ,

delete from (select * from table [where ] [fetch first n rows only])

because they can limit the number of rows to be deleted in one shot. It has been of immense help since I frequently delete millions of rows and it alleviates the problem of lock memory and log file usage. I just put this statement in a loop and run that for a specific number of times (or till it gets 0 rows returned, with a little complex code). Now the only setback we have is, we cannot use a select statement that joins tables, and would be staring at SQL0150N error. Now I just set out to solve this and using the mighty 'exists' clause, which has saved me during more than one bad situation, was actually able to mimic join and still limit delete to a set of rows.

The original query was
select t1.* from table1 t1 inner join table2 t2 on
T1.COL1 = T2.COL1 AND T1.COL2 = T2.COL2 AND T1.COL3 = T2.COL3;

The following will not work because joins are not allowed in the 'delete from (' clause
delete from (select t1.* from table1 t1 inner join table2 t2 on
T1.COL1 = T2.COL1 AND T1.COL2 = T2.COL2 AND T1.COL3 = T2.COL3 fetch first n rows only)
This would throw SQL0150N error.

So I changed the above to
delete from
(
SELECT * FROM table1 T1 where exists
(select 1 from TABLE2 T2 where T1.COL1 = T2.COL1 AND T1.COL2 = T2.COL2 AND T1.COL3 = T2.COL3)
);
Works wonderfully.

DB2_EXTENDED_OPTIMIZATION

Tuesday, June 03, 2008

I loved this new option 'ENHANCED_MULTIPLE_DISTINCT' that they gave for the registry variable in ver 9 fp 2. I normally face with sqls having multiple distinct clauses, select count(distinct(x)) , sum (distinct(x)) from table1, and what happens here is that the optimizer tries to do the groupby twice, once for each aggregation function and then unions them at the end.
Because of the new option we can prevent the above so that both functions are executed against the data whilst loading it only once.
This has good improvement potential in single processor systems and will not be useful all the time.

IBM can do magic!!

Monday, February 25, 2008

Have you ever come across situations wherein you need to drop a table that has been defined with 'restrict on drop' clause and you can't access the table at all, possibly because you inserted rows with 'not logged initially' state and it crashed???
Do the following..

For each node, run the following accordingly.
1) Take db offline. Make sure db is offline by checking with "db2 list
active databases"

2) db2dart <dbname> /mt /serv 1 /oi <table id> /tsi <tablespaceid> /PW
IEOAHERU
-----Alas - IBM services are the only guys who can give the password in the PW argument!!!!

3) Connect to the db, run the following statement

db2 ALTER TABLE <tablename> DROP RESTRICT ON DROP

4) Then drop the table immediately.


Interesting table

Monday, January 07, 2008

create table test (a integer not null generated always as identity (start with 1 increment by 1))

I cannot insert data since a is defined with "generated always", and there aint no other columns. This is a hole, just found this when I was taking prescription for everyday boredom.