Perl DBI help
Jun. 26th, 2009 11:56 am![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Argh, I've got an SQL query which works fine if I run it from Access, and which I think has no errors, but if I try run it from Perl I'm getting an error from the database. Can anyone tell me what obvious thing I'm doing wrong?
my $sth = $dbh->prepare("SELECT committed.engid, committed.crsid, committed.uid_num, committed.gid_num, committed.name, committed.college, committed.path FROM c_yj_yp_live_committed committed LEFT OUTER JOIN c_yj_yp_live_working working ON committed.engid = working.engid WHERE working.engid is null");
And this gives the following error:
DBD::Oracle::db prepare failed: ORA-00933: SQL command not properly ended (DBD ERROR: error possibly near <*> indicator at char 384 in 'SELECT committed.engid, committed.crsid, committed.uid_num, committed.gid_num, committed.name, committed.college, committed.path FROM c_yj_yp_live_committed committed <*>LEFT OUTER JOIN c_yj_yp_live_working working ON committed.engid = working.engid WHERE working.engid is null') [for Statement "SELECT committed.engid, committed.crsid, committed.uid_num, committed.gid_num, committed.name, committed.college, committed.path FROM c_yj_yp_live_committed committed LEFT OUTER JOIN c_yj_yp_live_working working ON committed.engid = working.engid WHERE working.engid is null"] at ./yj_correlate.pl line 33.
Any clues? (Apologies for some long lines, I do intended to split it up a bit more eventually, but at the moment I think it slightly aids readability)
Ah, it seems that in fact the oracle database does *not* support left outer joins, and that the reason it works in Access is because Access translates the query into a form that this version of oracle does support. Many thanks to Paul for popping in to explain (I could have just gone and asked him obviously, but he's been rather busy with exam marking recently). What a nuisance, since this is obviously a much nicer way to do the query than faffing about with a "where not in (subquery)" or similar. (We suspect it is supported in the new version of Oracle Paul's working on migrating to, but sadly I think my code is needed before then).
Double correction: it does support them, but with weird syntax. The following code works:
SELECT committed.engid, committed.crsid, committed.uid_num, committed.gid_num, committed.name, committed.college, committed.path FROM c_yj_yp_live_committed committed, c_yj_yp_live_working working WHERE committed.engid = working.engid (+) and working.engid is null
no subject
Date: 2009-06-26 11:11 am (UTC)no subject
Date: 2009-06-26 11:13 am (UTC)<*>
appears to be the suspiciously round number 384. Insanely small arbitrary length limit somewhere?no subject
Date: 2009-06-26 11:18 am (UTC)no subject
Date: 2009-06-26 11:37 am (UTC)I suppose I'm just as glad neither of my suggestions was right; either would have been more hideous than the truth :-)
no subject
Date: 2009-06-26 11:39 am (UTC)no subject
Date: 2009-06-26 12:17 pm (UTC)no subject
Date: 2009-06-26 11:26 am (UTC)eg this description (http://www.dba-oracle.com/tips_oracle_left_outer_join.htm)
no subject
Date: 2009-06-26 11:30 am (UTC)Of course the syntax is pretty deranged, but it is nice and short in comparison :)
no subject
Date: 2009-06-26 11:26 am (UTC)So you're doing a left outer join on the committed table and the working table, where the engids match, and selecting based on the the working engid being null, but you're only selecting committed table entries. This seems rather inefficient. If you're joining on matching IDs, can't you just do SELECT where committed.id IS NULL?
no subject
Date: 2009-06-26 11:35 am (UTC)The left outer join gives you a line for every line in the committed table, but where there's no matching line in the working table you get nulls in the half of the data that came from the working table. engid is in fact the key for each table.
no subject
Date: 2009-06-26 12:07 pm (UTC)How about
SELECT committed.engid,
committed.crsid,
committed.uid_num,
committed.gid_num,
committed.name,
committed.college,
committed.path
FROM c_yj_yp_live_committed committed
WHERE NOT EXISTS
( SELECT * FROM c_yj_yp_live_working working
WHERE working.engid = committed.engid )
Mind you that's not great either, and I haven't got anything set up to test it.
Scarily, I will probably have to do some database programming for the first time in five years next week.
no subject
Date: 2009-06-26 12:14 pm (UTC)no subject
Date: 2009-06-26 12:06 pm (UTC)no subject
Date: 2009-06-26 12:16 pm (UTC)MS Access SQL differs from Oracle SQL
Date: 2009-06-26 08:04 pm (UTC)