Oracle select schema depending on select-statement - oracle

I have have two schemas with the same table. e.g schema1.adress and schema2.adress.
Both tables are identical.
Layout of table customer:
customerno: integer
name: varchar2(50)
Now I want to get the customers of schema 1 using something like
"select * from customer where schemaname = 1" or
"select * from customer where schemaname = 2"
Is there a mechanism in Oracle that can switch the schema depending on a criteria in a select-statement?
Before you ask: for a new project I have to query legacy schemas. I cannot change the schema, but I can set any permission on the schema / user.
Any ideas?
Thanks for any response,
Sven

You could create a private synonym for the user for the schema.table you want them to access,
create synonym user1.customer for schemaname1.customer;
create synonym user2.customer for schemaname2.customer;
Then your queries would always just be select * from customer;

So you are logged in as the same user both when you want to select from schema1.customer and select from schema2.customer?
A possible way can be something like:
select *
from (
select 'schema1' schema$name, c.* from schema1.customer c
union all
select 'schema2' schema$name, c.* from schema2.customer c
)
where schema$name = 'schema1'
If you can create views, it can be an idea to create a view like:
create or replace view customer_view as
select 'schema1' schema$name, c.* from schema1.customer c
union all
select 'schema2' schema$name, c.* from schema2.customer c
That makes it possible to do:
select *
from customer_view
where schema$name = 'schema1'
Whether you use view or not, Oracle optimizer can in most cases like this push the predicate "where schema$name = 'schema1'" into the UNION ALL and then it recognizes that it does not need to access schema2.customer at all.

Related

Unexpected behavior with nested Oracle SELECT query

Would love to get some help here understanding an unexpected behavior with an Oracle SELECT query. And maybe there is a nicer way to construct my query.
Basically, this is the query that gets me the distinct set of IDs that I'm after:
select distinct(c.LOCATIONID) from COURSESESSION c where c.MARKETID=280 and c.STATUSID in(1, 2)
and c.COURSESESSIONID not in (SELECT distinct(REGISTRATION.COURSESESSIONID) FROM REGISTRATION)
But I also want all the data for these distinct IDs form COURSESESSION table, so I'm wrapping the above query in yet another select statement, so it looks like this:
select * from COURSESESSION cs where cs.COURSESESSIONID in
(select distinct(c.LOCATIONID) from COURSESESSION c where c.MARKETID=280 and c.STATUSID in(1, 2)
and c.COURSESESSIONID not in (SELECT distinct(REGISTRATION.COURSESESSIONID) FROM REGISTRATION));
The first query returns a set of 21 records, but the second set returns 19, so I'm pretty sure I'm not doing this right. The triple-select query is basically for these 2 steps:
Set idsSet = select distinct(c.LOCATIONID) from COURSESESSION c where c.MARKETID=280 and c.STATUSID in(1, 2)
and c.COURSESESSIONID not in (SELECT distinct(REGISTRATION.COURSESESSIONID) FROM REGISTRATION)
select * from COURSESESSION cs where cs.COURSESESSIONID in(idsSet);
Anyone knows how to fix my triple-select query?

Access union all into new table

I have a saved query (MyUnion) for a union, appending monthly files (linked views):
select * from RawTrade1801
union all
select * from RawTrade1802
Trying to write this to a new table is proving problematic:
SELECT MyUnion.* into RawTrade2
FROM MyUnion
WHERE Field8 = 'ZAR';
I get an error: Cannot open database "
My aim is to once a month create a master table by appending every monthly file.
The following steps should generate a table from your UNION query:
Create a new query. In the SQL View, now type:
SELECT * FROM (SELECT * FROM RawTrade1801
UNION ALL
SELECT * FROM RawTrade1802);
Save the query. In its Design View click the Make Table button. Type in the table name (e.g. NewTable) that you want the output of this query to be.
Save and close the query.
The query icon will have changed. Double click on it and it should generate your table.
Access actually changes the SQL to
SELECT * INTO NewTable FROM
(SELECT * FROM RawTrade1801
UNION ALL
SELECT * FROM RawTrade1802) AS [%$###_Alias];
when you view the SQL after step 4.
Try using INSERT INTO ... SELECT:
INSERT INTO RawTrade2
SELECT * FROM RawTrade1801 WHERE Field8 = 'ZAR'
UNION ALL
SELECT * FROM RawTrade1802 WHERE Field8 = 'ZAR';
Of course, even if this works it still does not explain why your original query does not work. I expect it is a slight technical problem, though I don't know enough Access to see it immediately.
Create the Union query, save it with the name like 'qUnion'.
From menu open:
Create-->Query--> Make Table.
In Add Table Menu chose "Queries" and
Add your union query ('qUnion').
Select the fields that you need.
Open query.
Anew table will be created.

can i set up an SSRS report where users input parameters to a table

I have an oracle query that uses a created table as part of the code. Every time I need to run a report I delete current data and import the new data I receive. This is one column of id's. I need to create a report on SSRS in which the user can input this data into said table as a parameter. I have designed a simple report that they can enter some of the id's into a parameter, but there may be times when they need to enter in a few thousand id's, and the report already runs long. Here is what the SSRS code currently says:
select distinct n.id, n.notes
from notes n
join (
select max(seq_num) as seqnum, id from notes group by id) maxresults
on n.id = maxresults.ID
where n.seq_num = maxresults.seqnum
and n.id in (#MyParam)
Is there a way to have MyParam insert data into a table I would join called My_ID, joining as Join My_Id id on n.id = id.id
I do not have permissions to create functions or procedures in the database.
Thank you
You may try the trick with MATERIALIZE hint which normally forces Oracle to create a temporary table :
WITH cte1 AS
( SELECT /*+ MATERIALIZE */ 1 as id FROM DUAL
UNION ALL
SELECT 2 DUAL
)
SELECT a.*
FROM table1 a
INNER JOIN cte1 b ON b.id = a.id

Query to find all views/charts owned or shared with a user in Dynamics 2013

Is there a way to see all views / charts owned or shared with a user in Dynamics 2013? (DB query would be fine. I can access the base tables if needed.
#Ryan 's solution helped me quite a bit but was painful to transcribe. This is the solution in a more usable format (with minor edits):
DECLARE #userid varchar(100)
SELECT #userid = 'domain\user'
-- Get team membership for the user
IF OBJECT_ID(N'tempdb.dbo.#UserAndTeams') IS NOT NULL DROP TABLE #UserAndTeams
SELECT DISTINCT t.TeamId TeamOrUserId, t.[Name]
INTO #UserAndTeams
FROM
TeamBase t
INNER JOIN TeamMembership tm ON t.TeamId = tm.TeamId
INNER JOIN SystemUserBase su ON su.SystemUserId = tm.SystemUserId
WHERE
su.DomainName = #userid
INSERT INTO #UserAndTeams(TeamOrUserId, [Name])
SELECT su.SystemUserId, su.Firstname + ' ' + su.Lastname [Name]
FROM SystemUserBase su WHERE su.DomainName = #userid
-- Get a union of all teams and this user
IF OBJECT_ID(N'tempdb.dbo.#AllUsersAndTeams') IS NOT NULL DROP TABLE #AllUsersAndTeams
SELECT t.TeamId TeamOrUserId, t.[Name]
INTO #AllUsersAndTeams
FROM TeamBase t
INSERT INTO #AllUsersAndTeams(TeamOrUserId, [Name])
SELECT su.SystemUserId, su.Firstname + ' ' + su.Lastname [Name]
FROM SystemUserBase su
-- Extract share info from POA for selected entity types
SELECT DISTINCT su.[Name] SharedWith, objectIds.[Type], objectIds.[Name] Objectname, aut.[Name] Ownername
FROM
PrincipalobjectAccess poa WITH (NOLOCK)
INNER JOIN #UserAndTeams su WITH (NOLOCK) ON poa.PrincipalId = su.TeamOrUserId
INNER JOIN
(
SELECT 'Chart' [Type], UserQueryVisualizationId id, [Name], OwnerId FROM UserQueryVisualizationBase WITH (NOLOCK)
UNION SELECT 'View', UserQueryId id, [Name], OwnerId FROM UserQueryBase WITH (NOLOCK)
UNION SELECT 'Report', ReportId, [Name], OwnerId FROM Report WITH (NOLOCK)
UNION SELECT 'Dashboard', uf.userFormId id, [Name], OwnerId FROM UserForm uf WITH (NOLOCK) WHERE uf.[Type] = 0
) objectIds ON poa.ObjectId = objectIds.id
INNER JOIN #AllUsersAndTeams aut ON objectIds.OwnerId = aut.TeamOrUserId
ORDER BY
objectIds.[Type], objectIds.[Name]
I came up with this procedure:
Which works well for views/dashboards and charts. If a user can access an item via team membership the team name is displayed; if it's been shared directly with the user, the users' name is displayed.
It needs to be run for a user with access to the base tables.
(I can't post the full SQL to Stack Overflow! It's containted in the attached image.)
This is actually trickier then you might think - The information about shared views is contained within the principalobjectaccess table in database.
This table contains the object that's being shared, who it's being shared with, and what permissions they have on that object.
The hard part is that the guid that contains the object being shared does not also specify what object type is being shared as well. It might be possible to create a query that joins the POA table to the views created, and then put in a where clause for that particular user... but be careful and don't run this against a production system (and if you have to make sure to use a (nolock) on the POA table.)
Sorry I couldn't be more help, but I'm not using On-prem and cant test a query.

Finding sequences and triggers associated with an Oracle table

I have used this query to fetch the list of sequences belonging to an Oracle database user:
SELECT * FROM all_sequences x,all_tables B
WHERE x.sequence_owner=B.owner AND B.TABLE_NAME='my_table';
But that database user is having many more sequence also, so the query returns me all the sequence of the database user. Can anybody help me to find the particular sequence of my_table using query so that I can get the auto increment id in my application.
i want the query which fetch list of table of my database user with the sequence and triggers used in the table
You can get the triggers associated with your tables from the user_triggers view. You can then look for any dependencies recorded for those triggers in user_dependencies, which may include objects other than sequences (packages etc.), so joining those dependencies to the user_sequences view will only show you the ones you are interested in.
Something like this, assuming you are looking at your own schema, and you're only interesting in triggers that references sequences (which aren't necessarily doing 'auto increment', but are likely to be):
select tabs.table_name,
trigs.trigger_name,
seqs.sequence_name
from user_tables tabs
join user_triggers trigs
on trigs.table_name = tabs.table_name
join user_dependencies deps
on deps.name = trigs.trigger_name
join user_sequences seqs
on seqs.sequence_name = deps.referenced_name;
SQL Fiddle demo.
If you're actually looking at a different schema then you'll need to use all_tables etc. and filter and join on the owner column for the user you're looking for. And if you want to include tables which don't have triggers, or triggers which don't refer to sequences, you can use outer joins.
Version looking for a different schema, though this assumes you have the privs necessary to access the data dictionary information - that the tables etc. are visible to you, which they may not be:
select tabs.table_name,
trigs.trigger_name,
seqs.sequence_name
from all_tables tabs
join all_triggers trigs
on trigs.table_owner = tabs.owner
and trigs.table_name = tabs.table_name
join all_dependencies deps
on deps.owner = trigs.owner
and deps.name = trigs.trigger_name
join all_sequences seqs
on seqs.sequence_owner = deps.referenced_owner
and seqs.sequence_name = deps.referenced_name
where tabs.owner = '<owner>';
If that can't see them then you might need to look at the DBA views, again if you have sufficient privs:
select tabs.table_name,
trigs.trigger_name,
seqs.sequence_name
from dba_tables tabs
join dba_triggers trigs
on trigs.table_owner = tabs.owner
and trigs.table_name = tabs.table_name
join dba_dependencies deps
on deps.owner = trigs.owner
and deps.name = trigs.trigger_name
join dba_sequences seqs
on seqs.sequence_owner = deps.referenced_owner
and seqs.sequence_name = deps.referenced_name
where tabs.owner = '<owner>';
One way would be to run these queries to check if there are any sequence's Pseudocolumns (NEXTVAL and CURRVAL ) used in your functions , procedures, packages, Triggers or PL/SQL JAVA SOURCE.
select * from user_source where
UPPER(TEXT) LIKE '%NEXTVAL%';
select * from all_source where
UPPER(TEXT) LIKE '%NEXTVAL%';
Then go to the specific Procedure, Function or Trigger to check which column/table gets populated by a sequence.
The query could also be used with '%CURRVAL%'
This might not help if you are running inserts from JDBC or other external applications using a sequence.
Oracle 12c introduced the IDENTITY columns, using which you could create a table with an identity column, which is generated by default.
CREATE TABLE t1 (c1 NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY,
c2 VARCHAR2(10));
This will internally create a sequence that auto-generates the value for the table's column.So, If you would like to know which sequence generates the value for which table, you may query the all_tab_columns
SELECT data_default AS sequence_val
,table_name
,column_name
FROM all_tab_columns
WHERE OWNER = 'HR'
AND identity_column = 'YES';
SEQUENCE_VAL |TABLE_NAME |COLUMN_NAME
-----------------------------------------|-------------------------------------
"HR"."ISEQ$$_78160".nextval |T1 |C1
I found a solution to this problem to guess the sequence of a particular sequence
select * from SYS.ALL_SEQUENCES where SEQUENCE_OWNER='OWNER_NAME' and LAST_NUMBER between (select max(FIELD_NAME) from TABLE_NAME) and (select max(FIELD_NAME)+40 from TABLE_NAME);
This query will guess by search the LAST_NUMBER of the sequence value between MAX value of the field using sequence and Max value + 40 (in my case cache value is 20, so I put 40)
select SEQUENCE_NAME from sys.ALL_TAB_IDENTITY_COLS where owner = 'SCHEMA_NAME' and table_name = 'TABLE_NAME';

Resources