Oracle: Invalid identifier - oracle

Can anyone explain to me why I get a 00904 error when I run the following
SELECT "OASM"."DT_GROUPEPG".GROUPEPGID,
"OASM"."DT_GROUPEPG".GROUPID,
"OASM"."DT_GROUPEPG".EPGID,
"OASM"."DT_GROUPEPG".ZAPID,
"OASM"."LU_EPG".LASTREADTIME,
"OASM"."LU_EPG".SERVICE_NAME,
"OASM"."LU_EPG".SOURCE_ID,
"OASM"."LU_EPG".ONID,
"OASM"."LU_EPG".TSID,
"OASM"."LU_EPG".SID,
"OASM"."LU_EPG".TYPE_ID,
"OASM"."LU_EPG".OPERATOR_ID,
"OASM"."LU_EPG".URL
FROM "OASM"."DT_GROUPEPG"
INNER JOIN "OASM"."LU_EPG"
ON "OASM"."DT_GROUPEPG".EPGID = "OASM"."LU_EPG".EPGID
ORDER BY LastReadTime;
I'm still new to Oracle, and was of the impression that, because Oracle executes blocks of statements, and not line by line, that doing this kind of query would be valid? The error currently fires at the OPERATOR_ID line, but removing/commenting it out just moves the erro up a line, until all the LU_EPG table references are removed

You can't (and don't need to) specify the schema name when referring to the columns. Also, I recommend you use table aliases (e.g. a and b in the example below):
SELECT a.GROUPEPGID,
a.GROUPID,
a.EPGID,
a.ZAPID,
b.LASTREADTIME,
b.SERVICE_NAME,
b.SOURCE_ID,
b.ONID,
b.TSID,
b.SID,
b.TYPE_ID,
b.OPERATOR_ID,
b.URL
FROM "OASM"."DT_GROUPEPG" a
INNER JOIN "OASM"."LU_EPG" b
ON a.EPGID = b.EPGID
ORDER BY b.LastReadTime;

Related

Group by result of custom function HIBERNATE

Hi I have some problem with group by a result of a custom function in Hibernate.
The query looks like:
#Query("SELECT NEW ReportDay(" +
"FUNCTION('atTimezone', p.startDate, :timezone), "
"SUM(p.energy)) " +
"FROM Process p GROUP BY FUNCTION('atTimezone', p.startDate, :timezone)")
The error thrown is that p.startDate must appear in groupBy clause or in an aggregate function. But the custom function is in the group by clause.
Any ideas? The custom function is this:
registerFunction("atTimezone", new SQLFunctionTemplate(StandardBasicTypes.TIMESTAMP,"date_trunc('day', (cast(?1 as timestamp) AT TIME ZONE cast(?2 as varchar)))"));
and is trying to get the date trunc to day in a specific timezone.
many thanks!
The problem here is that in SQL the two timezone parameters will be separate parameters and your database (at least PostgreSQL) won't be able to recognize that these are actually the same value.
In order to work around this issue, you can give your function an alias which can be referenced in the GROUP BY clause. Select aliases are not allowed in the GROUP BY clause according to ANSI SQL and JPQL. Some database dialects such as PostgreSQL, MySQL and H2 however do support it and since Hibernate 5.4.10 aliases in the group by clause are propagated to the SQL query for these supporting dialects (HHH-9301).
So instead of:
SELECT FUNCTION('atTimezone', p.startDate, :timezone), SUM(p.energy))
FROM Process p GROUP BY FUNCTION('atTimezone', p.startDate, :timezone)
You could do:
SELECT FUNCTION('atTimezone', p.startDate, :timezone) AS d, SUM(p.energy))
FROM Process p GROUP BY d
How this works together with object projection (NEW ReportDay(...)) is not known to me, but this should at least get you started.

Getting invalid identifier SQL query

I am trying to execute next query:
MERGE INTO NOTIFICATION_OBJS p
USING (SELECT
:fcsNotif_id as doc_id,
:OKPD2_code as OKPD2_code,
:OKPD2_name as OKPD2_name,
:quantity_value as quantity,
:purchaseObject_price as price
FROM DUAL
) v
ON (p.doc_id=v.doc_id)
WHEN MATCHED THEN
UPDATE SET
p.OKPD2_code = v.OKPD2_code,
p.OKPD2_name = v.OKPD2_name,
p.quantity_value = v.quantity_value,
p.price = v.price
WHEN NOT MATCHED THEN
INSERT (p.doc_id, p.OKPD2_code, p.OKPD2_name, p.quantity_value, p.price)
VALUES(v.doc_id, v.OKPD2_code, v.OKPD2_name, v.quantity_value, v.price)
I am sending to bind method next dictionary:
{'OKPD2_code': '62.02.30.000', 'OKPD2_name': 'some text', 'purchaseObject_price': '20466982.25', 'quantity_value': '1', 'fcsNotif_id': '18941152'}
But I am getting error:
ORA-00904: "P"."OKPD2_NAME": invalid identifier
All other query with binding are working. Please help me to find error.
There's no OKPD2_NAME column in NOTIFICATION_OBJS table.
If you used double quotes while creating that table (and its columns), you should
recreate the table without double quotes, or
reference the table (and its columns that use mixed case) using double quotes again, specifying case EXACTLY as it was while creating the table
[EDIT, after the screenshot has been uploaded]
Column name really is created using mixed case, so you'll have to reference it exactly like that: "OKPD2_name" paying attention to double quotes and mixed case.
If you use "okpd2_name" or "okPD2_NAME" or anything but "OKPD2_name", it won't work. Once again: get rid of double quotes.

Why do I get "ORA-00932: inconsistent datatypes: expected - got -" when using COLLECT() in a prepared statement?

I am using this query with the Perl DBI:
SELECT c.change_id
, COLLECT(t.tag) AS the_tags
FROM changes c
LEFT JOIN tags t ON c.change_id = t.change_id
WHERE c.project = ?
GROUP BY c.change_id
The DBI uses OCI to prepare this statement, bind the value I pass, and get the results. But Oracle, for some reason, does not like it. The error output is:
ORA-00932: inconsistent datatypes: expected - got - (DBD ERROR: error possibly near <*> indicator at char 41 in '
SELECT c.change_id
, <*>COLLECT(t.tag) AS the_tags
FROM changes c
LEFT JOIN tags t ON c.change_id = t.change_id
WHERE c.project = :p1
GROUP BY c.change_id
'
Not very informative. However, I can make this error go away not only by changing the call to COLLECT() also by replacing the placeholder with the actual value:
SELECT c.change_id
, COLLECT(t.tag) AS the_tags
FROM changes c
LEFT JOIN tags t ON c.change_id = t.change_id
WHERE c.project = 'tryoracle'
GROUP BY c.change_id
That version works perfectly. Why doesn't Oracle like the prepared statement with the COLLECT()?
In case it's any help, here is a trace of the OCI-related calls extracted via ora_verbose = 6 (h/t #bohica).
Finally got a solution to this issue, thanks to some digging by a user. The problem was not with the placeholder; why it worked without the placeholder on the VirtualBox image I have no idea. No, the issue was with the COLLECT(). Seems that both the values being collected need to be cast to a specific type, and the resulting array also needs to be cast to a pre-defined array data type. Just so happens that my code has a custom array type:
CREATE TYPE sqitch_array AS varray(1024) OF VARCHAR2(512);
So I'm able to get the query to work by casting the COLLECT() like so:
CAST(COLLECT(CAST(t.tags as VARCHAR2(512))) AS sqitch_array)

SQL query to return a row even if not found, with at least in parameters

I would like to write a SQL query (oracle)
to know if an operation (identified by ope.ope_operationid)
has at least an operation of a certain type (opt.opt_id), and if it does not, to show that it doesn't in the results.
For example, I have this operation LAA351BP (I know this one exists in base),
and I would like to know if it has at least an operation type which id is 3781.
If it has, print everything, if it hasn't, print the operationid
and something like 'not found' next to it
Is nvl the function to use ? It seems I can't get it to work properly.
SELECT DISTINCT ope.ope_operationid,
ser.ser_code,
opt.opt_code,
ost.ost_code
FROM od_operation ope,
od_service_type ser,
od_operation_type opt,
od_status_type ost,
od_equipment_type eqt,
WHERE ope.ser_id = ser.ser_id
AND opt.opt_id = ope.opt_id
AND ost.ost_id = ope.ost_id
AND ope.opt_id = 3781
AND ope.ope_operationid = 'LAA351BP'
Thanks
You should start using standard JOIN syntax. Apart from being more readable (at least in my opinion) it also protects you from accidental cartesian joins if you forget the actual join condition in the WHERE clause. Plus it is portable across nearly all DBMS as opposed to the clunky (+) syntax used by Oracle (which also has some limitations that the JOIN syntax does not have)
Here is the query re-written using explicit (instead of implicit) joins:
SELECT DISTINCT ope.ope_operationid,
ser.ser_code,
opt.opt_code,
ost.ost_code
FROM od_operation ope,
LEFT JOIN od_service_type ser ON ope.ser_id = ser.ser_id
LEFT JOIN od_operation_type opt ON opt.opt_id = ope.opt_id
LEFT JOIN od_status_type ost ON ost.ost_id = ope.ost_id
LEFT JOIN od_equipment_type eqt ON ????????
WHERE ope.opt_id = 3781
AND ope.ope_operationid = 'LAA351BP'
Edit
The missing join condition on od_equipment_type is exactly the reason why the JOIN syntax is preferred. If the trailing comma in the original SQL is removed, the statement would create an unwanted cartesian join which might have a severe impact on the server if the involved tables are big.
With the JOIN syntax you will always get a syntax error which prevents you from such typos. Using implicit joins will only give you an error when you leave a comma in the FROM list, but never if you miss a join condition in the WHERE

Can't find the cause of a 'missing right parenthesis' error

I am having problems with a line of code. I am trying to create a count function for a view that I created. I have done this a bunch of different ways but below is the format that I have most recently used.
CREATE VIEW ERP_REPORT(EVENTNAME, DESCRIPTION, COUNT(RIDERS) AS
SELECT EVENTNAME, RACES.DESCRIPTION,
RIDERS_FIRSTNAME||' '||RTRIM(RIDERS_LASTNAME)
FROM EVENTS, RACES, PARTICIPATION, RIDERS
WHERE EVENTS.EVENTID = RACES.EVENTID
AND RACES.RACEID = PARTICIPATION.RACEID
AND RIDERS.RIDERID = PARTICIPATION.RIDERID
ORDER BY RIDERS.RIDERS_LASTNAME, EVENTNAME;
The error I am getting is ORA-00907: missing right parenthesis. The error is at the (COUNT(RIDERS) part of the code. Any ideas how I should tackle this?
The list of names in parentheses on line 1 should be the names of the view columns:
CREATE VIEW ERP_REPORT(EVENTNAME, DESCRIPTION, COUNT(RIDERS) AS ...
You can't create a column called "COUNT(RIDERS" or even "COUNT(RIDERS)" since a column name may not contain ( or ). This would work:
CREATE VIEW ERP_REPORT(EVENTNAME, DESCRIPTION, RIDER_FULL_NAME) AS ...
However it appears that you really do want a count of something, though I'm not sure of what. To do that the view definition would have to be something like:
CREATE VIEW ERP_REPORT(EVENTNAME, DESCRIPTION, RIDER_COUNT) AS
SELECT EVENTNAME, RACES.DESCRIPTION, COUNT(*)
FROM EVENTS, RACES, PARTICIPATION, RIDERS
WHERE EVENTS.EVENTID = RACES.EVENTID
AND RACES.RACEID = PARTICIPATION.RACEID
AND RIDERS.RIDERID = PARTICIPATION.RIDERID
GROUP BY EVENTNAME, DESCRIPTION;
(i.e. the COUNT function goes in the SELECT part, not in the list of column names).
As an aside, since you are presumably new to Oracle, I would suggest you start using the more modern ANSI join syntax to make your queries clearer:
...
FROM EVENTS
JOIN RACES ON RACES.EVENTID = EVENTS.EVENTID
JOIN PARTICIPATION ON PARTICIPATION.RACEID = RACES.RACEID
JOIN RIDERS ON RIDERS.RIDERID = PARTICIPATION.RIDERID
CREATE VIEW ERP_REPORT(EVENTNAME, DESCRIPTION, COUNT(RIDERS) AS
....
Should not it be:
CREATE VIEW ERP_REPORT(EVENTNAME, DESCRIPTION, COUNT(RIDERS)) AS
As the error message points out you are missing a closing bracket ). The bracket is opened here : 'ERP_REPORT(EVENTNAME' and is never closed.
you can't have brackets in column names unless you put quotation marks around. Try this:
CREATE VIEW ERP_REPORT(EVENTNAME, DESCRIPTION, "COUNT(RIDERS)") AS ...
or
CREATE VIEW ERP_REPORT(EVENTNAME, DESCRIPTION, COUNT_RIDERS) AS ...
For example:
SQL> CREATE OR REPLACE VIEW foo ("count(*)") AS SELECT COUNT(*) FROM dual;
View created
SQL> CREATE OR REPLACE VIEW foo (count_all) AS SELECT COUNT(*) FROM dual;
View created
As Tony points out there are actually several syntax errors in your statement. The missing bracket is just the first.
I find it useful to have an IDE which supports bracket matching, because it can be hard to walk back through the code and find which bracket lacks a mate. As it happens my choice is TextPad but just about anything which is more advanced than NotePad ought to be able to do this.

Resources