问题
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