ORA-01002: fetch out of sequence - sql

I am getting org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL
UPDATE responses
SET version_no = ( version_no + 1 ),
read_status = 0,
tslastmodified = SYSDATE
WHERE responseid IN (SELECT responseid
FROM responses
WHERE read_status = 1
AND tslastmodified < SYSDATE - 45 / ( 24 * 60 )
AND id IN (SELECT id
FROM emp))
; SQL state [24000]; error code [1002]; ORA-01002: fetch out of sequence
; nested exception is java.sql.SQLException: ORA-01002: fetch out of sequence
JAVA code :
getJdbcTemplate().queryForObject(SurveyQuery.UPDATE_INPROCESS, Integer.class);
Please let me know what is wrong in above query

You can modify your UPDATE statement to something like below
UPDATE RESPONSES SET VERSION_NO=(VERSION_NO+1),
READ_STATUS=0,
TSLASTMODIFIED = SYSDATE
WHERE READ_STATUS = 1
AND TSLASTMODIFIED < SYSDATE - 45/(24*60)
AND EXISTS (SELECT 1 FROM EMP
WHERE RESPONSES.ID = EMP.ID)
Note: Though you can use the above modified query but I doubt the said error is because of the posted update statement. From Documentation it looks like the cause of the above error could be
When you perform a FETCH on an active cursor after all records have
been fetched.
(OR)
When you perform a FETCH on a SELECT FOR UPDATE after a COMMIT has
been issued.

Related

PLSQL - Update statement with variable

I am currently trying to write an update statement using a variable (which will be expanded to use multiple variables later on).
Currently I have the following statement (altered for posting here), but I am running into an error and I don't immediately see the mistake I am making:
DECLARE
v_var1 table1.CY_VALUE % TYPE;
BEGIN
SELECT SUM(Column1 + Column2)
INTO v_var1
FROM table2
WHERE survey_ID = 1 AND Active_Flag = 1
GROUP BY SURVEY_ID;
UPDATE table1
SET CY_VALUE = v_var1
WHERE SURVEY_ID = 1 AND KPI_ID = 1;
END;
This is the error I am receiving:
SQL Error [6550] [65000]: ORA-06550: line 15, column 1:
PLS-00103: Encountered the symbol "END" when expecting one of the following:
:= . ( # % ;
What do I need to alter in order to get this to work in this example?
Or are there better ways to write the update for table 1, containing a sum from table 2?
There is nothing obviously wrong with your code. But why not just use a correlated subquery and dispense with the variable -- and the PL/SQL?
UPDATE table1 t1
SET CY_VALUE = (SELECT SUM(t2.Column1 + t2.Column2)
FROM table2 t2
WHERE t2.survey_ID = t1.survey_ID AND
t2.Active_Flag = 1
)
WHERE SURVEY_ID = 1 AND KPI_ID = 1;
Although not related to your error, the GROUP BY in the first query is also misleading. An aggregate query with a GROUP BY can return any number of rows -- including 0. Instead, just lead out the GROUP BY:
SELECT SUM(Column1 + Column2)
INTO v_var1
FROM table2
WHERE survey_ID = 1 AND Active_Flag = 1;
The WHERE clause filters down to the survery_ID you want and without the GROUP BY this query always returns exactly one row.

DB2 i 7.3: writing stored procedures that loop (with date variable) insert values from select

I'm having problem to create procedure in db2 i 7.3. The main ideia is to a given end date (should be today) to insert values to specific table from selected that results match with fist_day(end date - 3 years) and last_day(end date - 3 years) for every month until today.
Is currently returning this error: 14:19:25 [CREATE - 0 row(s), 0.000 secs] [Error Code: -199, SQL State: 42601] [SQL0199] Palavra-chave FOR não esperada. Testemunhos válidos: ;.
... 1 statement(s) executed, 0 row(s) affected, exec/fetch time: 0.000/0.000 sec [0 successful, 0 warnings, 1 errors]
Above my code:
CREATE PROCEDURE MYLIB.SP_DIFJURO ()
LANGUAGE SQL
MODIFIES SQL DATA
BEGIN
DECLARE DATAJURO DATE DEFAULT NULL;
FOR DATAJURO > (SELECT CURRENT_DATE - 3 YEAR FROM SYSIBM.SYSDUMMY1)
DO
INSERT INTO MYLIB.SDDIFJUROD (CONTAJURO, JUROCALC, JURODEBIT, DATAINICIO, DATAFIM)
SELECT NCJCCONTA, totaljurocalculado, NCLJVLRJ, LEFT(CHAR(LAST_DAY(DATAJURO), ISO),8)||'01', LAST_DAY(DATAJURO) FROM ( SELECT SUM(valorjurocalculado) totaljurocalculado, a.NCJCCONTA from
(SELECT C.NCJCCONTA NCJCCONTA, C.NCJCDTPRO, C.NCJCDTJUR,
CASE
WHEN R.NCJCTREG = 'R' THEN R.NCJCSLDV
ELSE C.NCJCSLDV
END saldodatavalor,
CASE
WHEN R.NCJCTREG = 'R' THEN round(R.NCJCTXC,2)
ELSE round(C.NCJCTXC,2)
END taxadiaria, decimal(round((ifnull(R.NCJCSLDV, C.NCJCSLDV)*ifnull(R.NCJCTXC, C.NCJCTXC)/100)/360,2),15,2) valorjurocalculado
FROM (
SELECT NCJCCONTA, NCJCDTPRO, NCJCDTJUR, NCJCTREG, NCJCSLDV, NCJCMOED, NCJCTXC FROM MYLIB.LOGJR
WHERE NCJCDTJUR BETWEEN LEFT(VARCHAR_FORMAT(LAST_DAY(DATAJURO), 'YYYYMMDD'),6)||'01' AND VARCHAR_FORMAT(LAST_DAY(DATAJURO), 'YYYYMMDD')
AND NCJCCLCP = 'DO' AND NCJCTREG = 'C' AND NCJCNUMVD < 0 ) C
LEFT JOIN
(SELECT NCJCCONTA, NCJCDTPRO, NCJCDTJUR, NCJCTREG, NCJCSLDV, NCJCMOED, NCJCTXC FROM MYLIB.LOGJR
WHERE NCJCDTJUR BETWEEN LEFT(VARCHAR_FORMAT(LAST_DAY(DATAJURO), 'YYYYMMDD'),6)||'01' AND VARCHAR_FORMAT(LAST_DAY(DATAJURO), 'YYYYMMDD')
AND NCJCCLCP = 'DO' AND NCJCTREG = 'R' AND NCJCNUMVD < 0) R
ON C.NCJCCONTA = R.NCJCCONTA AND C.NCJCDTJUR = R.NCJCDTJUR
) a group by a.NCJCCONTA
)jurocalc
INNER JOIN MYLIB.LJRDC ON NCLJCONTA = NCJCCONTA
AND LEFT(NCLJBUFFER, 16) = LEFT(VARCHAR_FORMAT(LAST_DAY(DATAJURO), 'YYYYMMDD'),6)||'01'||VARCHAR_FORMAT(LAST_DAY(DATAJURO), 'YYYYMMDD')
WHERE int(ABS(totaljurocalculado)) != int(ABS(NCLJVLRJ));
SET DATAJURO = (SELECT DATAJURO - 1 MONTH FROM SYSIBM.SYSDUMMY1);
END FOR;
END
Wrong use of FOR statement.
FOR in SQL/PL doesn't look like for loop in some programming language like c or java. You must use a SELECT statement with FOR, which iterates the result set of this SELECT providing you an ability to reference the corresponding column values in the statements inside the body of FOR by cursor name C1.
In the example below the SELECT statement using Recursive Common Table Expression returns the last day of every month from CURRENT_DATE - 3 YEARS to CURRENT_DATE. You may run this SELECT standalone to check / slightly modify its condition to return exact list of dates needed.
Note, that you don't use a SET statement to increment your "loop variable" C1.DATAJURO, since the SELECT statement handles this.
FOR C1 AS
WITH DATES (DT) AS
(
VALUES FIRST_DAY(CURRENT_DATE)
UNION ALL
SELECT DT - 1 MONTH
FROM DATES
WHERE DT > CURRENT_DATE - 3 YEAR
)
SELECT LAST_DAY(DT) AS DATAJURO
FROM DATES
DO
INSERT INTO MYLIB.SDDIFJUROD ...
... C1.DATAJURO ...
END FOR;

Oracle SQL syntax error (missing right parenthesis)

I don't understand why this provokes a syntax error (missing right parenthesis):
UPDATE table
SET doc =
(SELECT 'table-2844-doc' || SUBSTR(doc_file, INSTR(doc_file, '.', -1))
FROM docvers
WHERE (docvers.table_name = 'other_table'
AND docvers.field_name = 'doc')
AND ROWNUM = 1
ORDER BY VERSION DESC)
WHERE table_id = 2844
This looks right to me, does get executed correctly in SQL Server, and is similar to requests found, for example, in Oracle SQL: Update a table with data from another table.
Any tip?
Do it like this:
UPDATE table
SET doc = (
select r.myval
from (
SELECT 'table-2844-doc' || SUBSTR(doc_file, INSTR(doc_file, '.', -1)) myval, ROWNUM RN
FROM docvers
WHERE docvers.table_name = 'other_table'
AND docvers.field_name = 'doc'
ORDER BY VERSION DESC
) r
where r.RN = 1
)
WHERE table_id = 2844
Select the data set first including the ROWNUM, then select from that data set the first row.

Invalid Identifier on Update (Oracle)

I try to execute following command:
UPDATE DB_TEST.STOCK_ITEMS
SET STATUS = (SELECT *
FROM (SELECT STOCK_ITEM_STATUS
FROM DB_TEST.STOCK_ITEMS_HISTORY
WHERE STOCK_ITEM_ID = DB_TEST.STOCK_ITEMS.ID
ORDER BY CHANGED_ON DESC, ID DESC)
WHERE ROWNUM <= 1)
WHERE EXISTS (SELECT *
FROM DB_TEST.STOCK_ITEMS_HISTORY
WHERE STOCK_ITEM_ID = DB_TEST.STOCK_ITEMS.ID);
But I get the error:
SQL-Error: ORA-00904: "DB_TEST"."STOCK_ITEMS"."ID": invalid identifier
I looked up the Oracle error, but all I get is that I supposedly used a wrong or missing column name, but the DB_TEST.STOCK_ITEMS.ID field definitely exists.
What other reasons can cause this error?
Oracle limits the scope of a table to one level of subqueries. Here is a method that solves your problem using keep:
UPDATE DB_TEST.STOCK_ITEMS
SET STATUS = (SELECT MAX(STOCK_ITEM_STATUS) KEEP (DENSE_RANK FIRST ORDER BY CHANGED_ON DESC, ID DESC)
FROM DB_TEST.STOCK_ITEMS_HISTORY
WHERE STOCK_ITEM_ID = DB_TEST.STOCK_ITEMS.ID
)
WHERE EXISTS (SELECT 1
FROM DB_TEST.STOCK_ITEMS_HISTORY
WHERE STOCK_ITEM_ID = DB_TEST.STOCK_ITEMS.ID
);

UPDATE where timestamp is the latest

I have a group of records all with the same data except the timestamp (Yeah, not my design)
Example:
record_id, user, tmstmp
1, myself, 2006-11-15 09:56:14.325882-05
1, myself, 2006-11-15 09:56:19.051823-05
1, myself, 2006-11-15 11:23:30.581366-05
etc...
Now I would like to UPDATE the record with the latest timestamp. Here is what I'm trying with no luck yet:
UPDATE tbl
SET user = 'TESTING'
WHERE record_id = 1
ORDER BY tmstmp DESC
LIMIT 1
The ORDER BY throws the syntax error.
I think it should be a AND condition but not seeing how. Any thoughts?
PostgreSQL is my db.
UPDATE tbl
SET user = 'TESTING'
WHERE record_id = 1
AND tms_tmp in
(select max(tms_tmp) from tbl where record_id = 1)
UPDATE mytable
SET user = 'TESTING'
WHERE ctid =
(
SELECT ctid
FROM mytable
WHERE record_id = 1
ORDER BY
tmstmp DESC
LIMIT 1
)
This will correctly handle duplicates on tmstmp, if any.
Using PL/pgsql:
DECLARE
cur CURSOR(key int) FOR
SELECT * FROM tbl WHERE tbl.record_id = key ORDER BY tmstmp DESC FOR UPDATE;
BEGIN
OPEN cur(1); -- record_id
MOVE NEXT FROM cur;
UPDATE tbl SET "user" = 'TESTING' WHERE CURRENT OF cur;
CLOSE cur;
END
You can do this in a DO block (from version 9.0) or a function.