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

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.

Related

Postgres - How to join on two columns?

I have a table containing account information:
And another table, containing transactions information:
I'd like to retrieve both the titles from transactions.from_acc_id and transactions.to_acc_id
So far, I'm only able to retrieve either one or the other with the following JOIN:
SELECT transactions.transaction_type,
transactions.from_acc_id,
transactions.to_acc_id,
transactions.amount,
account.title AS "ACCOUNT DESTINATION"
FROM transactions
JOIN account
ON transactions.to_acc_id = account.acc_id
This gives me the title of transactions.to_acc_id.
How can I add another field containing the title of transactions.from_acc_id with the same SELECT statement, please ?
Thanks
EDIT: I'd like to keep all field from the Select statement, adding the title of transactions.from_acc_id where is pertinent
You join your account table in twice and give each instance its own alias. Furthermore, to ensure that every record from transactions table shows up and only those records from your accounts table (both source and destination), use a LEFT OUTER JOIN instead of your implicit INNER JOIN that you are currently using.
SELECT transactions.transaction_type,
transactions.from_acc_id,
transactions.to_acc_id,
transactions.amount,
dest.title AS "ACCOUNT DESTINATION",
src.title AS "ACCOUNT SOURCE"
FROM transactions
LEFT OUTER JOIN account as dest
ON transactions.to_acc_id = dext.acc_id
LEFT OUTER JOIN account as src
ON transactions.from_acc_id = src.acc_id
For more information on types of joins that are available in most databases, check out W3Schools SQL Joins page
Simply join the table twice. Use table aliases to tell the source account from the target account.
SELECT
t.transaction_type,
t.from_acc_id,
t.to_acc_id,
t.amount,
from_acc.title AS from_account,
to_acc.title AS to_account
FROM transactions t
LEFT JOIN account from_acc ON from_acc.acc_id = t.from_acc_id
LEFT JOIN account to_acc ON to_acc.acc_id = t.to_acc_id

Tableau ERROR: column reference "datasource" is ambiguous; Error while executing the query Unable to create extract

I am trying to create a tde file from a live data source. I am connecting to multiple materialized views in postgres so the data source is a custom sql query. Everything in the workbook runs fine while live but when I try to extract the data, I receive the error:
ERROR: column reference "datasource" is ambiguous; Error while executing the query
Unable to create extract
I do have multiple tables with the same field name so I aliased each of the fields accordingly in my custom query. It seems that when Tableau creates their query for extract, the aliasing isn't recognized. Any help is very appreciated.
SELECT
i.trx_line_id
,i.datasource
,ie.category_type
,ss.trx_line_id
,ss.datasource
,pl.pl_cd
FROM invoice i
LEFT JOIN sales_structure ss ON i.trx_line_id = ss.trx_line_id
LEFT JOIN invoice_ext ie ON i.trx_line_id = ie.trx_line_id
LEFT JOIN product_level pl ON i.pl_cd = pl.pl_cd
WHERE ss.sales_team_rpt IN ('a','b')
You are returning to Tableau a set of data where fields (datasource and trx_line_id) have the same name. A simple fix would be to alias those fields:
SELECT
i.trx_line_id AS invoice_line_id, -- Aliased
i.datasource AS invoice_datasource, -- Aliased
ie.category_type,
ss.trx_line_id AS sales_structure_line_id, -- Aliased
ss.datasource AS sales_structure_datasource, -- Aliased
pl.pl_cd
FROM
invoice i
LEFT JOIN
sales_structure ss ON i.trx_line_id = ss.trx_line_id
LEFT JOIN
invoice_ext ie ON i.trx_line_id = ie.trx_line_id
LEFT JOIN
product_level pl ON i.pl_cd = pl.pl_cd
WHERE
ss.sales_team_rpt IN ('a','b');

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

How to list tables from accessible via database links?

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

Inconsistent results between remote and local query

I have an interesting case of results sets returned by SQL Server being different depending on whether a query is executed locally or remotely.
In essence, if I execute the following query:
SELECT p.ID AS Id
FROM csdb.users.People AS p
LEFT JOIN csdb.users.Accounts AS a ON p.ID = a.IdentityId
then the left join is performed, and I obtain 633 rows back. However, if I execute the query remotely as:
SELECT p.ID AS Id
FROM quantdb.csdb.users.People AS p
LEFT JOIN quantdb.csdb.users.Accounts AS a ON p.ID = a.IdentityId
then the left join is not performed, an index scan of the People table is performed, and only 564 records are returned. In essence it seems as if in the remote case the optimiser is saying 'well, you are not requiring any of the columns from the Accounts table so I won't do the join' whereas in the other case it is saying 'I will do the join'.
Is this difference in behaviour of the optimiser for remote and local queries a known 'feature' of SQL Server, or is this a bug?
We are using SQL Server 2008, SP1
Not doing the join is a valid optimization if there is a unique constraint on Accounts.IdentityId, because the join cannot add any new row (a non-unique column would cause p.ID to repeat for each corresponding duplicate in Accounts.IdentityId).
Can you post the exact schema of the tables, including all indexes and constraints? I want to see if it reproes.