SQL Batch Update error - New request is not allowed to start because it should come with valid transaction descriptor - sql

I am running microsoft sql 2008 and jdbc driver 3.0 and am getting this error on a batch SQL update
"New request is not allowed to start because it should come with valid transaction descriptor"
To debug I've reduced the batch size down to just one statement, but it still errors. Here it is
IF EXISTS (SELECT * FROM StaffDetail WHERE PsnID = 'GC91')
UPDATE staffdetail
SET psnid = 'GC91',
servicegroup = '41B001',
discipline = 'IT',
dob = '1967-09-28',
ghdstartdate = '2008-12-15',
yearsexperience = '11 to 20 years',
classification = 'Admin Officer 1'
WHERE psnid = 'GC91'
ELSE
INSERT INTO staffdetail
(psnid,
servicegroup,
discipline,
dob,
ghdstartdate,
yearsexperience,
classification)
VALUES ('GC91',
'41B001',
'IT',
'1967-09-28',
'2008-12-15',
'11 to 20 years',
'Admin Officer 1')
Why does it error? I've googled this and only found references to a bug in SQL 2005 not 2008.
Is there any way I can change the connection string I use to connect or change the SQL statements I use in the batch to try and avoid this error?

Try changing your SQL to this:
UPDATE StaffDetail SET PsnID = 'GC91',ServiceGroup = '41B001',Discipline = 'IT',DOB = '1967-09-28',GHDStartDate = '2008-12-15',YearsExperience = '11 to 20 years',Classification = 'Admin Officer 1' WHERE PsnID = 'GC91';
INSERT INTO StaffDetail (PsnID,ServiceGroup,Discipline,DOB,GHDStartDate,YearsExperience,Classification)
SELECT 'GC91','41B001','IT','1967-09-28','2008-12-15','11 to 20 years','Admin Officer 1'
WHERE NOT EXISTS (SELECT * FROM StaffDetail WHERE PsnID = 'GC91')

can you put the above code as Stored Procedure definition and pass thru using con.prepareStatement ?

A late update, in case others find my findings useful...
I have had this problem a lot recently. Re-architeching the query to either use CTE or Table Variables has often resolved it, but believe that ultimately, as noted at http://computer-aaaargh.blogspot.co.za/2012/12/weird-cause-of-msg-3989-new-request-is.html , it has to do with the underlying data. Look at your joins and try and change what you are fetching back from the underlying data - in this case only the one statement (Try SELECT 1 FROM StaffDetail WHERE PsnID = 'GC91') or use another script in the exist just as a form of elimination.

You can MERGE instead which removes the IF and ELSE which makes it really one statement
MERGE INTO staffdetail AS TARGET
USING (VALUES ('GC91',
'41B001',
'IT',
'1967-09-28',
'2008-12-15',
'11 to 20 years',
'Admin Officer 1')) AS SOURCE (psnid, servicegroup, discipline, dob,
ghdstartdate, yearsexperience, classification)
ON TARGET.psnid = SOURCE.psnid
WHEN MATCHED THEN
UPDATE SET servicegroup = SOURCE.servicegroup,
discipline = SOURCE.discipline,
dob = SOURCE.dob,
ghdstartdate = SOURCE.ghdstartdate,
yearsexperience = SOURCE.yearsexperience,
classification = SOURCE.classification
WHEN NOT MATCHED BY TARGET THEN
INSERT (psnid,
servicegroup,
discipline,
dob,
ghdstartdate,
yearsexperience,
classification)
VALUES ('GC91',
'41B001',
'IT',
'1967-09-28',
'2008-12-15',
'11 to 20 years',
'Admin Officer 1')

Related

ORACLE(TOAD) CASE with multiple conditions for different updates

I need to update qualifications in a Oracle DB, I am running into a problem where my script errors.
I would usually create a few smaller update statements to get the job done.
However I thought it would be better to do one query, this is simple but my background is mostly on T-SQL and mySQL not Oracle.
So help would be appreciated.
My Statement.
--ALTER SESSION TO CHANGE DT--
alter session set nls_date_format = 'DD/MM/YYYY HH24:MI:SS';
--Update
Update Qualifications_t
Set (COMMENTS = 'Task'),
(Expiry_DTS = CASE Expiry_DTS
When cd = '1'
Then Expiry_DTS = '31/12/2016 23:59:00'
When cd = '2'
Then Expiry_DTS = '01/07/2019 23:59:00'
When cd = '3'
Then Expiry_DTS = '31/12/1999 23:59:00'
When cd = '4'
Then Expiry_DTS = '31/08/2021 23:59:00'
When cd = '5'
Then Expiry_DTS = '17/06/2021 23:59:00')
END
Where EXPIRY_DTS IS NULL;
--SELECT
Select *
from QUALIFICATIONS_T
where COMMENTS = 'Task';
Error at line 5
ORA-00905: missing keyword
Yes, I googled it but couldn't figure it out.
Remove the parentheses around the update assignments.
Then: it's not clear what you mean by the case expression. Perhaps this:
update qualifications_t
set comments = 'task',
expiry_dts = case when cd = '1' then to_date('31/12/2016 23:59:00',
'dd/mm/yyyy hh24:mi:ss')
when cd = '2' then to_date(....)
(etc.)
end
where expiry_dts is null
;
Notice the structure of a case expression. The name of the column you are updating doesn't belong after the keyword case, and the case expression "returns" values directly, not through assignments. There should be only one assignment ("equal sign"); the case expression is evaluated and returns a single value, used for update.
Note also the proper way to represent date values (assuming the column data type is date, as it should be; if it isn't, you should fix that first).

GETTING ERROR-- ORA-00936:MISSING EXPRESSION for below query please help on this

SELECT CASE (SELECT Count(1)
FROM wf_item_activity_statuses_v t
WHERE t.activity_label IN ('WAITING_DISB_REQ',
'LOG_DDE',
'LOG_SENDBACK_DDE')
AND t.item_key IN(
SELECT r.i_item_key
FROM wf_t_item_xref r
WHERE r.sz_appl_uniqueid = '20400000988')
)
WHEN 0 THEN
(
delete
from t_col_val_document_uploaded p
WHERE p.sz_application_no = '20400000988'
AND p.sz_collateral_id = 'PROP000000000PRO1701'
AND p.i_item_key = '648197'
AND p.i_document_srno = '27' )
WHEN 1 THEN
(
DELETE
FROM t_col_val_document_uploaded p
WHERE p.sz_application_no = '20400000988'
AND p.sz_collateral_id = 'PROP000000000PRO1701'
AND p.i_document_srno = '28' )
ELSE NULL
END
FROM dual;
You need to recreate your query and make sure to follow the flow of the clauses properly, please check the next two links to get a better understanding :
[ORA-00936: missing expression tips]
How do I address this ORA-00936 error?
Answer: The Oracle oerr utility notes this about the ORA-00936 error:
ORA-00936 missing expression
Cause: A required part of a clause or expression has been omitted. For example, a SELECT statement may have been entered without a list of columns or expressions or with an incomplete expression. This message is also issued in cases where a reserved word is misused, as in SELECT TABLE.
Action: Check the statement syntax and specify the missing component.
The ORA-00936 happens most frequently:
1 - When you forget list of the column names in your SELECT statement.
2. When you omit the FROM clause of the SQL statement.
ora-00936-missing-expression
I hope this can help you.
You cannot use a simple select query like this. You have to use a PL/SQL block like below -
DECLARE NUM_CNT NUMBER := 0;
BEGIN
SELECT Count(1)
INTO NUM_CNT
FROM wf_item_activity_statuses_v t
WHERE t.activity_label IN ('WAITING_DISB_REQ',
'LOG_DDE',
'LOG_SENDBACK_DDE')
AND t.item_key IN(SELECT r.i_item_key
FROM wf_t_item_xref r
WHERE r.sz_appl_uniqueid = '20400000988');
IF NUM_CNT = 0 THEN
delete
from t_col_val_document_uploaded p
WHERE p.sz_application_no = '20400000988'
AND p.sz_collateral_id = 'PROP000000000PRO1701'
AND p.i_item_key = '648197'
AND p.i_document_srno = '27';
ELSIF NUM_CNT = 1 THEN
DELETE
FROM t_col_val_document_uploaded p
WHERE p.sz_application_no = '20400000988'
AND p.sz_collateral_id = 'PROP000000000PRO1701'
AND p.i_document_srno = '28' )
END IF;
END;

How can I retrieve an updated script in the oracle database?

How can I retrieve an updated script in the oracle database?
An incorrect script was run in the oracle database. I want to get this script back. how can I do that? The script is as follows.
--52 record
update cons.paymentplan_detail det set det.payment_date = to_char(ADD_MONTHS(to_Date (det.payment_date, 'YYYYMMDD'),3),'YYYYMMDD')
where det.oid in (select det.oid
from cons.instalment_instalment_loan ins,
cons.paymentplan_detail det,
cons.paymentplan_def def,
(select ins.loans_reference_no,min(det.payment_date) as payment_date
from cons.instalment_instalment_loan ins,
cons.paymentplan_detail det,
cons.paymentplan_def def
where ins.loan_state in ('OPEN', 'BLOCKED')
and ins.status = '1'
and def.status = '1'
and det.status = '1'
and ins.payment_plan_oid = det.payment_plan_oid
and det.plan_detail_status in ('NO','LT')
and ins.OID='251pfek38q43fg00'
and def.oid = det.payment_plan_oid
and def.payment_plan_status = 'GR'
and def.credit_oid = ins.oid
group by ins.loans_reference_no) t
where ins.loan_state in ('OPEN', 'BLOCKED')
and ins.status = '1'
and def.status = '1'
and det.status = '1'
and ins.payment_plan_oid = det.payment_plan_oid
and det.plan_detail_status in ('NO')
and ins.OID='251pfek38q43fg00'
and def.oid = det.payment_plan_oid
and def.payment_plan_status = 'GR'
and def.credit_oid = ins.oid
and t.loans_reference_no = ins.loans_reference_no
group by det.oid);
If you haven't COMMITted the data then use ROLLBACK.
Otherwise, your solution could be as simple as running the same query but subtracting 3 months:
update cons.paymentplan_detail det
set det.payment_date = to_char(
ADD_MONTHS(
to_Date (det.payment_date, 'YYYYMMDD'),
-3 -- Changed from +3 to -3
),
'YYYYMMDD'
)
where ...
If that won't work and you have COMMITted the data and the database has flashback activated then you can use a flashback query to find the old data from before the UPDATE.
If all that fails, then you can look and see if the database has a recent backup you can restore from.

Converting the sybase stuff function in to oracle

Sybase query :
UPDATE #horizCallSign SET
effDaysZ = STUFF( effDaysZ, csd.day+shift1, 1, '1')
FROM #callSignTbl csd
WHERE csd.legId1 = #horizCallSign.legId1
AND csd.legId2 = #horizCallSign.legId2
AND day = 28
Oracle Query :
UPDATE TEMP_HORIZ_CALL_SIGN
SET eff_Days_Z = REPLACE( eff_days_Z,csd.day+shift1, '1')
FROM temp_call_sign_table1 csd
WHERE csd.leg_Id1 = temp_horiz_Call_Sign.leg_Id1
AND csd.leg_Id2 = horiz_Call_Sign.leg_Id2
AND day = 28
In Oracle, we have changed the column names with having "_" in them.
temp_call_sign_table1 and TEMP_HORIZ_CALL_SIGN are global temporary tables
created for Oracle in place of sybase temp tables with on commit preserve
rows.
We are converting sybase DB to Oracle DB. When I execute the above query in oracle it says QL Error: ORA-00933: SQL command not properly ended.
Please help.
There was an issue with your table name on line 5, this is easily avoided by using aliases.
Also, you can't use FROM in Oracle without a SELECT. Thus a sub-query must be used in this instance. For example...
UPDATE TEMP_HORIZ_CALL_SIGN hcs
SET eff_Days_Z =
(SELECT
REPLACE(eff_days_Z,csd.day+shift1, '1')
FROM temp_call_sign_table1 csd
WHERE csd.leg_Id1 = hcs.leg_Id1
AND csd.leg_Id2 = hcs.leg_Id2
AND day = 28)
(Not tested)
Your are off on your aliasing. Also, consider using INNER JOINS instead.
UPDATE THCS
SET eff_Days_Z = REPLACE( eff_days_Z,csd.day+shift1, '1')
FROM temp_call_sign_table1 csd , TEMP_HORIZ_CALL_SIGN THCS, horiz_Call_Sign HCS
WHERE csd.leg_Id1 = THCS.leg_Id1
AND csd.leg_Id2 = HCS.leg_Id2
AND day = 28
In Oracle, You can use MERGE INTO.
MERGE INTO temp_horiz_call_sign m
using (SELECT leg_id1,
leg_id2,
eff_days_z,
day + shift1 plushift1
FROM temp_call_sign_table1
WHERE day = 28) r
ON ( r.leg_id1 = m.leg_id1
AND r.leg_id2 = m.leg_id2 )
WHEN matched THEN
UPDATE SET m.eff_days_z = Replace(m.eff_days_z, r.plushift1, '1');

Oracle Merge to be Scheduled Job

I have written two merge statements that I intend to be set up on an Oracle 10g (10.2) database, I will send these to the Oracle DBA to be evaluated before being implemented, but I'm quite a noob when it comes to Oracle PL/SQL coding so wanted to ask the question here whether there is something obviously wrong with these statements before looking a fool in front of the DBA.
In this scenario, I have an engineering database that is setup; the tag number (component.cmpnt_name) is often used as a basis to create other equipment tags or document numbers in the database. Only, in later workflows the Tag Number may get changed, but, that change does not filter down and change the equipment or document numbers automatically so we are left with mismatches.
So this is a bit of a sledgehammer approach to making the equipment names (cs_tag_name) and document name (dwg_name) match again. The Tag Number naming convention often has spaces (whitespace) within it which is done on purpose and required, but these spaces are trimmed when the equipment and document numbers are first created.
So the idea is to trim the spaces out of the cmpnt_name field, then update the cs_tag_name and the dwg_name fields accordingly. I hope that made sense. Merge code below.
Merge 1, updating the dwg_name = trimmed cmpnt_name ...
MERGE INTO drawing
USING
(
SELECT c.cmpnt_id, c.cmpnt_name, ssd.dwg_id
FROM component c, spec_sheet_data ssd
WHERE c.cmpnt_id = ssd.cmpnt_id and c.cmpnt_id > 0 and ssd.spec_form_id > 0
) ta ON (ta.dwg_id = drawing.dwg_id
and replace(ta.cmpnt_name, ' ', '') <> drawing.dwg_name)
WHEN MATCHED THEN UPDATE
SET replace(ta.cmpnt_name, ' ', '') = drawing.dwg_name
Merge 2 updating the cs_tag_name = trimmed cmpnt_name ...
MERGE INTO control_system_tag
USING
(
SELECT c.cmpnt_id, c.cmpnt_name
FROM component c
WHERE c.cmpnt_id > 0
) tb ON (tb.cmpnt_id = control_system_tag.cmpnt_id and
replace(tb.cmpnt_name, ' ', '') <> control_system_tag.cs_tag_name)
WHEN MATCHED THEN UPDATE
SET replace(tb.cmpnt_name, ' ', '') = control_system_tag.cs_tag_name
MERGE is for (INSERT and UPDATE) and sometimes DELETE.
You have only UPDATE. Why do you need MERGE? Use UPDATE!
next:
SET replace(tb.cmpnt_name, ' ', '') = control_system_tag.cs_tag_name
will not work, column name should be on the left side:
SET control_system_tag.cs_tag_name = replace(tb.cmpnt_name, ' ', '')
Here is update statement:
UPDATE drw set
dwg_name = lace(c.cmpnt_name, ' ', '')
FROM drawing drw, component c, spec_sheet_data ssd
WHERE c.cmpnt_id = ssd.cmpnt_id
and c.cmpnt_id > 0
and ssd.spec_form_id > 0
and ta.dwg_id = drw.dwg_id
and drw.dwg_name = lace(c.cmpnt_name, ' ', '')