How to list tables from accessible via database links? - select

I have an access to a database, and sure I can get all tables/columns accessible for me just using:
select * from ALL_TAB_COLUMNS
I can also access some tables using "#", as I understand a database link mechanism, like this:
select * from aaa.bbb_ddd#ffgh where jj = 55688
where aaa.bbb_ddd#ffgh corresponds to some table with a column jj
BUT I don't see this aaa.bbb_ddd#ffgh table in ALL_TAB_COLUMNS.
How can I request all tables (and columns inside them) accessible for me via these database links (or so)?

You can't, easily, get all columns accessible via all database links; you can get all columns accessible via one database link by querying ALL_TAB_COLUMNS on the remote database
select * from all_tab_columns#<remote_server>
where <remote_server> in your example would be ffgh.
If you want to get this same information for all database links in your current schema, you'd either have to manually enumerate them and UNION the results together:
select * from all_tab_columns#dblink1
union all
select * from all_tab_columns#dblink2
Or, do something dynamically.
As Justin says, it's clearer if you add which database the data is coming from; you can do this either by just writing it in the query:
select 'dblink1' as dblink, a.* from all_tab_columns#dblink1 a
union all
select 'dblink2', a.* from all_tab_columns#dblink2 a
Or by using an Oracle built-in to work, for example the GLOBAL_NAME table (there's lots more ways):
select db1g.global_name, db1a.*
from all_tab_columns#dblink1 db1a
cross join global_name#dblink1 db1g
union all
select db2g.global_name, db2a.*
from all_tab_columns#dblink2 db2a
cross join global_name#dblink2 db2g

Related

SQL Natural Join

Okay. So the question that I got asked by the teacher was this:
(5 marks) Construct a SQL query on the dvdrental database that uses a natural join of two or more tables and an additional where condition. (E.g. find the titles of films rented by a particular customer.) Note the hints on the course news page if your query returns nothing.
Here is the layout of the database im working with:
http://www.postgresqltutorial.com/wp-content/uploads/2013/05/PostgreSQL-Sample-Database.png
The hint to us was this:
PostgreSQL hint:
If a natural join doesn't produce any results in the dvdrental DB, it is because many tables have the last update: timestamp field, and thus the natural join tries to join on that field as well as the intended field.
e.g.
select *
from film natural join inventory;
does not work because of this - it produces an empty table (no results).
Instead, use
select *
from film, inventory
where film.film_id = inventory.film_id;
This is what I did:
select *
from film, customer
where film.film_id = customer.customer_id;
The problem is I cannot get a particular customer.
I tried doing customer_id = 2; but it returns a error.
Really need help!
Well, it seems that you would like to join two tables that have no direct relation with each other, there's your issue:
where film.film_id = customer.customer_id
To find which films are rented by which customer you would have to join customer table with rental, then with inventory and finally with film.
The task description states
Construct a SQL query on the dvdrental database that uses a natural join of two or more tables and an additional where condition.quote

Postgres subquery has access to column in a higher level table. Is this a bug? or a feature I don't understand?

I don't understand why the following doesn't fail. How does the subquery have access to a column from a different table at the higher level?
drop table if exists temp_a;
create temp table temp_a as
(
select 1 as col_a
);
drop table if exists temp_b;
create temp table temp_b as
(
select 2 as col_b
);
select col_a from temp_a where col_a in (select col_a from temp_b);
/*why doesn't this fail?*/
The following fail, as I would expect them to.
select col_a from temp_b;
/*ERROR: column "col_a" does not exist*/
select * from temp_a cross join (select col_a from temp_b) as sq;
/*ERROR: column "col_a" does not exist
*HINT: There is a column named "col_a" in table "temp_a", but it cannot be referenced from this part of the query.*/
I know about the LATERAL keyword (link, link) but I'm not using LATERAL here. Also, this query succeeds even in pre-9.3 versions of Postgres (when the LATERAL keyword was introduced.)
Here's a sqlfiddle: http://sqlfiddle.com/#!10/09f62/5/0
Thank you for any insights.
Although this feature might be confusing, without it, several types of queries would be more difficult, slower, or impossible to write in sql. This feature is called a "correlated subquery" and the correlation can serve a similar function as a join.
For example: Consider this statement
select first_name, last_name from users u
where exists (select * from orders o where o.user_id=u.user_id)
Now this query will get the names of all the users who have ever placed an order. Now, I know, you can get that info using a join to the orders table, but you'd also have to use a "distinct", which would internally require a sort and would likely perform a tad worse than this query. You could also produce a similar query with a group by.
Here's a better example that's pretty practical, and not just for performance reasons. Suppose you want to delete all users who have no orders and no tickets.
delete from users u where
not exists (select * from orders o where o.user_d = u.user_id)
and not exists (select * from tickets t where t.user_id=u.ticket_id)
One very important thing to note is that you should fully qualify or alias your table names when doing this or you might wind up with a typo that completely messes up the query and silently "just works" while returning bad data.
The following is an example of what NOT to do.
select * from users
where exists (select * from product where last_updated_by=user_id)
This looks just fine until you look at the tables and realize that the table "product" has no "last_updated_by" field and the user table does, which returns the wrong data. Add the alias and the query will fail because no "last_updated_by" column exists in product.
I hope this has given you some examples that show you how to use this feature. I use them all the time in update and delete statements (as well as in selects-- but I find an absolute need for them in updates and deletes often)

Access Connected to SQL Server: Get User Name in Form Query

I use Access with linked tables to SQL Server 2008 R2 (ODBC connection). Via a access form I select the following query when opening the access form (the query code is entered in Design View > Form Properties > Record Source):
SELECT
mp_industry_description.group_name,
mp_industry_description.industry_description
FROM
((ax_id_storage
INNER JOIN
mn_entity
ON ax_id_storage.id_bb_global_company = mn_entity.id_bb_global_company)
INNER JOIN
mp_industry
ON mn_entity.industry_subroup_num = mp_industry.subgroup_num)
INNER JOIN
mp_industry_description
ON mp_industry.industry_description_group_num = mp_industry_description.industry_group_num;
The query works fine. Table ax_id_storage contains a column with all possible user names (userID). Therefore, the above query gives me several row entries, one for each user. I want to have only one user, which is the one who is currently executing the query. In a SQL Server query, I can adjust for this by adding:
WHERE ax_id_storage.userID = (SELECT nt_username FROM sys.sysprocesses WHERE (spid = ##SPID));
at the end of the first query. However, this does not work when I use the exact same command in Access. I get an error:
Syntax error in query expression 'ax_id_storage.userID = (SELECT
nt_username FROM sys.sysprocesses WHERE (spid = ##SPID))'.
How can I get the user name in Access?
I found the solution. There were three problems with my code:
First, I had to link the table sys.sysprocesses from the SQL server into Access.
Second, the command
WHERE ax_id_storage.userID = (SELECT nt_username FROM sys.sysprocesses
WHERE (spid = ##SPID));
had to be changed into
WHERE ax_id_storage.userID = (SELECT nt_username FROM
sys.sysprocesses)
as ##SPID is not executable in Access, onlny in SQL Server itself.
And third, Access does not allow INNER JOINS concatenated without parentheses. Therefore, I had to add them in the following way:
Select a FROM (table1 INNER JOIN table 2 ON table1.a = table2.a) INNER
JOIN table 3 on [...]
I have a similar topic with ODBC, attached tables and ADO connections from the same MS Access Client to a SQL Server DB. There I have found the "nt_username" not working. However, the you have 3 or more different connections the "hostaddress" is a good thing to use.
I first insert a record containing the username into a table (secUserSession_tbl) on the server (with the respective ##SPID) and then I use the following view to propagate the username to all sessions from the same host:
CREATE VIEW secSessionUser_vw
AS
SELECT su.UserID, su.Login from sys.sysprocesses as sp
INNER JOIN secSessionUser_tbl AS su ON sp.hostprocess = su.hostprocess
WHERE sp.hostprocess = (SELECT hostprocess FROM sys.sysprocesses WHERE spid = ##SPID)
This view can now be joined with every table or view and returns a username and/or respective permissions.

Determine column data types in PostgreSQL

I'm interacting with a PostgreSQL on command-line based environment, and I'd like to be able to determine the data types of the table columns in this database.
For a simple example, when I request
SELECT * FROM products
I'd like to know if the product id column it returns is giving me text or integers.
You can get this kind of information by querying the catalog.
To find the specific queries, run psql -E (to echo hidden query) and then e.g. \d products. You'll see psql output various queries that yield information about your table, its column types, indexes, etc.
In this specific case, you'd run something like:
SELECT a.attname,
pg_catalog.format_type(a.atttypid, a.atttypmod)
FROM pg_catalog.pg_attribute a
WHERE a.attrelid = 'products'::regclass AND a.attnum > 0 AND NOT a.attisdropped
ORDER BY a.attnum;

Combine dynamic columns with select query

I am using a PostgreSQL database. I have one select query:
select userid, name, age from tbluser;
Now there is another table, tblcalculatedtax, which is generated on the fly and their column names are not predefined, the only mapping between that table and this table is userid. I want to get records after joining two tables. How can I get that?
Simpler:
SELECT *
FROM tbluser
JOIN tblcalculatedtax USING (userid)
Details in the fine manual about SELECT.
Your need SQL Joins. Here's a W3Schools tutorial: http://www.w3schools.com/sql/sql_join.asp
To quickly answer your question, though:
SELECT * FROM tbluser
INNER JOIN tblcalculatedtax
ON tbluser.userid=tblcalculatedtext.userid
The * selects all the columns, so you don't need to know their names. Of course, I'm not sure what use a column is to you if you don't know it's name: do you know what data it contains?