Oracle query to concat a column data having two rows into one - oracle

I have an Oracle column with "Long" datatype, as the column has the 4000 chars limit, we tend to insert data into two rows or more than that, now we want to display 2 rows of data into one, I tried but there are some of the other error like char to long and so on, could you please help.
Id, Series, Serialized
1 1 abc
1 1 def
3 2 gdf
Id, Series
1 1
1 1
3 2
Output
Id, Series, Serialized
1 1 abcdef
3 2 gdf
Here's the table scripts
CREATE TABLE "LOGMESSAGE"
( "ID" VARCHAR2(36 BYTE) NOT NULL ENABLE,
"SERIALIZEDMESSAGE" LONG,
"SERIES" NUMBER(10,0)
)
CREATE TABLE "LOGENTRY"
( "ID" VARCHAR2(36 BYTE) NOT NULL ENABLE
)
insert into "LOGMESSAGE" values(
'd8dcd593-af52-425a-8bf2-d93f78a601c6','{"name":"miogetadapter001.xml","type":"miogetadapterresponse","id":"56e125af-4202-44cb-bf90-58df03776793","time":"2021-10-05T06:27:04.8595987Z","source":"miochannelsource","adapter":"miotestadapter","channel":"miotestchannel","original":"<RESTTestResponse TestTimestamp=\"2021/10/05 11:57:05\">\r\n <Name>miotestadapter</Name>\r\n <IsActive>true</IsActive>\r\n <Description>Added during MIO install for confirmation test. Version=3.0.0.0</Description>\r\n <type>ChannelAdapterConfiguration</type>\r\n <AdapterConfigurationTypeName>FileAdapterConfiguration</AdapterConfigurationTypeName>\r\n <AdapterType>FileAdapter</AdapterType>\r\n <AdapterVersion>1</AdapterVersion>\r\n <AdapterKind>default</AdapterKind>\r\n <ContentFormat>Xml</ContentFormat>\r\n <ChannelSourceName>miochannelsource</ChannelSourceName>\r\n <MessageChannelName>miotestchannel</MessageChannelName>\r\n <MomConnectionName></MomConnectionName>\r\n <OutboundNameFormat>{messagename}</OutboundNameFormat>\r\n <InboundNameFormat>{messagename}</InboundNameFormat>\r\n <DoNotSend>false</DoNotSend>\r\n <DoNotSendOutbound>false</DoNotSendOutbound>\r\n <ShutdownMaxTime>15</ShutdownMaxTime>\r\n <IsXml>true</IsXml>\r\n <WakeUpInterval>-1</WakeUpInterval>\r\n <UserName></UserName>\r\n <Password></Password>\r\n <DomainName></DomainName>\r\n <VerifyUnique>true</VerifyUnique>\r\n <UniqueIncludesTimestamp>true</UniqueIncludesTimestamp>\r\n <UniqueCacheExpiration>0</UniqueCacheExpiration>\r\n <ClearOriginalContents>true</ClearOriginalContents>\r\n <BufferSettings>\r\n <Description></Description>\r\n <Kind>Persistent</Kind>\r\n <ConnectionName></ConnectionName>\r\n <ConnectionString>folder name=%AppData%</ConnectionString>\r\n <Interval>2000</Interval>\r\n <Expiration>-1</Expiration>\r\n <MaxCount>-1</MaxCount>\r\n </BufferSettings>\r\n <InProcessExpiration>120</InProcessExpiration>\r\n <InboundFilters />\r\n <OutboundFilters />\r\n <OutboundFailPlugin>LogAndDiscard</OutboundFailPlugin>\r\n <OutboundFailConfiguration>LogAndDiscard</OutboundFailConfiguration>\r\n <OutboundRetryInterval>15000</OutboundRetryInterval>\r\n <OutboundMaxRetries>5</OutboundMaxRetries>\r\n <SendMessageMaxRetries>10</SendMessageMaxRetries>\r\n <SendMessageRetryInterval>10000</SendMessageRetryInterval>\r\n <InboundUri>C:\\Program Files\\Opcenter Connect MOM\\Channel Adapter Host\\inbound</InboundUri>\r\n <OutboundUri>C:\\Program Files\\Opcenter Connect MOM\\Channel Adapter Host\\outbound</OutboundUri>\r\n <ErrorUri></ErrorUri>\r\n <InboundDriveToMap></InboundDriveToMap>\r\n <InboundFilenameFilter>*.*</InboundFilenameFilter>\r\n <OutboundDriveToMap></OutboundDriveToMap>\r\n <MaxReadRetries>10</MaxReadRetries>\r\n <RetryDelay>15000</RetryDelay>\r\n <DeleteInterval>15</DeleteInterval>\r\n <EncodingName>UTF-8</EncodingName>\r\n</RESTTestResponse>","contents":"<RESTTestResponse TestTimestamp=\"2021/10/05 11:57:05\">\r\n <Name>miotestadapter</Name>\r\n <IsActive>true</IsActive>\r\n <Description>Added during MIO install for confirmation test. Version=3.0.0.0</Description>\r\n <type>ChannelAdapterConfiguration</type>\r\n <AdapterConfigurationTypeName>FileAdapterConfiguration</AdapterConfigurationTypeName>\r\n <AdapterType>FileAdapter</AdapterType>\r\n <AdapterVersion>1</AdapterVersion>\r\n <AdapterKind>default</AdapterKind>\r\n <ContentFormat>Xml</ContentFormat>\r\n <ChannelSourceName>miochannelsource</ChannelSourceName>\r\n <MessageChannelName>miotestchannel</MessageChannelName>\r\n <MomConnectionName></MomConnectionName>\r\n <OutboundNameFormat>{messagename}</OutboundNameFormat>\r\n <InboundNameFormat>{messagename}</InboundNameFormat>\r\n <DoNotSend>false</DoNotSend>\r\n <DoNotSendOutbound>false</DoNotSendOutbound>\r\n <ShutdownMaxTime>15</ShutdownMaxTime>\r\n <IsXml>true</IsXml>\r\n <WakeUpInterval>-1</WakeUpInterval>\r\n <UserName></UserName>\r\n <Password></Password>\r\n <DomainName></DomainName>\r\n <VerifyUnique>true</VerifyUniqu',
0)
insert into "LOGMESSAGE" values(
'd8dcd593-af52-425a-8bf2-d93f78a601c6','e>\r\n <UniqueIncludesTimestamp>true</UniqueIncludesTimestamp>\r\n <UniqueCacheExpiration>0</UniqueCacheExpiration>\r\n <ClearOriginalContents>true</ClearOriginalContents>\r\n <BufferSettings>\r\n <Description></Description>\r\n <Kind>Persistent</Kind>\r\n <ConnectionName></ConnectionName>\r\n <ConnectionString>folder name=%AppData%</ConnectionString>\r\n <Interval>2000</Interval>\r\n <Expiration>-1</Expiration>\r\n <MaxCount>-1</MaxCount>\r\n </BufferSettings>\r\n <InProcessExpiration>120</InProcessExpiration>\r\n <InboundFilters />\r\n <OutboundFilters />\r\n <OutboundFailPlugin>LogAndDiscard</OutboundFailPlugin>\r\n <OutboundFailConfiguration>LogAndDiscard</OutboundFailConfiguration>\r\n <OutboundRetryInterval>15000</OutboundRetryInterval>\r\n <OutboundMaxRetries>5</OutboundMaxRetries>\r\n <SendMessageMaxRetries>10</SendMessageMaxRetries>\r\n <SendMessageRetryInterval>10000</SendMessageRetryInterval>\r\n <InboundUri>C:\\Program Files\\Opcenter Connect MOM\\Channel Adapter Host\\inbound</InboundUri>\r\n <OutboundUri>C:\\Program Files\\Opcenter Connect MOM\\Channel Adapter Host\\outbound</OutboundUri>\r\n <ErrorUri></ErrorUri>\r\n <InboundDriveToMap></InboundDriveToMap>\r\n <InboundFilenameFilter>*.*</InboundFilenameFilter>\r\n <OutboundDriveToMap></OutboundDriveToMap>\r\n <MaxReadRetries>10</MaxReadRetries>\r\n <RetryDelay>15000</RetryDelay>\r\n <DeleteInterval>15</DeleteInterval>\r\n <EncodingName>UTF-8</EncodingName>\r\n</RESTTestResponse>","empty":false,"contentsformat":"Xml","contentshash":"64882DB2ED9382F3075C94A0657C3034","hash":"135D1EEE963EC392868AF2AFF7DE5711","priority":1,"outbound":true,"request":false,"response":true,"requestid":"06da6532-bfd0-4a77-9637-b4da6f48b23a","events":[],"attributes":{"filename":"miogetadapter001.xml","restcommand":"/api/channeladapters","httpverb":"GET","querystring":"name=miotestadapter"},"tagdata":"","adaptertagdata":{"properties":"{\r\n \"encoding\": \"UTF-8\",\r\n \"source\": \"miochannelsource\",\r\n \"adapter\": \"miotestadapter\",\r\n \"directory\": \"C:\\\\Program Files\\\\Opcenter Connect MOM\\\\Channel Adapter Host\\\\inbound\"\r\n}"},"status":"","correlationid":"","maxretrycount":10,"retrycount":0,"automapped":false,"express":false,"inhibitEvent":false,"eventonly":false,"eventttl":0,"check":{"timestamp":"2021-10-05T06:27:04.8626024Z","stages":[{"name":"Created","machineName":"VM-VDIP49-03","timestamp":"2021-10-05T06:27:04.8626024Z","time":0,"duration":0},{"name":"Adapter Host Added","machineName":"VM-VDIP49-03","timestamp":"2021-10-05T06:27:04.8645993Z","time":1,"duration":1},{"name":"Adapter Host Dispatch","machineName":"VM-VDIP49-03","timestamp":"2021-10-05T06:27:04.869603Z","time":7,"duration":6,"dispatcher":"BrokerBalanced"},{"name":"Broker Received","machineName":"VM-VDIP49-03","timestamp":"2021-10-05T06:27:04.8905926Z","time":27,"duration":20},{"name":"Broker Added","machineName":"VM-VDIP49-03","timestamp":"2021-10-05T06:27:04.8925959Z","time":29,"duration":2},{"name":"Broker Dispatch","machineName":"VM-VDIP49-03","timestamp":"2021-10-05T06:27:04.9285978Z","time":65,"duration":36,"availThreads":24,"dispatcher":"fifowithpredecessors"},{"name":"Broker Added","machineName":"VM-VDIP49-03","timestamp":"2021-10-05T06:27:05.0966056Z","time":234,"duration":169},{"name":"Broker Dispatch","machineName":"VM-VDIP49-03","timestamp":"2021-10-05T06:27:05.1066034Z","time":244,"duration":10,"availThreads":24,"dispatcher":"fifowithpredecessors"},{"name":"Adapter Host Received","machineName":"VM-VDIP49-03","timestamp":"2021-10-05T06:27:05.1216049Z","time":259,"duration":15},{"name":"Adapter Host Send","machineName":"VM-VDIP49-03","timestamp":"2021-10-05T06:27:05.1486105Z","time":286,"duration":27}]}}',
1)
insert into "LOGENTRY"
values ('d8dcd593-af52-425a-8bf2-d93f78a601c6')
**Tried Query**
SELECT M.Id,RTRIM(XMLAGG(XMLELEMENT(E,M.SerializedMessage,',').EXTRACT('//text()') ORDER BY M.SerializedMessage).GetClobVal(),',') AS LIST1,M.Series
from LOGENTRY E INNER JOIN LOGMESSAGE M ON E.Id = M.Id group by M.Id,M.series;
**Error**
ORA-00932: inconsistent datatypes: expected CHAR got LONG
00932. 00000 - "inconsistent datatypes: expected %s got %s"

The long datatype by itself has lots of restrictions and is very difficult to work with in general. There's a reason why it's deprecated and you're just giving yourself extra work, finding ways around it, instead of using clobs.
But to answer your question, this is, I think, probably what you wanted:
SELECT listagg(a.linetext, '') within group (order by rownum)
FROM
(
SELECT 'a' linetext from dual
UNION ALL
SELECT 'a' linetext from dual
UNION ALL
SELECT '2' linetext from dual
UNION ALL
SELECT 'b' linetext from dual
) a
Replace the subquery with a query of your table and it will concat your results, which you get in separate lines.

Related

MIN function behavior changed on Oracle databases after SAS Upgrade to 9.4M7

I have a program that has been working for years. Today, we upgraded from SAS 9.4M3 to 9.4M7.
proc setinit
Current version: 9.04.01M7P080520
Since then, I am not able to get the same results as before the upgrade.
Please note that I am querying on Oracle databases directly.
Trying to replicate the issue with a minimal, reproducible SAS table example, I found that the issue disappear when querying on a SAS table instead of on Oracle databases.
Let's say I have the following dataset:
data have;
infile datalines delimiter="|";
input name :$8. id $1. value :$8. t1 :$10.;
datalines;
Joe|A|TLO
Joe|B|IKSK
Joe|C|Yes
;
Using the temporary table:
proc sql;
create table want as
select name,
min(case when id = "A" then value else "" end) as A length 8
from have
group by name;
quit;
Results:
name A
Joe TLO
However, when running the very same query on the oracle database directly I get a missing value instead:
proc sql;
create table want as
select name,
min(case when id = "A" then value else "" end) as A length 8
from have_oracle
group by name;
quit;
name A
Joe
As per documentation, the min() function is behaving properly when used on the SAS table
The MIN function returns a missing value (.) only if all arguments are missing.
I believe this happens when Oracle don't understand the function that SAS is passing it - the min functions in SAS and Oracle are very different and the equivalent in SAS would be LEAST().
So my guess is that the upgrade messed up how is translates the SAS min function to Oracle, but it remains a guess. Does anyone ran into this type of behavior?
EDIT: #Richard's comment
options sastrace=',,,d' sastraceloc=saslog nostsuffix;
proc sql;
create table want as
select t1.name,
min(case when id = 'A' then value else "" end) as A length 8
from oracle_db.names t1 inner join oracle_db.ids t2 on (t1.tid = t2.tid)
group by t1.name;
ORACLE_26: Prepared: on connection 0
SELECT * FROM NAMES
ORACLE_27: Prepared: on connection 1
SELECT UI.INDEX_NAME, UIC.COLUMN_NAME FROM USER_INDEXES UI,USER_IND_COLUMNS UIC WHERE UI.TABLE_NAME='NAMES' AND
UIC.TABLE_NAME='NAMES' AND UI.INDEX_NAME=UIC.INDEX_NAME
ORACLE_28: Executed: on connection 1
SELECT statement ORACLE_27
ORACLE_29: Prepared: on connection 0
SELECT * FROM IDS
ORACLE_30: Prepared: on connection 1
SELECT UI.INDEX_NAME, UIC.COLUMN_NAME FROM USER_INDEXES UI,USER_IND_COLUMNS UIC WHERE UI.TABLE_NAME='IDS' AND
UIC.TABLE_NAME='IDS' AND UI.INDEX_NAME=UIC.INDEX_NAME
ORACLE_31: Executed: on connection 1
SELECT statement ORACLE_30
ORACLE_32: Prepared: on connection 0
select t1."NAME", MIN(case when t2."ID" = 'A' then t1."VALUE" else ' ' end) as A from
NAMES t1 inner join IDS t2 on t1."TID" = t2."TID" group by t1."NAME"
ORACLE_33: Executed: on connection 0
SELECT statement ORACLE_32
ACCESS ENGINE: SQL statement was passed to the DBMS for fetching data.
NOTE: Table WORK.SELECTED_ATTR created, with 1 row and 2 columns.
! quit;
NOTE: PROCEDURE SQL used (Total process time):
real time 0.34 seconds
cpu time 0.09 seconds
Use the SASTRACE= system option to log SQL statements sent to the DBMS.
options SASTRACE=',,,d';
will provide the most detailed logging.
From the prepared statement you can see why you are getting a blank from the Oracle query.
select
t1."NAME"
, MIN ( case
when t2."ID" = 'A' then t1."VALUE"
else ' '
end
) as A
from
NAMES t1 inner join IDS t2 on t1."TID" = t2."TID"
group by
t1."NAME"
The SQL MIN () aggregate function will exclude null values from consideration.
In SAS SQL, a blank value is also interpreted as null.
In SAS your SQL query returns the min non-null value TLO
In Oracle transformed query, the SAS blank '' is transformed to ' ' a single blank character, which is not-null, and thus ' ' < 'TLO' and you get the blank result.
The actual MIN you want to force in Oracle is min(case when id = "A" then value else null end) which #Tom has shown is possible by omitting the else clause.
The only way to see the actual difference is to run the query with trace in the prior SAS version, or if lucky, see the explanation in the (ignored by many) "What's New" documents.
Why are you using ' ' or '' as the ELSE value? Perhaps Oracle is treating a string with blanks in it differently than a null string.
Why not use null in the ELSE clause?
or just leave off the ELSE clause and let it default to null?
libname mylib oracle .... ;
proc sql;
create table want as
select name
, min(case when id = "A" then value else null end) as A length 8
from mylib.have_oracle
group by name
;
quit;
Also try running the Oracle code yourself, instead of using implicit pass thru.
proc sql;
connect to oracle ..... ;
create table want as
select * from connection to oracle
(
select name,
min(case when id = "A" then value else null end) as A length 8
from have_oracle
group by name
)
;
quit;
When I try to reproduce this in Oracle I get the result you are looking for so I suspect it has something to do with SAS (which I'm not familiar with).
with t as (
select 'Joe' name, 'A' id, 'TLO' value from dual union all
select 'Joe' name, 'B' id, 'IKSK' value from dual union all
select 'Joe' name, 'C' id, 'Yes' value from dual
)
select name
, min(case when id = 'A' then value else '' end) as a
from t
group by name;
NAME A
---- ----
Joe TLO
Unrelated, if you are only interested in id = 'A' then a better query would be:
select name
, min(value) as a
from t
where id = 'A'
group by name;

How to split a comma-separated value to columns using connect by

I have a column with less than <50 comma separated values. And the number of comma separated values in that particular column is not constant I would like to query this table with IN/AND/OR clause for these comma separated values:
So I would like to:
split these values into separate columns in the select query
Query for a person's market code with AND, OR and IN :
EUP and APCAC
APAC or EU Or CA
IN ( APAC,EU,LATIM)
I have to use this query in spring data jpa native query
I don't want to use as many substr.
I thought to accomplish this by using connect by with level would be useful after referring the following answers - ans1 and ans2
Usertable:
username
market_code
in_use
john
eup,apac,Latim
0
sebastin
apac,Latim
0
xavier
ca,apac,Latim
0
However the following only returns one row where I expected to have 3 rows :
select regexp_substr(market_code,'[^|]+', 1, level) from testautomadm.userpool
where AND USERNAME = 'john'
connect by regexp_substr('market_code', '[^|]+', 1, level)
is not null
Any help to solve this use case much appreciated.
Thank you!
You can use the multiset and hierarchy query as follows:
Select user_name,
listagg(market_code, ',') within group (order by pos) as market_code,
In_use
From
(Select user_name,
regexp_substr(market_code, '[^,]+',1, column_value) as market_code,
in_use,
column_value as pos
From t,
table(cast(multiset(
select level from dual
connect by level <= length (regexp_replace(t.market_code, '[^,]+')) + 1
) as sys.OdciNumberList)) levels) t
Where market_code in ('EUP','APCAC')
Group by user_name, in_use
Having count(distinct market_code) = 2
Above query shows the usage of AND as we have used count = 2 You can use count = 1 and respective market_code in IN for OR And IN query

Translate hierarchical Oracle query to DB2 query

I work primarily with SAS and Oracle and am still new to DB2. Im faced with needing a hierarchical query to separate a clob into chunks that can be pulled into sas. SAS has a limit of 32K for character variables so I cant just pull the dataset in normally.
I found an old stackoverflow question about the best way to pull a clob into a sas data set but it is written in Oracle.
Import blob through SAS from ORACLE DB
Since I am new to DB2 and the syntax for this type of join seems very different I was hoping to find someone that could help convert it and explain the syntax. I find the Oracle syntax to be much easier to understand. I'm not sure in DB2 if you would use a CTE recursion like this https://www.ibm.com/support/knowledgecenter/en/SSEPEK_10.0.0/apsg/src/tpc/db2z_xmprecursivecte.html or if you would use hierarchical queries like this https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_71/sqlp/rbafyrecursivequeries.htm
Here is the Oracle query.
SELECT
id
, level as chunk_id
, regexp_substr(clob_value, '.{1,32767}', 1, level, 'n') as clob_chunk
FROM (
SELECT id, clob_value
FROM schema.table
WHERE id = 1
)
CONNECT BY LEVEL <= regexp_count(clob_value, '.{1,32767}',1,'n')
order by id, chunk_id;
The table has two fields the id and the clob_value and would look like this.
ID CLOB_VALUE
1 really large clob
2 medium clob
3 another large clob
The thought is I would want this result. I would only ever be doing this one row at a time where id= which ever row I am processing.
ID CHUNK_ID CLOB
1 1 clob_chunk1of3
1 2 clob_chunk2of3
1 3 clob_chunk3of3
Thanks for any time spent reading and helping.
Here is a solution that should work in DB2 with few changes (but please be advised that I don't know DB2 at all; I am just using Oracle features that are in the SQL Standard, so they should be implemented identically - or almost so - in DB2).
Below I create a table with your sample data; then I show how to chunk it into substrings of length at most 8 characters. Although the strings are short, I defined the column as CLOB and I am using CLOB tools; this should work on much larger CLOBs.
You can make both the chunk size and the id into bind parameters, if needed. In my demo below I hardcoded the chunk size and I show the result for all IDs in the table. In case the CLOB is NULL, I do return one chunk (which is NULL, of course).
Note that touching CLOBs in a query is very expensive; so most of the work is done without touching the CLOBs. I only work on them as little as possible.
PREP WORK
drop table tbl purge; -- If needed
create table tbl (id number, clob_value clob);
insert into tbl (id, clob_value)
select 1, 'really large clob' from dual union all
select 2, 'medium clob' from dual union all
select 3, 'another large clob' from dual union all
select 4, null from dual -- added to check handling
;
commit;
QUERY
with
prep(id, len) as (
select id, dbms_lob.getlength(clob_value)
from tbl
)
, rec(id, len, ord, pos) as (
select id, len, 1, 1
from prep
union all
select id, len, ord + 1, pos + 8
from rec
where len >= pos + 8
)
select id, ord, dbms_lob.substr(clob_value, 8, pos)
from tbl inner join rec using (id)
order by id, ord
;
ID ORD CHUNK
---- ---- --------
1 1 really l
1 2 arge clo
1 3 b
2 1 medium c
2 2 lob
3 1 another
3 2 large cl
3 3 ob
4 1
Another option is to enable the Oracle compatibility in Db2 and just issue the hierarchical query.
This GitHub repository has background information on SQL recursion in DB2, including the Oracle-style syntax and a side by side example (both work against the Db2 sample database):
-- both queries are against the SAMPLE database
-- and should return the same result
SELECT LEVEL, CAST(SPACE((LEVEL - 1) * 4) || '/' || DEPTNAME
AS VARCHAR(40)) AS DEPTNAME
FROM DEPARTMENT
START WITH DEPTNO = 'A00'
CONNECT BY NOCYCLE PRIOR DEPTNO = ADMRDEPT;
WITH tdep(level, deptname, deptno) as (
SELECT 1, CAST( DEPTNAME AS VARCHAR(40)) AS DEPTNAME, deptno
FROM department
WHERE DEPTNO = 'A00'
UNION ALL
SELECT t.LEVEL+1, CAST(SPACE(t.LEVEL * 4) || '/' || d.DEPTNAME
AS VARCHAR(40)) AS DEPTNAME, d.deptno
FROM DEPARTMENT d, tdep t
WHERE d.admrdept=t.deptno and d.deptno<>'A00')
SELECT level, deptname
FROM tdep;

Applying where condition on Casted number coulmn in ORACLE from a inner query result

For Sample purpose lets create a table with below schema and fill some sample values
CREATE TABLE games(ID INT ,Name VARCHAR(20));
INSERT INTO games(ID,Name) VALUES (2008,'Beijing');
INSERT INTO games(ID,Name) VALUES (2012,'London');
INSERT INTO games(ID,Name) VALUES (2012,12);
INSERT INTO games(ID,Name) VALUES (2012,654);
Output:
ID NAME
2008 Beijing
2012 London
2012 12
2012 654
In the above table we have both number and string data in the name column lets write a query that uses the REGX to filter only the numerical rows
SELECT TO_NUMBER(Name)as Trimmed FROM games where REGEXP_LIKE(Name, '(?<=\s|^)\d+(?=\s|$)', '')
Output:
TRIMMED
12
654
Now here is the problem if write a where clause of getting values greater than 12 from the above result it throws invalid number.
Select * from (SELECT TO_NUMBER(Name)as Trimmed FROM games where REGEXP_LIKE(Name, '(?<=\s|^)\d+(?=\s|$)', '')) T1 where T1.Trimmed >12 ;
I found this is how the oracle query planning works but is there any other way i can achieve this
This will work:
Select * from
(SELECT Name as Trimmed
FROM games where REGEXP_LIKE(Name, '(?<=\s|^)\d+(?=\s|$)', '')) T1
where to_number(T1.Trimmed) >12 ;
Unfortunately you need a subquery. It can't be done with one where.
This can be done in a single query:
with
inputs as (
select 2008 as id, 'Beijing' as name from dual union all
select 2012 , 'London' from dual union all
select 2012 , '12' from dual union all
select 2012 , '654' from dual
)
select id, name
from inputs
where translate(name, 'a0123456789', 'a') is null
and to_number(regexp_replace(name, '[^[:digit:]]', '')) > 12
;
ID NAME
---------- -------
2012 654
1 row selected.
regexp_replace removes all the characters except digits, so the test can be done regardless of what the name is. If there are no digits in the name, the result is NULL, which can be converted to number (it is still null).
The translate solution for testing for "all-digits" is more efficient than using regexp_like. The odd-looking 'a' in translate is needed due to an oddity in the translate function itself (see the documentation). This test is not needed if all the names are either "all letters" or "all digits" (if "all letters", the second test with regexp_replace would suffice); but the first test is needed if names like "Sydney 2000" are possible in the name column.

Expected CHAR got NUMBER

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

Resources