Oracle SQL - Column has no Corresponding Table - sql

I came across something that makes no sense.
This is the SAAADMS form containing the Curriculum tab. The form has fields (columns) from different sources (tables). Most of these columns have a corresponding table, but the User ID and Activity Date (in the red rectangle) do not have a corresponding table!
You can see that the SOVLCUR_ACTIVITY_DATE and SOVLCUR_USER_ID do not have a corresponding table. It states "N/A." The other two columns I listed (I only listed a couple since there are several) do have a corresponding table.
I am trying to pull data from the two columns with no corresponding table.
The SOVLCUR table I currently have in the code does NOT exist.
How do I find where this SOVLCUR_USER_ID and SOVLCUR_ACTIVITY_DATE data is stored or pull from a column that seems to have no table?
If the data is not really stored in SOVLCUR_USER_ID and SOVLCUR_ACTIVITY_DATE is there a way for me to see where it is stored? find all associated columns?
SELECT
SP.SPRIDEN_ID AS "STUDENT_ID",
SP.SPRIDEN_LAST_NAME AS "LAST",
SP.SPRIDEN_FIRST_NAME AS "FIRST",
SD.SARADAP_TERM_CODE_ENTRY AS "TERM",
SD.SARADAP_APPL_DATE AS "APP_DATE",
SV.SOVLCUR_USER_ID AS "USER_ID", /*SOVLCUR table does not exist*/
SV.SOVLCUR_ACTIVITY_DATE AS "ACTIVITY_DATE", /*SOVLCUR table does not exist*/
SYSDATE
FROM
SPRIDEN SP
JOIN SARADAP SD
ON SPRIDEN_PIDM = SARADAP_PIDM
JOIN SOVLCUR SV /*This table does not exist*/
ON SPRIDEN_PIDM = SOVLCUR_PIDM
WHERE
SP.SPRIDEN_CHANGE_IND IS NULL
AND
SD.SARADAP_TERM_CODE_ENTRY >= '201510'
AND
SV.SOVLCUR_USER_ID NOT IN ('SSmith', 'JJones')
AND
SV.SOVLCUR_ACTIVITY_DATE BETWEEN SYSDATE-1 AND SYSDATE

Oracle provides views/tables that can be query to find out that type of information:
select table_name from all_tab_columns
where column_name = 'COLUMN NAME';
This query will return all the table where that column exists.

As user1261620 said, use ALL_TAB_COLUMNS to see the table_name corresponding to a column_name. But, as you say that few tables does not exist, perhaps, those are not tables, rather VIEWS.
To confirm whether those are TABLE or VIEW, you can query ALL_OBJECTS
SELECT object_name, object_type
FROM all_objects
WHERE object_name = 'SOVLCUR';
If the above returns no rows, that would mean the object really doesn't exist. But, in that case the query won't be executed, as it won't be parsed at all. You would get error : table/view does not exist`.
Also, not all values needs to be always stored in database. The computed values are generally calculated through a query and returned to the user for display. And other than computed values, few static values like SYSDATE can be dynamically generated rather than storing it in database and querying it.
So, I think, those are not tables, rather VIEWS. Follow the steps as I mentioned to have a clear understanding.
Update Based on OP's new inputs
So, now you know that SOVLCUR is a synonym. Execute the following query to see its details :
SELECT * FROM all_synonyms WHERE synonym_name = 'SOVLCUR';
For example,
I am user LALIT, and I create a synonym for EMP table in SCOTT schema.
SQL> show USER
USER is "LALIT"
SQL>
SQL> CREATE OR REPLACE SYNONYM lalit FOR scott.emp
2 /
Synonym created.
SQL>
SQL> SELECT owner, synonym_name, table_owner, table_name
2 FROM all_synonyms
3 WHERE synonym_name = 'LALIT'
4 /
OWNER SYNONYM_NAME TABLE_OWNER TABLE_NAME
---------- --------------- ------------ ----------
LALIT LALIT SCOTT EMP
So, the table_owner and table_name shows the SCHEMA is SCOTT and TABLE is EMP.

Related

Convert JSONB Keys to Columns

I have a user table users containing id , name and information of type jsonb
User Table
id
name
information
1001
Alice
{"1":"Google","2":"1991-02-08"}
1002
Bob
{"1":"StackOverflow","3":"www.google.com"}
I have another Table having all the profile fields values named ProfileFields
profilefieldid
Value
1
Company
2
DateOfBirth
3
ProfileLink
The information jsonb column can only have keys present in the ProfileField Table.
You can expect the data is coming from a real world and the profile field will be updating.
I would like to output export this table in the format of
id
name
Company
DateOfBirth
ProfileLink
1001
Alice
Google
1991-02-08
1002
Bob
StackOverflow
www.google.com
My Trails :-
I was able to map profilefieldid with its respective values
SELECT
id ,
name ,
(SELECT STRING_AGG(CONCAT((SELECT "title" FROM "profile_fields" WHERE CAST("key" AS INTEGER)="id"),':',REPLACE("value",'"','')),',') FROM JSONB_EACH_TEXT("profile_fields")) "information"
FROM "users" ORDER BY "id";
I tried to use json_to record() but since the profilefield can have dynamic keys i was not able to come up with a solution because in the AS block i need to specify the columns in advance.
I sometimes encounter errors in Select Statement as Subquery returning more than 1 column.
Any suggestions and Solutions are greatly appreciated and welcomed.
Let me know if i need to improve my db structure , like its not in 2nd NormalForm or not well structured like that. Thank You
There is no way you can make this dynamic. A fundamental restriction of the SQL language is, that the number, names and data type of all columns of a query must be known before the database starts retrieving data.
What you can do though is to create a stored procedure that generates a view with the needed columns:
create or replace procedure create_user_info_view()
as
$$
declare
l_columns text;
begin
select string_agg(concat('u.information ->> ', quote_literal(profilefield_id), ' as ', quote_ident(value)), ', ')
into l_columns
from profile_fields;
execute 'drop view if exists users_view cascade';
execute 'create view users_view as select u.id, u.name, '||l_columns||' from users u';
end;
$$
language plpgsql;
After the procedure is executed, you can run select * from users_view and see all profile keys as columns.
If you want, you can create a trigger on the table profile_fields that re-creates the view each time the table is changed.
Online example

How to create a table in Sql from existing table along with it partition and indexs Structure

I have a table in Schema ABC, I have to create an exact replica for that table in the schema XYZ along with its Partition and Index.
Create table XYZ.table1 as Select * from ABC.table2;
Is there any possible way of implementing this?
It is DBMS_METADATA package you should look at.
In your case, to get table description (along with its partitions), you'd use
SELECT DBMS_METADATA.get_ddl ('TABLE', 'EMP', 'SCOTT') FROM DUAL;
(where EMP represents table name, while SCOTT is its owner).
To get its indexes, you'd use
SELECT DBMS_METADATA.get_ddl ('INDEX', index_name, 'SCOTT')
FROM user_indexes
WHERE table_name = 'EMP';
Another option might be to use Data Pump Export and Import utilities which allow you to export not only metadata, but tables' contents.

Dual table issue

Hi We all know DUAL is the table of SYS and other users have synonym of it.
but when i fire the below commnad
create table dual(x varchar2(1));
it worked. An object of the name DUAL was created.
when there is already a synonym with the name DUAL how can we create another object of same name? why oracle is allowing us to do it.
You can create a table named DUAL because tables and public synonyms have a different namespace. For details, see chapter Database Object Names and Qualifiers of Oracle's SQL Language Reference.
EDIT: To illustrate the mechanism:
If you create your own DUAL table as user scott
CREATE TABLE dual (x VARCHAR2(1));
... then it shows up in the data dictionary:
SELECT object_id, object_type, owner, object_name, namespace
FROM dba_objects
WHERE object_name='DUAL';
OBJECT_ID OBJECT_TYPE OWNER OBJECT_NAME NAMESPACE
142 TABLE SYS DUAL 1
143 SYNONYM PUBLIC DUAL 1
78138 TABLE SCOTT DUAL 1
So, the names are unique per owner and namespace. You cannot add yet another table in your schema called DUAL. You cannot create a private synonym named DUAL, but you can create your own synonym for schemas in other objects.
Please make sure to drop the table again. Even simple statements won't work anymore:
SELECT sysdate FROM DUAL;
--
DROP TABLE dual;
SELECT sysdate FROM DUAL;
01.07.2018
I think DUAL is a distraction here. Of course it's a system table and there are side effects if you mess about with it, so don't. But the question is really about why there is no namespace conflict between any object and a public synonym with the same name. For example, I can create a table named ALL_TABLES or DBMS_OUTPUT in my own schema (if I really want to). Or, I can create a table called MYDEMOTABLE and then create a public synonym MYDEMOTABLE for WILLIAM.MYDEMOTABLE.
But then, what restriction are you expecting to exist? There is already both a table (owned by SYS) and a public synonym (owned by PUBLIC) named DUAL. You can create a third object with the same name, as long as it isn't owned by SYS or PUBLIC.
I think I found a way to demonstrate what is going on (without using DUAL or any other SYS object ;-):
If two users create a table with the same name, the tables end up in their own schema as expected:
CREATE USER user_a IDENTIFIED BY user_a;
CREATE USER user_b IDENTIFIED BY user_b;
CREATE TABLE user_a.foo (x NUMBER);
CREATE TABLE user_b.foo (x NUMBER);
SELECT object_id, object_type, owner, object_name, namespace
FROM dba_objects
WHERE object_name='FOO';
OBJECT_ID OBJECT_TYPE OWNER OBJECT_NAME NAMESPACE
78225 TABLE USER_A FOO 1
78226 TABLE USER_B FOO 1
But when one of them creates a public synonym (as SYS did with it's DUAL table), it ends up in a magic schema with the name PUBLIC:
CREATE PUBLIC SYNONYM foo FOR user_a.foo;
SELECT object_id, object_type, owner, object_name, namespace
FROM dba_objects
WHERE object_name='FOO';
OBJECT_ID OBJECT_TYPE OWNER OBJECT_NAME NAMESPACE
78225 TABLE USER_A FOO 1
78226 TABLE USER_B FOO 1
78156 SYNONYM PUBLIC FOO 1
So, in other words, public synonyms are just synonyms that live in the schema PUBLIC. And you can have only one table, view, sequence, package, synonym with the same name per schema.
There have various schemas in your single database. When you asked about default DUAL table, which actually belongs to 'sys' Schema which is system schema. But your default Database schema is dbo it means when you have executed your query to create DUAL table is actually created in your default schema named dbo.
If you want to check their actual double existence there are many ways to check.
You can apply a query like "select * from sys.DUAL" and "select * from dbo.DUAL". there you will see two different outputs.
you can check all the schemas in "select * from sys.schemas".
Also, you can check their different schemas in with table name
"select * from sys.tables where name ='DUAL'";
the result will be two different tables with two different schema Id's.
Hope this will help you to understand schema basics.

Are SCHEMA and USER the same thing in Oracle?

Are SCHEMA and USER the same thing in Oracle? Is there is situation where a single user can have two or more schemas?
Strictly speaking a SCHEMA is the set of objects owned by a USER. However, a USER can have only one SCHEMA, so people often use the terms interchangeably.
Here's the difference between USER and SCHEMA. User "A" has granted rights on its PRODUCT table to user "B". User "B" does not have a table of that name.
SQL> show user
USER is "B"
SQL> select count(*) from products
2 /
select count(*) from products
*
ERROR at line 1:
ORA-00942: table or view does not exist
SQL> select count(*) from a.product
2 /
COUNT(*)
----------
2
SQL>
Without a synonym "B" needs to prefix the schema to reference the PRODUCT table. Unless they choose to change the current schema:
SQL> alter session set current_schema = "A"
2 /
Session altered.
SQL> select count(*) from product
2 /
COUNT(*)
----------
2
SQL> show user
USER is "B"
SQL>
Now the user is "B" but the current (default) schema is "A". Which menas they need to prefix the schema when referencing their own tables!
SQL> select table_name from user_tables;
TABLE_NAME
------------------------------
YOUR_TABLE
SQL> select count(*) from your_table;
select count(*) from your_table
*
ERROR at line 1:
ORA-00942: table or view does not exist
SQL> select count(*) from b.your_table;
COUNT(*)
----------
6
SQL>
"Whether a schema can be created separately Without any user ."
No. A SCHEMA must belong to a USER. When we create user Oracle creates a schema, an empty one, automatically.
Confusingly there is a create schema syntax, but that is just a short hand for creating a number of tables (and indexes) in one statement. Find out more.

SQL Table does not exist

This is what happens:
SQL> select table_name from user_tables;
TABLE_NAME
------------------------------
Discount
Taxes
Customer
Vehicles
WorkOrder
Task
TaskPart
Employee
EmplyeeTask
WorkOrderPart
InvoiceDetails
TABLE_NAME
------------------------------
Invoice
Parts
InvoicePrimaries
14 rows selected.
SQL> select * from Discount;
select * from Discount
*
ERROR at line 1:
ORA-00942: table or view does not exist
SQL>
I can't access that table. I can make it work just fine in C#, but in the Oracle GUI and the SQL Command Line, I cannot select the table. (It's a personal, self made database using Oracle Express)
Because in user_tables the table names are written in upper and lower case letters. I assume that you created these tables using something like
create table "Discount" ...
Generally oracle saves tablenames in upper case letters and table names without double quotas are searched in uppercase. Therefore your
select * from Discount
searches for a table named DISCOUNT and not Discount. You have to explicitly tell oracle that you want to preserve the letter case of your table names. That is done with double quotas as well. So
select * from "Discount"
should work.