(Already solved with a second solution, but I wonder why the first idea does not work).
I have a table with FID, Geom (Point-data), orientation and so on. I want to update the Orientation based on the coordinates, like "set orientation = 99 where X = something and Y = something"
I have this:
UPDATE WW_POINT
SET
ORIENTATION = 99.9
WHERE
F_CLASS_ID_ATTR = 77
AND GEOM.SDO_POINT.X = 2695056.511
AND GEOM.SDO_POINT.Y = 1279718.364;
The result is:
Error starting at line : 1 in command -
UPDATE WW_POINT
SET
ORIENTATION = 99.9
WHERE
F_CLASS_ID_ATTR = 77 -- haltunsgverbindung
AND GEOM.SDO_POINT.X = 2695056.511
AND GEOM.SDO_POINT.Y = 1279718.364
Error at Command Line : 7 Column : 12
Error report -
SQL Error: ORA-00904: "GEOM"."SDO_POINT"."Y": invalid identifier
00904. 00000 - "%s: invalid identifier"
*Cause:
*Action:
A simple select returns X and Y as expected:
SELECT
X.GEOM.SDO_POINT.X
, X.GEOM.SDO_POINT.Y
FROM
WW_POINT X
So the question is: What is wrong here?
My second solution with SDO_EQUAL seem to work fine:
UPDATE WW_POINT
SET
ORIENTATION = 389.608
WHERE
F_CLASS_ID_ATTR = 77 -- haltunsgverbindung
AND SDO_EQUAL (
GEOM
, MDSYS.SDO_GEOMETRY (
2001
, 2056
, SDO_POINT_TYPE (
2695056.511
, 1279718.364
, NULL
)
, NULL
, NULL
)
) = 'TRUE';
Comparing both of your queries: the second one (working) has a form <table alias>.<column name>.<attr>.<attr>, but the first one is <column name>.<attr>.<attr>.
From the documentation:
t_alias
Specify a correlation name, which is an alias for the table, view, materialized view, or subquery for evaluating the query. This alias is required if the select list references any object type attributes or object type methods.
Given this sample table:
create table t (p)
as
select
SDO_GEOMETRY (
2001, 2056
, SDO_POINT_TYPE (1, 1, NULL)
, NULL, NULL
)
from dual
A query without table alias fails:
select t.p.sdo_point.x
from t
where t.p.sdo_point.x = 1
ORA-00904: "T"."P"."SDO_POINT"."X": invalid identifier
And the query with table alias works as expected allowing attribute access in the select list as well as in the where clause:
select t.p.sdo_point.x
from t t
where t.p.sdo_point.x = 1
P.SDO_POINT.X
1
db<>fiddle here
Related
There is a table called USER_SETUP. This table has a column called EMPLOYEE_ID which is originally VARCHAR. I created a view to convert the VARCHAR data type to NUMBER. I used TO_DECIMAL("EMPLOYEE_ID",12,0) AS "EMPLOYEE_ID" (because when I use TO_INTEGER("EMPLOYEE_ID") AS "EMPLOYEE_ID", I am getting exception in view).
The view is created using nested SQL statement [e.g: select * from (select * from table)] The view is generating correct output with correct data. In the view I created 2 columns using CASE function which is based on the SQL code inside. Refer the code of SQL View below
Main View code:
CREATE VIEW ECLINIC_KNG.VIEW_USER_SETUP AS
SELECT
USER_ID,
EMPLOYEE_ID,
CASE
WHEN EMPLOYEE_ID < 50000 THEN 'Kuwaiti'
WHEN EMPLOYEE_ID >= 50000 AND LENGTH(EMPLOYEE_ID) <=6 THEN 'Non-Kuwaiti'
ELSE 'NOT KNG'
END AS "KWT_NKWT",
CASE
WHEN LENGTH(EMPLOYEE_ID) <=6 THEN 'KNG'
WHEN LENGTH(EMPLOYEE_ID)=12 THEN 'MOH'
ELSE 'Undefined'
END AS "KNG_MOH",
USER_NAME,
ACTIVE_DATE,
DEACTIVE_DATE,
ACTIVE_STATUS,
USER_CODE,
USER_LABEL,
USER_PASSWORD,
USER_TYPE,
OFFICE_ID,
USER_DESIG,
USER_LICENSE,
USER_SIGN,
CLIMIT_DAYS,
EDIT_BILL_SERVICE,
PASSWORDGROUP_ID,
USERLABEL_AR,
DISCOUNT_APPROVAL,
DISCOUNT_TYPE,
DISCOUNT_MAX,
BILL_CANCELLATION,
BILL_CANCELLATION_DAYS,
DOCTOR_ID
FROM
(SELECT
"USER_ID",
--TO_INTEGER("EMPLOYEE_ID") AS "EMPLOYEE_ID" ,
TO_DECIMAL("EMPLOYEE_ID",12,0) AS "EMPLOYEE_ID",
"USER_NAME",
"ACTIVE_DATE",
"DEACTIVE_DATE",
"ACTIVE_STATUS",
"USER_CODE",
"USER_LABEL",
"USER_PASSWORD",
"USER_TYPE",
"OFFICE_ID",
"USER_DESIG",
"USER_LICENSE",
"USER_SIGN",
"CLIMIT_DAYS",
"EDIT_BILL_SERVICE",
"PASSWORDGROUP_ID",
"USERLABEL_AR",
"DISCOUNT_APPROVAL",
"DISCOUNT_TYPE",
"DISCOUNT_MAX",
"BILL_CANCELLATION",
"BILL_CANCELLATION_DAYS",
"DOCTOR_ID"
FROM
"ECLINIC_KNG"."USER_SETUP"
WHERE
"USER_SETUP"."EMPLOYEE_ID" not in ('undefined', '299450','34(NEW RECRUIT)', 'army', 'MOH
Nurse','NEW RECRUITMENT 380','1111111','0')
AND
"USER_SETUP"."EMPLOYEE_ID" LIKE_REGEXPR '[0-9]'
ORDER BY
"USER_ID");
The 2 new columns created in the view
CASE
WHEN EMPLOYEE_ID < 50000 THEN 'Kuwaiti'
WHEN EMPLOYEE_ID >= 50000 AND LENGTH(EMPLOYEE_ID) <=6 THEN 'Non-Kuwaiti'
ELSE 'NOT KNG'
END AS "KWT_NKWT",
CASE
WHEN LENGTH(EMPLOYEE_ID) <=6 THEN 'KNG'
WHEN LENGTH(EMPLOYEE_ID)=12 THEN 'MOH'
ELSE 'Undefined'
END AS "KNG_MOH"
The issue is when I am filtering specific data using these 2 SQL scripts
--(1)
SELECT * FROM VIEW_USER_SETUP vus WHERE vus.KNG_MOH LIKE 'MOH'; --Issue
--(2)
SELECT * FROM VIEW_USER_SETUP vus WHERE vus.KWT_NKWT LIKE 'NOT KNG'; --Issue
The first issue the output is as follows:
SAP DBTech JDBC: [339]: invalid number: exception 71000339: SQL Error
The second issue the output is a follows:
invalid number: [6930] attribute value is not a number;exception 70006930: attribute value is not a number
To temporary solve 1, I use the below code:
SELECT * FROM VIEW_USER_SETUP vus WHERE vus.KNG_MOH NOT LIKE 'KNG';
Similarly to temporarily solve 2, I use the same above code because of the realtion.
I believe the issue is originating from the two CASE expressions created in the main view code, because when I use other filters from view there is no issue.
What is the correction required in the Main View code such that, when I execute --(1) and --(2), I get the required output?
Require help.
I am new to Oracle SQL Developer, and today while running this
select r.id, r.date, it.group, it.comment, it.item, it.remark, r.summary,
substr (it.remark, instr(it.remark,'ABC')+8,7 ) as label1,
cast(substr (it.remark, instr(it.remark,'-')+1,3 ) as integer) as label2
from it_table it
inner join sp_table sp on sp.id = substr (it.remark, instr(it.remark,'ABC')+8,7 ) and sp.label_id = cast(substr (it.remark, instr(it.remark,'-')+1,3 ) as integer)
inner join sq_table sq on sq.id = sp.id
where it.date > '01-jan-2020' and it.remark like '%ABC%' and it.group= 'O'
order by sp.id, it.id;
it caught the error:
ORA-01722: invalid number
01722. 00000 - "invalid number"
*Cause: The specified number was invalid.
*Action: Specify a valid number.
I think the problem lies with the extraction as in row 3 (cast(substr (it.remark, instr(it.remark,'-')+1,3 ) as integer)), where I need to convert a string into a number using cast.
According to doc, the error occurs when an attempt is made to convert a character string into a number, and the string cannot be converted into a valid number.
So, I tried replacing:
cast(substr (it.remark, instr(it.remark,'-')+1,3 ) as integer)
with
to_number(substr (it.remark, instr(it.remark,'-')+1,3 ))
and even tried to_char but didn't work. However, the original script seems to work fine in sandbox database. I am wondering why this is happening. Any help is greatly appreciated.
Update:
Sample data it:
ID DATE NAME GROUP REMARK COMMENT ...
100 20-10-08 AABC X ACS LOCATION 1 - ABC IDD x105213-1
101 20-10-08 AxB Y MN LOCATION 8 - ABC IDD x105244-2
...
Sample data sp:
ID DATE NAME GROUP label_id
105213 20-10-08 AABC X 1
105244 20-10-08 AxB Y 2
...
It turns out that the error was caused by having 2 - in remark which lead to ambiguity and I just need the second one.
New question then:
How do I extract the last - in the value to join with another value in the other column?
Use cast with default null on conversion error to avoid exception and investigate the cause of the failed conversion.
Example
with dt as
(select '001' remark from dual union all
select ' 2' from dual union all
select 'OMG' from dual)
select substr(remark,1,3) txt,
cast (substr(remark,1,3) as INT default null on conversion error) num
from dt;
TXT NUM
--- ----------
001 1
2 2
OMG
First, I execute the following SQL statements.
drop table names;
drop table ages;
create table names (id number, name varchar2(20));
insert into names values (1, 'Harry');
insert into names values (2, 'Sally');
insert into names values (3, 'Barry');
create table ages (id number, age number);
insert into ages values (1, 25);
insert into ages values (2, 30);
insert into ages values (3, 35);
select * from names;
select * from ages;
As a result, the following tables are created.
ID NAME
---------- ----------
1 Harry
2 Sally
3 Barry
ID AGE
---------- ----------
1 25
2 30
3 35
Now, I want to update increment the age of Sally by 1, i.e. set it to 31. The following query works fine.
update ages set age = age + 1 where id = (select id from names where name = 'Sally');
select * from ages;
The table now looks like this.
ID AGE
---------- ----------
1 25
2 31
3 35
I want to know if there is a way it can be done by joins. For example, I tried the following queries but they fail.
SQL> update ages set age = age + 1 from ages, names where ages.id = names.id and names.name = 'Sally';
update ages set age = age + 1 from ages, names where ages.id = names.id and names.name = 'Sally'
*
ERROR at line 1:
ORA-00933: SQL command not properly ended
SQL> update ages set age = age + 1 from names join ages on ages.id = names.id where names.name = 'Sally';
update ages set age = age + 1 from names join ages on ages.id = names.id where names.name = 'Sally'
*
ERROR at line 1:
ORA-00933: SQL command not properly ended
The syntax of the UPDATE statement is:
http://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10007.htm
where dml_table_expression_clause is:
Please pay attention on ( subquery ) part of the above syntax.
The subquery is a feature that allows to perform an update of joins.
In the most simplest form it can be:
UPDATE (
subquery-with-a-join
)
SET cola=colb
Before update a join, you must know restrictions listed here:
https://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_8004.htm
The view must not contain any of the following constructs:
A set operator
A DISTINCT operator
An aggregate or analytic function
A GROUP BY, ORDER BY, MODEL, CONNECT BY, or START WITH clause
A collection expression in a SELECT list
A subquery in a SELECT list
A subquery designated WITH READ ONLY
Joins, with some exceptions, as documented in Oracle Database Administrator's Guide
and also common rules related to updatable views - here (section: Updating a Join View):
http://docs.oracle.com/cd/B19306_01/server.102/b14231/views.htm#sthref3055
All updatable columns of a join view must map to columns of a
key-preserved table. See "Key-Preserved Tables" for a discussion of
key-preserved tables. If the view is defined with the WITH CHECK
OPTION clause, then all join columns and all columns of repeated
tables are not updatable.
We can first create a subquery with a join:
SELECT age
FROM ages a
JOIN names m ON a.id = m.id
WHERE m.name = 'Sally'
This query simply returns the following result:
AGE
----------
30
and now we can try to update our query:
UPDATE (
SELECT age
FROM ages a
JOIN names m ON a.id = m.id
WHERE m.name = 'Sally'
)
SET age = age + 1;
but we get an error:
SQL Error: ORA-01779:cannot modify a column which maps to a non key-preserved table
This error means, that one of the above restriction is not meet (key-preserved table).
However if we add primary keys to our tables:
alter table names add primary key( id );
alter table ages add primary key( id );
then now the update works without any error and a final outcome is:
select * from ages;
ID AGE
---------- ----------
1 25
2 31
3 35
DB: Oracle 11g
Query:
SELECT CASE
WHEN rs.OPTION = '3'
THEN
(SELECT COUNT(DISTINCT ex.EXTS) AS TMPCOL0
FROM CRSIDM.SUB_OPTS ex
INNER JOIN CRSIDM.SUB_OPTS_GRP cg
ON cg.GROUP_ID = ex.GRP_ID
)
ELSE
(SELECT COUNT(DISTINCT ex.EXTS) AS TMPCOL0
FROM CRSIDM.SUB_OPTS ex
INNER JOIN CRSIDM.SUB_OPTS_POL cg
ON cg.GROUP_ID = ex.GRP_ID
)
END AS PROPTS
FROM PR_OPTS
I am getting error 'expected CHAR got NUMBER', here EXTS,GROUP_ID & GRP_ID are numeric. Then how there is a chance of expecting CHAR?
Generally when Oracle compares different datatypes such as a NUMBER with a CHARACTER, implicit conversion kicks in and all is well (provided the data can be converted.) For example, if you have a function that expects a CHARACTER value but you pass it a NUMBER, all is well - Oracle simply converts the NUMBER to character.
E.g. a function like this:
create or replace function get_something(p_id VARCHAR2) return number ...
works if you call it with this:
get_dno(10);
or this:
get_dno('10');
and in SQL:
select * from some_table where numeric_column = '10' -- no problem.
A popular place where you see this kind of error is with the return values in CASE statements. For instance, you'll get that error if you have something like this:
SQL> SELECT CASE WHEN 1 = 1 THEN '1' ELSE 2 END
2 FROM dual
3 ;
SELECT CASE WHEN 1 = 1 THEN '1' ELSE 2 END
*
ERROR at line 1:
ORA-00932: inconsistent datatypes: expected CHAR got NUMBER
(The datatype from the first WHEN clause is what it expects in the other WHEN/ELSE clauses that follow.)
But in your case the WHEN and THEN both return counts - the datatypes are consistent. So, I think you have a red-herring in there.
As Alex mentioned above, OPTION is a keyword and if you try and create a table with that as a column name, Oracle disagrees:
SQL> create table dummy
2 (option varchar2(10)
3 );
(option varchar2(10)
*
ERROR at line 2:
ORA-00904: : invalid identifier
This works:
SQL> create table dummy
2 (option_col varchar2(10)
3 );
Table created.
or you could do it with quotes:
SQL> create table dummy
2 ("option" varchar2(10));
Table created.
But now you're in a world of hurt - you need quotes from now on:
SQL> select option from dummy;
select option from dummy
*
ERROR at line 1:
ORA-00936: missing expression
SQL> select d.option from dummy d;
select d.option from dummy d
*
ERROR at line 1:
ORA-01747: invalid user.table.column, table.column, or column specification
With quotes:
SQL> select d."option" from dummy d;
no rows selected
So, if your query is really giving you "expected CHAR, got NUMBER", it looks to me like something is off.
Essentially, it means some of the fields you are using aren't compatible with each other. It's basically a "type mismatch". Just check to see if any types of CHAR are being used with types of NUMBER. Then you can either switch the type of one, or simply use a conversion as part of the query.
The issue is OPTION = '3', the quotation marks indicate that you're looking for a string containing the solitary character 3.
Try this instead:
SELECT CASE
WHEN rs.OPTION = 3
THEN
(SELECT COUNT(DISTINCT ex.EXTS) AS TMPCOL0
FROM CRSIDM.SUB_OPTS ex
INNER JOIN CRSIDM.SUB_OPTS_GRP cg
ON cg.GROUP_ID = ex.GRP_ID)
ELSE
(SELECT COUNT(DISTINCT ex.EXTS) AS TMPCOL0
FROM CRSIDM.SUB_OPTS ex
INNER JOIN CRSIDM.SUB_OPTS_POL cg
ON cg.GROUP_ID = ex.GRP_ID)
END AS PROPTS
FROM PR_OPTS
Here is my sample table:
SELECT p.id, p.loc, t.x, t.y,t.id vertex_num
FROM my_test p, TABLE(sdo_util.getvertices(p.geom))t
where p.id in (23, 24);
id loc x y vetex_num
--------------------------------
23 RECTANGLE 1 10 1
23 RECTANGLE 15 20 2
24 LINE 1 10 1
24 LINE 15 10 2
It seems the boundaries of the LINE interacts with the boundary of RECTANGLE which should return TRUE for SDO_ON function,
SELECT A.loc , b.loc
FROM my_test A, my_test b
WHERE SDO_ON(A.geom, B.geom) = 'TRUE';
but it results none , Thought it shows result for ANYINTERACT. I've tried with SDO_RELATE with 'mask= on' parameter, but no rows returned.
Any help is appreciated. Thanks:)
I myself found at last!!
The problem is with the SRID, (my indexed and tabular SRID was 8307)
I've change the SRID whcih supports the wkt as PROJECTED cordinates.
eg. 32774, 90112,
I used 32774 and queried the same above and now the i got result like expected:
LOC LOC_1
----------
LINE RECT
But I still do not understand why does it not working with srid 8307.