ORA-00918: column ambiguously defined: how to find the column - oracle

I'm getting the classic error:
ORA-00918: column ambiguously defined
Usually, I know how to solve it but my problem now is that I'm working with a 700 row query.
Is there a way to identify the column?

Have you tried to do a binary search?
e.g.
If your original query looks like
Select col1
,col2
,col3
,col4
from MyTable
you can start with commenting the 2nd half
Select col1
,col2
/*,col3
,col4 */
from MyTable
If you still get the error, run the query again commenting some column from the other half:
Select col1
/*,col2 */
,col3
,col4
from MyTable
If you still get an error then your problem is with col1, otherwise you need to change col2.

The ambiguous column error message indicates that you have joined two (or more) columns in your query which share the same column name.
The proper way to solve this is to give each table in the query an alias and then prefix all column references with the appropriate alias. I agree that won't be fun for such a large query but I'm afraid you will have to pay the price of your predecessor's laxness.

In Oracle, you can use all_tab_cols to query the columns names of your tables. The following query will return the common column names between TABLE1 and TABLE2. Then you just need to prefix those common columns instead of all 100 column references.
select column_name from all_tab_cols
where table_name='TABLE1' and owner ='OWNER1'
and column_name in (
select column_name from all_tab_cols
where table_name='TABLE2' and owner ='OWNER2')

For posterity's sake:
I had this issue when I selected columns TABLE1.DES and TABLE2.DES in a query without aliasing the result. When I ran it alone my SQL editor turned these into DES and DES_1, no complaint.
However when I turned the same query into a subquery
SELECT a.col1, a.col2, a.col3, b.*
from TABLE3 a
INNER JOIN (
--that query as a subquery
) b
on a.PK=b.FK`
it threw the same ORA-00918 error message you described. Changing the SELECT in my subquery to
SELECT TABLE1.DES AS T1_DES, TABLE2.DES AS T2_DES ...
fixed the issue.

you can check common columns by using :
select COLUMN_NAME from ALL_TAB_COLS where TABLE_NAME = 'tablenamefirst'
intersect
select COLUMN_NAME from ALL_TAB_COLS where TABLE_NAME = 'tablenamesecond';

Related

How to return distinct values in a JSON_ARRAYAGG

So I'm attempting to place the results of a distinct, single-column query into a JSON array so it can be used on my web server. I have it set up something like this:
SELECT JSON_OBJECT(
'ArrayKey' VALUE JSON_ARRAYAGG( col )
) AS jsonResult
FROM(SELECT DISTINCT column_name AS col
FROM tbl_name);
However, when this query returns results, the array it generates in JSON contains all values from my column and ignores the DISTINCT clause in the subquery somehow. Whenever I get rid of the JSON_ARRAYAGG clause and output the results directly, the result are unique, but somehow the command is ignored when I add it back in. I've also attempted to place the DISTINCT clause inside the JSON_ARRAYAGG as well, like so:
SELECT JSON_OBJECT(
'ArrayKey' VALUE JSON_ARRAYAGG( DISTINCT col )
) AS jsonResult
FROM(SELECT DISTINCT column_name AS col
FROM tbl_name);
to no avail. Does anyone know what's going wrong in my code that's causing the array to output all values instead of distinct ones?
Interesting... Looks like a bug to me. The optimizer seems to push down too eagerly.
As workaround you can use the NO_MERGE hint on the subquery.
SELECT /*+NO_MERGE(x)*/
json_object('ArrayKey'
VALUE json_arrayagg(column_name)) jsonresult
FROM (SELECT DISTINCT
column_name
FROM tbl_name) x;
A CTE and a MATERIALIZE hint seem to work too.
WITH cte
AS
(
SELECT /*+MATERIALIZE*/
DISTINCT
column_name
FROM tbl_name
)
SELECT json_object('ArrayKey'
VALUE json_arrayagg(column_name)) jsonresult
FROM cte;
db<>fiddle
This was a bug, we fixed it. You can try it out on live SQL
create table tbl_name (column_name number);
insert into tbl_name values(1);
insert into tbl_name values(1);
insert into tbl_name values(2);
SELECT JSON_OBJECT(
'ArrayKey' VALUE JSON_ARRAYAGG( col )
) AS jsonResult
FROM(SELECT DISTINCT column_name AS col
FROM tbl_name);
{"ArrayKey" : [1,2]}
The bug is
Bug 27757725 - JSON GENERATION AGGREGATION FUNCTIONS IGNORE DISTINCT
you can request a backport from Oracle Support Services
I've found this hack to work:
SELECT JSON_OBJECT(
'ArrayKey' VALUE JSON_ARRAYAGG( col )
) AS jsonResult
FROM(SELECT DISTINCT column_name AS col
FROM tbl_name)
HAVING COUNT(*) = COUNT(*);
See also: Oracle bug produces duplicate aggregate values in JSON_ARRAYAGG

How do I get all table names and its column names in oracle?

How do I get all table names and its column names in oracle? The Table names should be printed first followed by all the column name, then the next table and its columns, and so on and so forth.
If you are dba you can see all tables in DB;
select * from all_tab_columns
order by table_name;
The query below, in the middle column (str), has the data the way you requested it. However, without the info in the first and/or the last column, it is not clear how you will know which values are table names and which are columns under them.
It would make a lot more sense to have table name in one column (repeated for each of its columns), then the column name and then the order. This would be just the second member of the union all operation.
The query below works for the tables in your schema. If you want to do this for all the tables you have access to, use all_tables and all_tab_columns; if you have DBA privileges, use dba_tables and dba_tab_columns (but in these cases, don't you need to know the schema/owner, not just the table name?)
select table_name as tbl, table_name as str, 0 as ord from user_tables
union all
select table_name, column_name, column_id from user_tab_columns
order by tbl, ord
;
SELECT table_name, column_name
FROM all_tab_cols
order by table_name, column_name

How can I display the all the table names, along with their count of column names?

My database has a lot of tables. How can I display all the table names along with the count of column names in each table?
myoutput:
------------
table_name count(*)
---------- --------
table_t1 12
x_a 5
Y_k 23
samptabl 0
Use USER_TAB_COLS view to get the column_count.
SELECT table_name, count(*) column_count
FROM user_tab_cols
GROUP BY table_name;
If you want the name of the table with the number of columns in it, use DBA's answer here.
If you want name of the table and the number of rows in it, use the following:
SELECT table_name, num_rows
FROM user_tables;
The numbers of rows in this query represent the numbers when the table was last analyzed. To return the latest numbers run ANALYSE tablename before running this query.
If you want to know all table_names and columns count in your Entire Database then here is the query.
Query : SELECT TABLE_NAME,COUNT(COLUMN_NAME) as No_Of_Cols
FROM ALL_TAB_COLS
GROUP BY TABLE_NAME;
Thanks,
Venu.
SELECT table_name, count(*) column_count
FROM all_tables
GROUP BY table_name;

Comparing two tables for different columns PL SQL

I very new to PL SQL and I have encountered a problem. Hopefully its not too hard to solve and I'm just going about it all wrong.
My problem is this: I have two tables with a different amount of columns. I need to run a check to see what the different columns are and then add them to one of the tables.
For example:
Table 1 has 1 column called name.
Table 2 has 2 columns called name and id.
(name has the same data type in both tables)
In this case, I would need to run a script that will check table 1 and 2, see that table 1 is missing the 'id' column and then add it to table 1.
Is this possible?
so far I have this:
SELECT TABLE_NAME, COLUMN_NAME FROM user_tab_columns WHERE table_name = 'TEST_TBL' OR TABLE_NAME ='TEST_TBL1'
which returns the columns for both tables. I have looked everywhere on the internet with no luck at all. I have tried to do intersect and join but with no luck.
If anyone has any help or could point me in the right direction I would appreciate it so much!
To get the different columns
SELECT TABLE_NAME, COLUMN_NAME FROM user_tab_columns
where table_name = 'Table1' AND COLUMN_NAME NOT IN ( SELECT COLUMN_NAME FROM USER_TAB_COLUMNS WHERE TABLE_NAME='table2')
UNION
SELECT TABLE_NAME, COLUMN_NAME FROM user_tab_columns
where table_name = 'table2' AND COLUMN_NAME NOT IN ( SELECT COLUMN_NAME FROM USER_TAB_COLUMNS WHERE TABLE_NAME='table1');

populating select list with common column names b/w two tabels via subquery -oracle

My code is clear enough to describe what i am trying to achieve
SELECT (select column_name from user_tab_cols where table_name='tbl1'
intersect
select column_name from user_tab_cols where table_name='tbl2')
FROM tbl2;
It is throwing ORA-01427: single-row subquery returns more than one row
I understand this error but don't know the alternate solution to achieve my goal .
You don't need the subquery here. Try this instead:
SELECT column_name FROM user_tab_cols WHERE table_name = 'tbl1'
INTERSECT SELECT column_name FROM user_tab_cols WHERE table_name = 'tbl2'
This will return a list of column names that exist in both tbl1 and tbl2.

Resources