arsenal
arsenal

Reputation: 24194

Oracle Sql If exists then do this else do that

    String s1 = "create table " +tableName+
    "(id number NOT NULL PRIMARY KEY, " +
    "url varchar(1000) NOT NULL, " +
    "urlHash varchar(1000) NOT NULL, " +
    "contentHash varchar(1000), " +
    "modDate date, " +
    "contentLocation varchar(1000), " +
    "status integer, " +
    "lastCrawlDate date) ";

String s3 = "create sequence " +sequenceName+ " start with 1 increment by 1 nomaxvalue";

    stmt=conn.createStatement();
    stmt.executeUpdate(s1);
    stmt.executeUpdate(s3);

ps = conn.prepareStatement (
          "INSERT INTO testing (id, url, urlHash, contentHash, modDate, contentLocation, status, lastCrawlDate) VALUES(test_seq.nextval,?,?,?,?,?,?,?)");


          ps.setString (1, url);
          ps.setString (2, urlHash);
          ps.setString (3, contentHash);
          ps.setString (4, modDate);
          ps.setString (5, contentLocation);
          ps.setLong (6, status);
          ps.setString (7, lastCrawlDate); 

What I am doing in this is I am creating a table and a sequence for auto increment. And then I am inserting into oracle database using prepared statement. And this table contauns huge amount of data around 20,000 entries approx.

First Problem:- So now what I have to do is If I need to add any url and other corresponding data into this table I have to search within the table to see if this url exists in this table or not. If it doesn't exist then add this url to the table and other corresponding data. So how can I achieve this if exists then do this else do that functionality in oracle sql.

For the first problem I can fire the select query on the url or urlHash to see if url exists or not if it doesn't then add it

rs = stmt.executeQuery("SELECT urlHash FROM " +tableName+ " where urlHash ='urlHash' "); 
          while (rs.next()) {
              String last = rs.getString("urlHash");
              }

And then compare the values and if it doesn't compare add it. I don't think this is the way I should go for. And what will be the fastest way to do this first problem..

Second Problem- And secondly if this url exists and it got modified(we can see this in last modified header and I am storing this value in modDate) then update the url with other corresponding data.

So it's a kind of this problem

if URL does not Exists {
Add to the oracle table and other data
} else if(url got modified by checking the modDate) {
update the url into oracle database and other data
}

Upate as per pilcrow solutions:- I am trying to convert string date type to Date type here but I am getting error as Missing IN or OUT parameter at index 8. Why is it so?

    ps =  conn.prepareStatement(
                        "MERGE INTO testing " +
                        "USING (  SELECT ? AS url, " +                 // We will maybe add this record
                        "                ? AS urlHash, " +
                        "                ? AS contentHash, "+
                        "         TO_DATE(?, 'YYYY-MM-DD'T'HH24:MI:SS'Z'') AS modDate, "+
                        "         ? AS contentLocation, "+
                        "         ? AS status, "+
                        "      TO_DATE(?, 'YYYY-MM-DD'T'HH24:MI:SS'Z'') AS lastCrawlDate "+
                        "           FROM dual ) maybe "+
                        "   ON (maybe.urlHash = testing.urlHash) "+
                        "         WHEN MATCHED THEN "+
                           // We only need update the fields that might have changed
                        "       UPDATE SET testing.contentHash     = maybe.contentHash, "+
                        "                  testing.modDate         = maybe.modDate, "+
                        "                  testing.contentLocation = maybe.contentLocation, "+
                        "                  testing.status          = maybe.status, "+
                        "                  testing.lastCrawlDate   = maybe.lastCrawlDate "+
                           // But only if the new record is more recent
                        "        WHERE TO_CHAR(testing.modDate, 'YYYY-MM-DD'T'HH24:MI:SS'Z'') < TO_CHAR(maybe.modDate, ''YYYY-MM-DD'T'HH24:MI:SS'Z''') "+
                        "         WHEN NOT MATCHED THEN "+
                           // Insert new URL record
                        "   INSERT VALUES (test_seq.nextval, maybe.url, maybe.urlHash, maybe.contentHash, maybe.modDate, maybe.contentLocation, maybe.status, maybe.lastCrawlDate)");


ps.setString (1, "http://www.computergeeks.com");
          ps.setString (2, "ahsasoiowiewie");
          ps.setString (3, "sgasjwhwueybdbfndf");
          ps.setString (4, "2011-07-28T23:54:14Z");
          ps.setString (5, "c://");
          ps.setLong (6, 0);
          ps.setString (7, "2011-07-28T23:54:14Z"); 
          ps.executeUpdate();
          ps.close();

Upvotes: 2

Views: 1298

Answers (1)

pilcrow
pilcrow

Reputation: 58741

Disclaimer: I cannot test this right now. You want something like an "UPSERT" with logic to update only when modDate is newer.

In Oracle, that should be possible with MERGE:

MERGE INTO testing
USING (  SELECT ? AS url,                 -- We will maybe add this record
                ? AS urlHash,
                ...
                ? AS lastCrawlDate
           FROM dual ) maybe
   ON (maybe.urlHash = testing.urlHash)
WHEN MATCHED THEN
   -- We only need update the fields that might have changed
       UPDATE SET testing.contentHash     = maybe.contentHash,
                  testing.modDate         = maybe.modDate,
                  testing.contentLocation = maybe.contentLocation,
                  testing.status          = maybe.status,
                  testing.lastCrawlDate   = maybe.lastCrawlDate
   -- But only if the new record is more recent
        WHERE testing.modDate < maybe.modDate
WHEN NOT MATCHED THEN
   -- Insert new URL record
   INSERT VALUES (test_seq.nextval, maybe.url, maybe.urlHash, ...);

I'll note in passing that you seem to be missing some constraints on your testing table (e.g., url and urlHash seem like they should be UNIQUE at least)

(Update: corrections per ruakh's comment)

Upvotes: 8

Related Questions