ORA-00918: column ambiguously defined - INSERT INTO table - oracle

Please help me with this error, I spent hours on this.
Maybe the problems is somewhere on those fields that highlighted ( on the image ), because when I remove
it, the code works.
I check good on column names to make sure there is no wrong typing.
This is the table design:
This is my command text:
INSERT INTO PRODUCTS(
idz,category_id,brand_id,
namez,
computed_name,
unit_price,discount,
url_key,
short_description,
rate_avg,
rate_total,
rate_avg_recent,
rate_total_recent,
rate_total_counting,
rate_avg_counting,
views,
views_recent,
views_counting,
purchases,
purchases_recent,
purchases_counting,
search_recent,
search_counting
)
WITH recs AS (
SELECT 52333193, 1811, 111461,
'Tai nghe bluetooth không dây F9 True wireless Dock Sạc có Led Báo Pin Kép',
'Tai nghe bluetooth không dây F9 True wireless Dock Sạc có Led Báo Pin Kép',
169000,581000,
'tai-nghe-bluetooth-khong-day-f9-true-wireless-cam-ung-van-tay-dock-sac-co-led-bao-pin-kep-p52333193/52333193',
'\n \n\n\n\n\n\n \nSử dụng Chip Bluetooth 5.0 mạnh mẽ',
0,0,0,0,0,0,0,0,0,0,0,0,0,0 -- I think the problem is here, It work when I remove this line (and
-- columns defined above )
FROM dual
)
SELECT * FROM recs
Thank guys!!

I think the problem is that Oracle sets a default alias for each column in the subquery, based its value. Since you have multiple columns with the same value, they get the same alias, and this causes SELECT * to generate the error.
This produces the same error:
with recs as (select 1,2,3,0,0,0 from dual) select * from recs;
But providing explicit unique aliases for the columns that have the same value works:
with recs as (select 1,2,3,0 as a, 0 as b, 0 as c from dual) select * from recs

Related

ORA-30483: window functions are not allowed here in ODI Mapping

I am working on ODI mapping where I am calculating" Min(ID) over parition by(device_num, sys_id) as min_id" in expression component, I used another expression component to filter duplicates using row_number() over partition by (ID) order by(min_id) followed by a filter component "rownum=1" this results in window function error are not allowed here.
I understand that I need to run the analytical function on top the aggregate results. I am not sure how to achieve this in odi mapping (odi 12c). can anyone of you please guide me?
merge into (
select /*+ */ *
from target_base.tgt_table
where (1=1)
) TGT
using (
select /*+ */
RESULT2.ID_1 AS ID,
RESULT2.COL AS MIN_ID
from (
SELECT
RESULT1.ID AS ID ,
RESULT1.DEVICE__NUM AS DEVICE__NUM ,
RESULT1.SYS_ID AS SYS_ID ,
MIN(RESULT1.ID) OVER (PARTITION BY RESULT1.DEVICE__NUM ,RESULT1.SYS_ID) AS COL ,
ROW_NUMBER() OVER (PARTITION BY RESULT1.ID ORDER BY (MIN(RESULT1.ID) OVER (PARTITION BY RESULT1.DEVICE__NUM ,RESULT1.SYS_ID) AS COL) DESC ) AS COL_1
-- WINDOW FUNCTION ERROR,
FROM
(
select * from union_table
) RESULT1
)RESULT2
where (1=1)
and (RESULT2.COL_1 = 1)
) SRC
on (
and TGT.ID=SRC.ID )
when matched then update set
TGT.COMMON_ID = SRC.MIN_ID
, TGT.REC_UPDATE = SYSDATE
WHERE (
DECODE(TGT.COMMON_ID, SRC.COMMON_ID, 0, 1) > 0
)
UNION_TABLE has data as per below table
ID
device_num
sys_id
1
A
5
2
B
15
3
C
25
4
D
35
5
A
10
5
A
5
6
B
15
6
B
20
7
C
25
7
C
30
8
D
35
8
D
40
output expected: the ID where the rown_num=1 will be updated in target
ODI Mapping
This is very complex use case to model in ODI and the parser might not understand what you are trying to achieve.
My advice would be to write the difficult part of the query manually in SQL and use it as a source in ODI. Here is how to do it :
In the physical design of your mapping click on your source table. In the property pane, go to the Extract Options. You can then paste your SQL as a value for option CUSTOMER_TEMPLATE.
Of course it hides a bit the logic of the mapping so it shouldn't be used everywhere but for complex use cases as this one, this is an easy way to get the job done. I personally always add a memo on mapping with custom SQL so other developers can quickly see it.
Let try use IKM :Oracle Incremental Update on target table replace for IKM Oracle Merge.
Physical -> click target table -> Intergration Knowlege Module -> Oracle Incremental Update

How to make a select on different table in function of an argument?

In function of myVariable, this select is made from a different table.
select
*
from
table(decode(myVariable,1,sys.odcinumberlist(1,2),sys.odcinumberlist(3)))
result
if myVAriable =1 then 1,2
else 3
I would like to to make the same thing but instead of having sys.odcinumberlist, I would like to have the list of all integer inferior than 100.
I have tried a lot of way to do that. This for instance, but none has worked
select *
from
table(decode(myvariable,1,table(select level from dual connect by level<100),sys.odcinumberlist(3)))
wanted result:
myvariable =1 then 1,2,3....99
else 3
You have to cast this subquery as odcinumberlist:
select * from
table(decode(myvariable, 1,
cast(multiset(
select level from dual connect by level<100)
as sys.odcinumberlist),
sys.odcinumberlist(3)))

Passing a parameter to a WITH clause query in Oracle

I'm wondering if it's possible to pass one or more parameters to a WITH clause query; in a very simple way, doing something like this (taht, obviously, is not working!):
with qq(a) as (
select a+1 as increment
from dual
)
select qq.increment
from qq(10); -- should get 11
Of course, the use I'm going to do is much more complicated, since the with clause should be in a subquery, and the parameter I'd pass are values taken from the main query....details upon request... ;-)
Thanks for any hint
OK.....here's the whole deal:
select appu.* from
(<quite a complex query here>) appu
where not exists
(select 1
from dual
where appu.ORA_APP IN
(select slot from
(select distinct slots.inizio,slots.fine from
(
with
params as (select 1900 fine from dual)
--params as (select app.ora_fine_attivita fine
-- where app.cod_agenda = appu.AGE
-- and app.ora_fine_attivita = appu.fine_fascia
--and app.data_appuntamento = appu.dataapp
--)
,
Intervals (inizio, EDM) as
( select 1700, 20 from dual
union all
select inizio+EDM, EDM from Intervals join params on
(inizio <= fine)
)
select * from Intervals join params on (inizio <= fine)
) slots
) slots
where slots.slot <= slots.fine
)
order by 1,2,3;
Without going in too deep details, the where condition should remove those records where 'appu.ORA_APP' match one of the records that are supposed to be created in the (outer) 'slots' table.
The constants used in the example are good for a subset of records (a single 'appu.AGE' value), that's why I should parametrize it, in order to use the commented 'params' table (to be replicated, then, in the 'Intervals' table.
I know thats not simple to analyze from scratch, but I tried to make it as clear as possible; feel free to ask for a numeric example if needed....
Thanks

oracle sorting with text as number

My NLS settings:
NLS_SORT POLISH
NLS_COMP BINARY
Simple test query:
select * from (
select '11117' as x from dual
union
select '12988' as x from dual
union
select '14659' as x from dual
union
select '1532' as x from dual
union
select '18017' as x from dual
) order by x;
Actual result:
x
-----
11117
12988
14659
1532
18017
Desired result:
x
-----
1532
11117
12988
14659
18017
Question:
Is there a NLS setting that will help me achive desired result? I know I can do order by to_number(x) or, even better, order by lpad(x, 5), but it's not good in this case - I need a system-wide solution that won't require query change.
What I tried:
order by nlssort(x, 'nls_sort=binary');
alter session set nls_sort='binary';
Maybe a somewhat odd solution, but ...
Rename your TABLE_SOMETHING to TABLE_OTHER.
Create a view TABLE_SOMETHING on top of the TABLE_OTHER which will TO_NUMBER() the troubled string column of yours to the same column name.
If the table is, application-wide, being modified, then create INSTEAD OF triggers over the view TABLE_SOMETHING.
Recompile possibly invalidated packages.
Won't be particularly performant when it comes to modifying large quantities of records, won't allow for truncating the table, but it might solve the ordering problem.

pl-sql include column names in query

A weird request maybe but. My boss wants me to create an admin version of a page we have that displays data from an oracle query in a table.
The admin page, instead of displaying the data (query returns 1 row), needs to return the table name and column name
Ex: Instead of:
Name Initial
==================
Bob A
I want:
Name Initial
============================
Users.FirstName Users.MiddleInitial
I realize I can do this in code but would rather just modify the query to return the data I want so I can leave the report generation code mostly alone.
I don't want to do it in a stored procedure.
So when I spit out the data in the report using something like:
blah blah = MyDataRow("FirstName")
I can leave that as is but instead of it displaying "BOB" it would display "Users.FirstName"
And I want to do the query using select * if possible instead of listing all the columns
So for each of the columns I am querying in the * , I want to get (instead of the column value) the tablename.ColumnName or tablename|columnName
hope you are following- I am confusing myself...
pseudo:
select tablename + '.' + Columnname as WhateverTheColumnNameIs
from Table1
left join Table2 on whatever...
Join Table_Names on blah blah
Whew- after writing all this I think I will just do it on the code side.
But if you are up for it maybe a fun challenge
Oracle does not provide an authentic way(there is no pseudocolumn) to get the column name of a table as a result of a query against that table. But you might consider these two approaches:
Extract column name from an xmltype, formed by passing cursor expression(your query) in the xmltable() function:
-- your table
with t1(first_name, middle_name) as(
select 1,2 from dual
), -- your query
t2 as(
select * -- col1 as "t1.col1"
--, col2 as "t1.col2"
--, col3 as "t1.col3"
from hr.t1
)
select *
from ( select q.object_value.getrootelement() as col_name
, rownum as rn
from xmltable('//*'
passing xmltype(cursor(select * from t2 where rownum = 1))
) q
where q.object_value.getrootelement() not in ('ROWSET', 'ROW')
)
pivot(
max(col_name) for rn in (1 as "name", 2 as "initial")
)
Result:
name initial
--------------- ---------------
FIRST_NAME MIDDLE_NAME
Note: In order for column names to be prefixed with table name, you need to list them
explicitly in the select list of a query and supply an alias, manually.
PL/SQL approach. Starting from Oracle 11g you could use dbms_sql() package and describe_columns() procedure specifically to get the name of columns in the cursor(your select).
This might be what you are looking for, try selecting from system views USER_TAB_COLS or ALL_TAB_COLS.

Resources