Oracle MERGE and prepared statement

五迷三道 提交于 2021-02-19 07:48:05

问题


I have a backup utility, workig on restore section. This is my table:

CREATE TABLE "SBOOKS"."DEV_CORPUS" 
   (    "CORPUSID" NUMBER(9,0) NOT NULL ENABLE, 
    "CORPUS_NAME" VARCHAR2(768 BYTE) NOT NULL ENABLE, 
    "CORPUSLASTSYNC" DATE, 
     PRIMARY KEY ("CORPUSID")

In restore class I would like to look for a primary key in table, if it exists then update the row, if not then insert a row.
now the problem is I need to pass the parameters from the class (they do not exist in any table), how can I do this? what is your suggestion? using preparedstatment or what? and how? please give examples or links to sources.

more info: I am using oracle sql developer and java netbeans.

EDIT: I am trying this in command window:

  MERGE INTO dev_corpus a  
  USING (SELECT corpusid, corpus_name, corpusdesc, corpusimageids, rocf1, rocf2, rocf3, rocc1, rocc2, rocc3, corpusactive, corpusrunfrequency, corpuslastrun, corpuslastsync, rocsettingid, corpusaffinity, corpusterms, corpusdomain FROM dual WHERE corpusId = 1000156 AND corpus_name = 'sahar' AND corpusdesc = 'sahaaaaa' AND corpusimageids IS NULL AND rocf1 IS NULL AND rocf2 IS NULL AND rocf3 IS NULL AND rocc1 IS NULL AND rocc2 IS NULL AND rocc3 IS NULL AND corpusactive IS NULL AND corpusrunfrequency IS NULL AND corpuslastrun IS NULL AND corpuslastsync IS NULL AND rocsettingid IS NULL AND corpusaffinity IS NULL AND corpusterms IS NULL AND corpusdomain IS NULL) incoming 
  ON (a.corpusid = incoming.corpusid )  
  WHEN MATCHED THEN 
  UPDATE SET corpusid = incoming.corpusid , corpus_name = incoming.corpus_name , corpusdesc = incoming.corpusdesc , corpusimageids = incoming.corpusimageids , rocf1 = incoming.rocf1 , rocf2 = incoming.rocf2 , rocf3 = incoming.rocf3 , rocc1 = incoming.rocc1 , rocc2 = incoming.rocc2 , rocc3 = incoming.rocc3 , corpusactive = incoming.corpusactive , corpusrunfrequency = incoming.corpusrunfrequency , corpuslastrun = incoming.corpuslastrun , corpuslastsync = incoming.corpuslastsync , rocsettingid = incoming.rocsettingid , corpusaffinity = incoming.corpusaffinity , corpusterms = incoming.corpusterms , corpusdomain = incoming.corpusdomain 
  WHEN NOT MATCHED THEN 
  INSERT (corpusid, corpus_name, corpusdesc, corpusimageids, rocf1, rocf2, rocf3, rocc1, rocc2, rocc3, corpusactive, corpusrunfrequency, corpuslastrun, corpuslastsync, rocsettingid, corpusaffinity, corpusterms, corpusdomain) 
  VALUES (incoming.corpusid, incoming.corpus_name, incoming.corpusdesc, incoming.corpusimageids, incoming.rocf1, incoming.rocf2, incoming.rocf3, incoming.rocc1, incoming.rocc2, incoming.rocc3, incoming.corpusactive, incoming.corpusrunfrequency, incoming.corpuslastrun, incoming.corpuslastsync, incoming.rocsettingid, incoming.corpusaffinity, incoming.corpusterms, incoming.corpusdomain)

this is the real table:

CREATE TABLE "SBOOKS"."DEV_CORPUS" 
   (    "CORPUSID" NUMBER(9,0) NOT NULL ENABLE, 
    "CORPUS_NAME" VARCHAR2(768 BYTE) NOT NULL ENABLE, 
    "CORPUSDESC" VARCHAR2(4000 BYTE), 
    "CORPUSIMAGEIDS" VARCHAR2(768 BYTE), 
    "ROCF1" FLOAT(63), 
    "ROCF2" FLOAT(63), 
    "ROCF3" FLOAT(63), 
    "ROCC1" FLOAT(63), 
    "ROCC2" FLOAT(63), 
    "ROCC3" FLOAT(63), 
    "CORPUSACTIVE" NUMBER(3,0), 
    "CORPUSRUNFREQUENCY" NUMBER(3,0), 
    "CORPUSLASTRUN" DATE, 
    "CORPUSLASTSYNC" DATE, 
    "ROCSETTINGID" NUMBER(3,0), 
    "CORPUSAFFINITY" NUMBER(3,0), 
    "CORPUSTERMS" VARCHAR2(4000 BYTE), 
    "CORPUSDOMAIN" NUMBER(3,0), 
     PRIMARY KEY ("CORPUSID")

throws me this error:

Error at Command Line:2 Column:644
Error report:
SQL Error: ORA-00904: "CORPUSDOMAIN": invalid identifier
00904. 00000 -  "%s: invalid identifier"
*Cause:    
*Action:

.

I dont know what I am missing. Do u have any idea?

Thanks!

EDIT2: finally this works in comand win:

MERGE INTO dev_corpus a
  USING (SELECT 1000156 corpusid, 'sss2' corpus_name, 'sahaaaaaar' corpusdesc, null corpusimageids, null rocf1, null rocf2, null rocf3, null rocc1, null rocc2, null rocc3, null corpusactive, null corpusrunfrequency, null corpuslastrun, null corpuslastsync, null rocsettingid, null corpusaffinity, null corpusterms, null corpusdomain FROM dual) incoming 
  ON (a.corpusid = incoming.corpusid )  
  WHEN MATCHED THEN 
  UPDATE SET corpus_name = incoming.corpus_name , corpusdesc = incoming.corpusdesc , corpusimageids = incoming.corpusimageids , rocf1 = incoming.rocf1 , rocf2 = incoming.rocf2 , rocf3 = incoming.rocf3 , rocc1 = incoming.rocc1 , rocc2 = incoming.rocc2 , rocc3 = incoming.rocc3 , corpusactive = incoming.corpusactive , corpusrunfrequency = incoming.corpusrunfrequency , corpuslastrun = incoming.corpuslastrun , corpuslastsync = incoming.corpuslastsync , rocsettingid = incoming.rocsettingid , corpusaffinity = incoming.corpusaffinity , corpusterms = incoming.corpusterms , corpusdomain = incoming.corpusdomain 
  WHEN NOT MATCHED THEN 
  INSERT (corpusid, corpus_name, corpusdesc, corpusimageids, rocf1, rocf2, rocf3, rocc1, rocc2, rocc3, corpusactive, corpusrunfrequency, corpuslastrun, corpuslastsync, rocsettingid, corpusaffinity, corpusterms, corpusdomain) 
  VALUES (incoming.corpusid, incoming.corpus_name, incoming.corpusdesc, incoming.corpusimageids, incoming.rocf1, incoming.rocf2, incoming.rocf3, incoming.rocc1, incoming.rocc2, incoming.rocc3, incoming.corpusactive, incoming.corpusrunfrequency, incoming.corpuslastrun, incoming.corpuslastsync, incoming.rocsettingid, incoming.corpusaffinity, incoming.corpusterms, incoming.corpusdomain)

but this in java class nooot works in update cases, but if it is an insert case it will work. In case of update it will not throw any error it just freezes untill I delete the record from DB, then it inserts it, so no update!. Do you find something wrong in this code?

preparedStatement = dbConnection.prepareStatement("MERGE INTO dev_corpus a " +
                              "USING (SELECT ? corpusid, ? corpus_name, ? corpusdesc, ? corpusimageids, ? rocf1, ? rocf2, ? rocf3, ? rocc1, ? rocc2, ? rocc3, ? corpusactive, ? corpusrunfrequency, ? corpuslastrun, ? corpuslastsync, ? rocsettingid, ? corpusaffinity, ? corpusterms, ? corpusdomain FROM dual) incoming " +
                              "ON (a.corpusid = incoming.corpusid ) " +
                              "WHEN MATCHED THEN " +
                              "UPDATE SET corpus_name = incoming.corpus_name , corpusdesc = incoming.corpusdesc , corpusimageids = incoming.corpusimageids , rocf1 = incoming.rocf1 , rocf2 = incoming.rocf2 , rocf3 = incoming.rocf3 , rocc1 = incoming.rocc1 , rocc2 = incoming.rocc2 , rocc3 = incoming.rocc3 , corpusactive = incoming.corpusactive , corpusrunfrequency = incoming.corpusrunfrequency , corpuslastrun = incoming.corpuslastrun , corpuslastsync = incoming.corpuslastsync , rocsettingid = incoming.rocsettingid , corpusaffinity = incoming.corpusaffinity , corpusterms = incoming.corpusterms , corpusdomain = incoming.corpusdomain " +
                              "WHEN NOT MATCHED THEN " +
                              "INSERT (corpusid, corpus_name, corpusdesc, corpusimageids, rocf1, rocf2, rocf3, rocc1, rocc2, rocc3, corpusactive, corpusrunfrequency, corpuslastrun, corpuslastsync, rocsettingid, corpusaffinity, corpusterms, corpusdomain) " +
                              "VALUES (incoming.corpusid, incoming.corpus_name, incoming.corpusdesc, incoming.corpusimageids, incoming.rocf1, incoming.rocf2, incoming.rocf3, incoming.rocc1, incoming.rocc2, incoming.rocc3, incoming.corpusactive, incoming.corpusrunfrequency, incoming.corpuslastrun, incoming.corpuslastsync, incoming.rocsettingid, incoming.corpusaffinity, incoming.corpusterms, incoming.corpusdomain)");

thanks!


回答1:


Finally this works!, so here is the query for SQL command:

MERGE INTO dev_corpus a
  USING (SELECT 1000156 corpusid, 'sss2' corpus_name, 'sahaaaaaar' corpusdesc, null corpusimageids, null rocf1, null rocf2, null rocf3, null rocc1, null rocc2, null rocc3, null corpusactive, null corpusrunfrequency, null corpuslastrun, null corpuslastsync, null rocsettingid, null corpusaffinity, null corpusterms, null corpusdomain FROM dual) incoming 
  ON (a.corpusid = incoming.corpusid )  
  WHEN MATCHED THEN 
  UPDATE SET corpus_name = incoming.corpus_name , corpusdesc = incoming.corpusdesc , corpusimageids = incoming.corpusimageids , rocf1 = incoming.rocf1 , rocf2 = incoming.rocf2 , rocf3 = incoming.rocf3 , rocc1 = incoming.rocc1 , rocc2 = incoming.rocc2 , rocc3 = incoming.rocc3 , corpusactive = incoming.corpusactive , corpusrunfrequency = incoming.corpusrunfrequency , corpuslastrun = incoming.corpuslastrun , corpuslastsync = incoming.corpuslastsync , rocsettingid = incoming.rocsettingid , corpusaffinity = incoming.corpusaffinity , corpusterms = incoming.corpusterms , corpusdomain = incoming.corpusdomain 
  WHEN NOT MATCHED THEN 
  INSERT (corpusid, corpus_name, corpusdesc, corpusimageids, rocf1, rocf2, rocf3, rocc1, rocc2, rocc3, corpusactive, corpusrunfrequency, corpuslastrun, corpuslastsync, rocsettingid, corpusaffinity, corpusterms, corpusdomain) 
  VALUES (incoming.corpusid, incoming.corpus_name, incoming.corpusdesc, incoming.corpusimageids, incoming.rocf1, incoming.rocf2, incoming.rocf3, incoming.rocc1, incoming.rocc2, incoming.rocc3, incoming.corpusactive, incoming.corpusrunfrequency, incoming.corpuslastrun, incoming.corpuslastsync, incoming.rocsettingid, incoming.corpusaffinity, incoming.corpusterms, incoming.corpusdomain)

and here is the java code using pstmt:

preparedStatement = dbConnection.prepareStatement("MERGE INTO dev_corpus a " +
                              "USING (SELECT ? corpusid, ? corpus_name, ? corpusdesc, ? corpusimageids, ? rocf1, ? rocf2, ? rocf3, ? rocc1, ? rocc2, ? rocc3, ? corpusactive, ? corpusrunfrequency, ? corpuslastrun, ? corpuslastsync, ? rocsettingid, ? corpusaffinity, ? corpusterms, ? corpusdomain FROM dual) incoming " +
                              "ON (a.corpusid = incoming.corpusid) " +
                              "WHEN MATCHED THEN " +
                              "UPDATE SET a.corpus_name = incoming.corpus_name , a.corpusdesc = incoming.corpusdesc , a.corpusimageids = incoming.corpusimageids , a.rocf1 = incoming.rocf1 , a.rocf2 = incoming.rocf2 , a.rocf3 = incoming.rocf3 , a.rocc1 = incoming.rocc1 , a.rocc2 = incoming.rocc2 , a.rocc3 = incoming.rocc3 , a.corpusactive = incoming.corpusactive , a.corpusrunfrequency = incoming.corpusrunfrequency , a.corpuslastrun = incoming.corpuslastrun , a.corpuslastsync = incoming.corpuslastsync , a.rocsettingid = incoming.rocsettingid , a.corpusaffinity = incoming.corpusaffinity , a.corpusterms = incoming.corpusterms , a.corpusdomain = incoming.corpusdomain " +
                              "WHEN NOT MATCHED THEN " +
                              "INSERT (corpusid, corpus_name, corpusdesc, corpusimageids, rocf1, rocf2, rocf3, rocc1, rocc2, rocc3, corpusactive, corpusrunfrequency, corpuslastrun, corpuslastsync, rocsettingid, corpusaffinity, corpusterms, corpusdomain) " +
                              "VALUES (incoming.corpusid, incoming.corpus_name, incoming.corpusdesc, incoming.corpusimageids, incoming.rocf1, incoming.rocf2, incoming.rocf3, incoming.rocc1, incoming.rocc2, incoming.rocc3, incoming.corpusactive, incoming.corpusrunfrequency, incoming.corpuslastrun, incoming.corpuslastsync, incoming.rocsettingid, incoming.corpusaffinity, incoming.corpusterms, incoming.corpusdomain)");

you have the create table in the question section, hope it helps someone! :)




回答2:


If you're using Oracle then you'll need to focus on the MERGE statement - the INSERT ... ON DUPLICATE KEY doesn't work in Oracle.

I don't know if this is the only problem, but there are some syntax errors in the MERGE you posted:

MERGE INTO dev_corpus a
USING (SELECT * FROM dual WHERE (corpusid=?, corpus_name=?, corpuslastsync=?)
                                ^^^^^^^^^^^^^^^^^^^^^^ (1)
ON (a.corpusid = incoming.corpusid )
WHEN MATCHED THEN
UPDATE SET (a.corpus_name = incoming.corpus_name AND a.corpuslastsync = incoming.corpuslastsync )
            ^^^^^^^^^^^^^^^^^^ (2)
WHEN NOT MATCHED THEN
INSERT (a.corpusid, a.corpus_name, a.corpuslastsync)
VALUES (incoming.corpusid, incoming.corpus_name, incoming.corpuslastsync)

Problem (1): you have an unclosed parenthesis, plus the multiple WHERE conditions should be separated by AND, not a comma. Here's the corrected version, indented so it doesn't require horizontal scrolling:

USING (
  SELECT * FROM dual
  WHERE (corpusid=? AND corpus_name=? AND corpuslastsync=?))

The parentheses surrounding the WHERE conditions are optional in this case, so this would work too:

USING (
  SELECT * FROM dual
  WHERE corpusid=? AND corpus_name=? AND corpuslastsync=?)

Problem (2): The parentheses after the SET, and here you need the comma instead of the AND. It should look like this (as above, I've indented this so it can be read without horizontal scrolling)

UPDATE SET
  a.corpus_name = incoming.corpus_name,
  a.corpuslastsync = incoming.corpuslastsync

That should take care of any syntax errors, but of course that's no guarantee your results will be as expected :)

Finally, as I mentioned in the comments, try this out in SQLPlus or SQL Developer using test values (not parameters). It'll be much, much easier to debug that way. When you've got the MERGE behaving correctly you can move it to the Java code and parameterize it. Best of luck!


Addendum for the updated question

First of all, good news you're using SQL Developer to work this out! Disregard my last paragraph above :)

Second, your where includes AND corpuslastsync = null. When checking for null, you need IS NULL, not = NULL:

... AND corpuslastsync IS NULL

Finally, I'm pretty sure the specific error you're getting with your latest attempt is due to the aliases on this line:

INSERT (a.corpusid, a.corpus_name, a.corpuslastsync)

Try this instead:

INSERT (corpusid, corpus_name, corpuslastsync)

Oracle knows that the columns named here belong to the dev_corpus table, aliased as a.



来源:https://stackoverflow.com/questions/17705576/oracle-merge-and-prepared-statement

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!