Oracle SQL syntax error (missing right parenthesis) - sql

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.

Related

"ORA-00923: FROM keyword not found where expected\n what should I fix

I have an oracle query as follows but when I make changes to pagination the results are different. what should i pass for my code
SELECT *
FROM (
SELECT b.*,
ROWNUM r__
FROM (
select a.KODE_KLAIM,
a.NO_SS,
a.LA,
a.NAMA_TK,
a.KODE_K,
(
select tk.TEM_LAHIR
from KN.VW_KN_TK tk
where tk.KODE_K = a.KODE_K and rownum=1
) TEM_LAHIR,
(
select TO_CHAR(tk.TLAHIR, 'DD/MM/RRRR')
from KN.VW_KTK tk
where tk.KODE_K = a.KODE_K
and rownum=1
) TLAHIR
from PN.KLAIM a
where nvl(a.STATUS_BATAL,'X') = 'T'
and A.NOMOR IS NOT NULL
and A.TIPE_KLAIM = 'JPN01'
)b
)
where 1 = 1
WHERE ROWNUM < ( ( ? * ? ) + 1 )
WHERE r__ >= ( ( ( ? - 1 ) * ? ) + 1 )
but i run this query i have result ORA-00900: invalid SQL statement
You have three WHERE clauses at the end (and no ORDER BY clause). To make it syntactically valid you could change the second and third WHERE clauses to AND.
However, you mention pagination so what you probably want is to use:
SELECT *
FROM (
SELECT b.*,
ROWNUM r__
FROM (
select ...
from ...
ORDER BY something
)b
WHERE ROWNUM < :page_size * :page_number + 1
)
WHERE r__ >= ( :page_number - 1 ) * :page_size + 1
Note: You can replace the named bind variables with anonymous bind variables if you want.
Or, if you are using Oracle 12 or later then you can use the OFFSET x ROWS FETCH FIRST y ROWS ONLY syntax:
select ...
from ...
ORDER BY something
OFFSET (:page_number - 1) * :page_size ROWS
FETCH FIRST :page_size ROWS ONLY;
Additionally, you have several correlated sub-queries such as:
select tk.TEM_LAHIR
from KN.VW_KN_TK tk
where tk.KODE_K = a.KODE_K and rownum=1
This will find the first matching row that the SQL engine happens to read from the datafile and is effectively finding a random row. If you want a specific row then you need an ORDER BY clause and you need to filter using ROWNUM AFTER the ORDER BY clause has been applied.
From Oracle 12, the correlated sub-query would be:
select tk.TEM_LAHIR
from KN.VW_KN_TK tk
where tk.KODE_K = a.KODE_K
ORDER BY something
FETCH FIRST ROW ONLY

Using results from CTE giving ERROR: missing FROM-clause entry for table "cte"

I'm trying to use the results from my first query to perform a second query
WITH cte AS(
SELECT * FROM test_user WHERE user_id = NEW.user_id
)
UPDATE test_username SET money_counter = money_counter + 1, total_revenue = total_revenue + cte.total_revenue
WHERE username = cte.username;
But I'm getting an error
ERROR: missing FROM-clause entry for table "cte"
LINE 5: WHERE username = cte.username
^
QUERY: WITH cte AS(
SELECT * FROM test_user WHERE user_id = NEW.user_id
)
UPDATE test_username SET money_counter = money_counter + 1, total_revenue = total_revenue + cte.total_revenue
WHERE username = cte.username
CONTEXT: PL/pgSQL function test_trigger() line 4 at SQL statement
SQL state: 42P01
Not sure what I'm doing incorrectly.
This is from the returned results from the query:
SELECT * FROM test_user WHERE user_id = 1;
And the table I'm performing the second query on:
The WITH clause just defines a common table expression. You still need a FROM clause to access it. Using your query 'as is' -
WITH cte AS (
SELECT * FROM test_user WHERE user_id = NEW.user_id
)
UPDATE test_username
SET money_counter = money_counter + 1,
total_revenue = total_revenue + cte.total_revenue
FROM cte
WHERE test_username.username = cte.username;

Oracle 11g - MERGE and error ORA-30926: unable to get a stable set of rows in the source tables

I have read lots of posts related to the Oracle (11g) error ORA-30926, and I've checked Oracle's documentation on the proper use of the merge statement.
Based on previous threads, I've changed my code to specify a distinct value in the using clause and that is the value I compare in the ON clause. But I still get the ORA-30926 error.
I've also tested the subquery in the USING clause and it returns data without any problem. I've created a temporary table containing only data that meets conditions in the WHERE clause of the USING statement and tried to run that and I still get the error. Both tables have data in them also.
I hope someone can spot something in my code that is incorrect or give me any recommendations on testing.
BEGIN
MERGE
INTO persons myTarget
USING (
select
distinct(USERID),
GIVENNAME,
INITIALS,
SN,
GENERATIONQUALIFIER,
TITLE,
DISPLAYNAME,
TELEPHONENUMBER,
FACSIMILETELEPHONENUMBER,
MOBILE,
OTHERTELEPHONE
from person_updates
WHERE
SN IS NOT NULL
AND LENGTH(SN) < 20
AND SUBSTR(USERID,0,2) IN (SELECT PLACEID FROM code_table)
AND (LENGTH(USERID) = 8 OR LENGTH(USERID) = 10)
) mySource
ON (myTarget.userid = mySource.USERID)
WHEN MATCHED THEN
UPDATE SET myTarget.first_name = UPPER(mySource.GIVENNAME),
myTarget.last_name = UPPER(mySource.SN),
myTarget.generation = UPPER(mySource.GENERATIONQUALIFIER),
myTarget.title = UPPER(mySource.TITLE),
myTarget.display_name = UPPER(mySource.DISPLAYNAME),
myTarget.phone_num = UPPER(mySource.TELEPHONENUMBER),
myTarget.fax_num = UPPER(mySource.FACSIMILETELEPHONENUMBER),
myTarget.mobile_num = UPPER(mySource.MOBILE),
myTarget.dsn_phone = UPPER(mySource.OTHERTELEPHONE);
END;
As correctly told by #shrek using distinct will give you distinct rows across combination of all the columns you have selected. I have used row_number analytical function to get distinct rows only based on userid.
Query:
BEGIN
MERGE
INTO persons myTarget
USING (
select * from(
select
row_number() over(partition by userid order by null) as rn,
USERID,
GIVENNAME,
INITIALS,
SN,
GENERATIONQUALIFIER,
TITLE,
DISPLAYNAME,
EMPLOYEETYPE,
TELEPHONENUMBER,
FACSIMILETELEPHONENUMBER,
MOBILE,
OTHERTELEPHONE
from person_updates
WHERE
SN IS NOT NULL
AND LENGTH(SN) < 20
AND SUBSTR(USERID,0,2) IN (SELECT PLACEID FROM code_table)
AND (LENGTH(USERID) = 8 OR LENGTH(USERID) = 10)) where rn = 1
) mySource
ON (myTarget.userid = mySource.USERID)
WHEN MATCHED THEN
UPDATE SET myTarget.first_name = UPPER(mySource.GIVENNAME),
myTarget.last_name = UPPER(mySource.SN),
myTarget.generation = UPPER(mySource.GENERATIONQUALIFIER),
myTarget.title = UPPER(mySource.TITLE),
myTarget.display_name = UPPER(mySource.DISPLAYNAME),
myTarget.dod_emp_type = UPPER(mySource.EMPLOYEETYPE),
myTarget.phone_num = UPPER(mySource.TELEPHONENUMBER),
myTarget.fax_num = UPPER(mySource.FACSIMILETELEPHONENUMBER),
myTarget.mobile_num = UPPER(mySource.MOBILE),
myTarget.dsn_phone = UPPER(mySource.OTHERTELEPHONE);
END;
Hope this will help.

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
);

ORA-00905: missing keyword error in case after where clause

I have the following query which is giving error ORA-00905: missing keyword. I've not been able to find the syntax despite continuous efforts for last few hours. Please help.
SELECT a.DOCUMENT_CATEGORY,
a.template_id,
a.category_id,
a.REVIEW_CATEGORY,
a.WITH_BIDS,
a.WITH_FINAL_DOCUMENTS,
b.divn_id,
b.deptt_id,
a.vdr_id,
C.DEPARTMENT,
a.TEMPLATE_TITLE
FROM DCTM_VDR_REF_DTLS a, DCTM_VDR_REF_MASTER b, VW_DIVN_DIR c
WHERE b.DIVN_ID = c.DIVN_CODE
AND b.DEPTT_ID = c.SECTN_CODE
AND a.vdr_id = b.vdr_id
AND (b.REFERENCE_NUMBER, b.APPROVED_ON) IN
( SELECT MAX (REFERENCE_NUMBER), MAX (APPROVED_ON)
FROM DCTM_VDR_REF_MASTER
WHERE REFERENCE_NUMBER =
(SELECT DISTINCT
NVL (TRIM (MR_NUMBER), TRIM (TENDER_NO))
FROM EILEDMS.EIL_DOCUMENT_SV#EDMS_DBLINK
WHERE object_name =
'A307-0IC-JA-MR-7960-1030-157-FOA'
AND r_object_type =
'eil_foa_order_pr_doc'
AND ( title = 'FOA'
OR title = 'DRAFT FOA'))
AND APPROVED_ON IS NOT NULL
GROUP BY DIVN_ID, DEPTT_ID)
AND REVIEW_CATEGORY <> 'Delete Category'
AND (CASE (SELECT IS_SCHEDULE_LOCKED
FROM DCTM_VENDOR_SCHEDULE
WHERE SCH_ID = 359)
WHEN 0
THEN
1
WHEN 1
THEN
(a.template_id || '-' || a.category_id) IN
(SELECT template_id || '-' || category_id
FROM DCTM_VENDOR_SCH_UNLOCK_DTLS
WHERE APPROVAL = 'Y'
AND APPROVAL_UPTO >= SYSDATE
AND CONSUMED = 0
AND sch_ID = 359)
END) = 1
ORDER BY c.DEPARTMENT ASC,
a.TEMPLATE_ID,
a.SORT_ORDER,
a.DOCUMENT_CATEGORY ASC
Can't we use IN clause inside a THEN statement?
Now that you've edited your question, it looks like you are simply trying to look up category_id and template_id in DCTM_VENDOR_SCH_UNLOCK_DTLS. Does the following work for you?
then
(
SELECT COUNT(*) -- 1 if found, 0 otherwise
FROM DCTM_VENDOR_SCH_UNLOCK_DTLS
WHERE APPROVAL = 'Y'
AND APPROVAL_UPTO >= SYSDATE
AND CONSUMED = 0
AND sch_ID = 359
AND template_id = a.template_id
AND category_id = a.category_id
AND rownum = 1
)
This is not actually about an IN clause after WHERE being allowed or not. The expression
a.category_id IN (SELECT ...)
evaluates to TRUE or FALSE. Your statement
a.template_id || '-' || a.category_id IN (SELECT ...)
tries to concatenate that TRUE or FALSE with a.template_id and a minus sign. This is not possible, as there is no boolean type in Oracle SQL. Think it over what you actually want to concatenate.
EDIT: Now that you set parentheses, you compare a string with another string resulting from a select statement. Fine so far. But still: All this evaluates to a boolean, not a number. Your first then results in a number (1), your second in a boolean (TRUE or FALSE). Oracle SQL has no boolean type, so your expression makes no sense to the parser and you get a syntax error.