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.