How to list schemas of a specific database in Informix using SQL? - sql

What is the query to get a list of schemas names in a specific database in Informix?

Schemas are not commonly used in Informix databases and have very little trackability within a database. The CREATE SCHEMA notation is supported because it was part of SQL-89. The AUTHORIZATION clause is used to determine the (default) 'owner' of the objects created with the CREATE SCHEMA statement. There is nothing to stop a single user running the CREATE SCHEMA statement multiple times, either consecutively or at widely different times (in any given database within an Informix instance).
CREATE SCHEMA AUTHORIZATION "pokemon"
CREATE TABLE gizmo (s SERIAL NOT NULL PRIMARY KEY, v VARCHAR(20) NOT NULL)
CREATE TABLE widget(t SERIAL NOT NULL PRIMARY KEY, d DATETIME YEAR TO SECOND NOT NULL)
;
CREATE SCHEMA AUTHORIZATION "pokemon"
CREATE TABLE object (u SERIAL NOT NULL PRIMARY KEY, i INTEGER NOT NULL)
CREATE TABLE "pikachu".complain (C SERIAL NOT NULL PRIMARY KEY, v VARCHAR(255) NOT NULL)
;
After the CREATE SCHEMA statement executes, there is no way of tracking that either pair of these tables were created together as part of the same schema; there's no way to know that "pikachu".complain was part of a CREATE SCHEMA statement executed on behalf of "pokemon". There is no DROP SCHEMA statement that would necessitate such support.

A schema belongs to a user. You can list all available users from the sysusers system catalog :
SELECT username FROM "informix".sysusers;
Since only DBAs and Resource privilieges allow a user to issue a CREATE SCHEMA statement, we could restrict the query like :
SELECT username FROM "informix".sysusers WHERE usertype IN ('D', 'R');
Another solution is to list only users that actually have created tables ; for that, you can query the systables system catalog and list distinct owners.
SELECT DISTINCT owner FROM FROM "informix".systables
As commented by #JonathanLeffler, a user could have been granted RESOURCE privileges and have created a table, and then be 'demoted' to CONNECT privileges. The user would still own the table. Hence the second solution is the most accurate.

Related

I have restricted select access at table level in sql server. But users are able to access views which are created top of that table

I have restricted select access at table level for 1 single table 'A'in sql server(2016).
But users are able to access views which are created top of that table 'A'.
when users run select statement on table 'A'(select * from table 'A')users are getting 'select permission is denied on object table 'A' ' message.
when users run select statement on view (select * from view 'A') users are able to access all data.
Users are able to create new views by writing select statement on table 'A'.
How can i restrict users to access table 'A' from views as well.
This is expected behavior due to ownership chaining. Permissions on tables referenced by the view are not checked as long as the view and tables have the same owner (AUTHORIZATION).
To break the ownership chain, you could either move the table to a different schema (owned by a different user than the view schema) or change to owner of the table. Examples below.
--move table to different schema
CREATE USER RestricedTablesOwner WITHOUT LOGIN;
GO
CREATE SCHEMA RestricedTables AUTHORIZATION RestricedTablesOwner;
GO
ALTER SCHEMA RestricedTables TRANSFER dbo.A;
GO
--change table to different owner, retaining same schema
ALTER AUTHORIZATION ON OBJECT::dbo.A TO RestricedTablesOwner;

Is there any way in DB2 to find temp table from the session?

Is there any way in DB2 to find temp table from the session ?
I have created a temp table pertaining to session
DECLARE GLOBAL TEMPORARY TABLE SESSION.TEMP_TABLE_NAME
(
COL_1 VARCHAR(11) NOT NULL,
COL_2 VARCHAR(10)
) ON COMMIT PRESERVE ROWS;
When I am trying to create query
select * from sysibm.systables where owner='SESSION' and name='TEMP_TABLE_NAME'
yields 0 rows.
Am I looking at the incorrect table to find temp tables ?
Thanks !
A declared global temporary table ( DGTT) will not appear in the catalog, this is the design - so you will not find a DGTT in sysibm.systables. A DGTT cannot be used by any other program except the one that declares it - it is specific to that session, hence there's no value to having it in the catalogue.
If you are using Db2 for z/OS (v10 or higher), or Db2-LUW, you may need instead, a "CREATED global temporary table" (CGTT) which uses a different syntax create global temporary table ... These are catalogued, but you need relevant permissions to create them.
See the Db2-LUW documentation.
or for Db2 for z/OS here.
Look at the SYSIBMADM.ADMINTEMPTABLES administrative view.
If you want to see all the DGTTs created in your session, then:
SELECT TABNAME
FROM SYSIBMADM.ADMINTEMPTABLES
WHERE TEMPTABTYPE='D'
AND APPLICATION_HANDLE=mon_get_application_handle();

Retrieving entries of linked list in relational database

For my project, I implemented linked list with rdbms. The linked list uses rowid column as a pointer, and contains prior, next and owner pointer(from different table).
The simple example would be like this.
CREATE TABLE EMPLOYEE
(
EMP_ID NUMBER(4) NOT NULL,
OFFICE_CODE CHAR(2),
OFF_EMP_prior ROWID,
OFF_EMP_next ROWID,
OFF_EMP_owner ROWID
);
{EMP1,(NULL,EMP2,OFF1)} - {EMP2,(EMP1,EMP3,OFF1)} - {EMP3,(EMP2,NULL,OFF1)}
Now I have to implement a retrieval function like "Find 'nth(integer)' entry of the list which has 'OFF1' as a owner".
This can be simply done by using loop to traverse the linked list. But this requires too many SQL operations for one retrieval. (I know that using sequence number can be another option, but this is the decision made so far.)
Instead, I found SELECT - CONNECTED BY in oracle SQL, and tried
select * from EMPLOYEE
where OFF_EMP_owner = [OFF_ROWID]
connect by nocycle OFF_EMP_prior = rowid;
This query works for retrieving entries of the list, but the order of the result is not as I expected (something like EMP3-EMP1-EMP2).
Is it possible to retrieve entries of the linked list and sort them by the order of the list with SELECT-CONNECT BY'? Or is there exists more suitable SQL?
select * from EMPLOYEE
where DEPT_EMPLOYEE_owner = [OWNER_ROWID}
start with OFF_EMP_prior is NULL
connect by OFF_EMP_prior = prior rowid;
Solved the problem with the query above. 'prior' should be used instead of nocycle.

SQL Server - Display the username in a column

We have a SQL Server 2012 database that 4 developers use, lets call them, user1, user2, user3, user4.
I want to create a column in one of the tables lets call the column User_Input, this column needs to show the username of the developer who insert any data, is this possible? For example if user2 inserted a new record, the column User_Input should display user2.
Please let me know if SQL Server does not support that, and if there is any other solution cause I searched the ## functions for SQL Server and non of them seems to get the username.
SYSTEM_USER function will return the login name of the user.
You can test it out with this statement:
SELECT SYSTEM_USER
The MSDN documentation for SYSTEM_USER states:
You can use the SYSTEM_USER function with DEFAULT constraints in the
CREATE TABLE and ALTER TABLE statements. You can also use it as any
standard function.
Here is a quick example of how to create a table with DEFAULT constraint that inserts the SYSTEM_USER into the User_Input column.
CREATE TABLE MyTable
(
ID int,
Value varchar(30),
User_Input varchar(200) DEFAULT SYSTEM_USER
)
I believe this is what you're looking for.
SELECT SYSTEM_USER
You can add this to inserts/updates as needed.
CURRENT_USER provides the schema, not the login associated with the transaction.

Alternative to check constraints in Views

So I have two tables:
Requests
--------
Id
RequestSchemeId
ReceivedByUserId
ForwardedRequests
-----------------
Id
RequestId (FK to Id column of Requests Table)
ForwardedToUserId
and one view
ForwardedRequestsInRequestSchemes
---------------------------------
Requests.RequestSchemeId
Requests.ReceivedByUserId
ForwardedRequests.ForwardedToUserId
What's the standard/recommended way of adding a constraint equivalent to Requests.ReceivedByUserId != ForwardedRequests.ForwardedToUserId in the view?
I know check constraints are not allowed in views. Using SQL Server 2008.
EDIT:
This is a followup question to this question.
Business rules:
The same request can be forwarded to multiple users. Hence the Id column in the ForwardedRequests table.
A user can receive only one Request for a particular RequestScheme. So I created a UniqueKey constraint for RequestSchemeId+ReceivedByUserId in the Requests table.
The request can be forwarded to another user only if forwarded user does not already have a forwarded request under the same scheme from any other user. So as Martin suggested in the linked question, I created a view from the two tables and added a unique constraint on Requests.RequestSchemeId+ForwardedRequests.ForwardedToUserId.
The business rule this question is about, is that the receiver of the request cannot forward it to himself/herself.
I can think of a couple of ways of getting SQL Server to enforce this for you. Both pretty hacky though so interested to see any other approaches.
1) You could add to the indexed view ForwardedRequestsInRequestSchemes an additional column 1/(ForwardedToUserId - ReceivedByUserId) AS FailIfSame which would raise a Divide by zero error if the two values are the same. This does mean that you end up storing a redundant column in the indexed view though.
2) You could create a new view that returns any such rows cross joined onto a two row table then define a unique constraint on that view. This view will always be empty.
CREATE TABLE dbo.TwoRows(C INT) INSERT INTO dbo.TwoRows VALUES(1),(1)
GO
CREATE VIEW dbo.FailIfForwardedUserEqualToReceivedByUser
WITH SCHEMABINDING
AS
SELECT 1 AS C
FROM dbo.ForwardedRequests FR
INNER JOIN dbo.Requests R
ON R.Id = FR.RequestId AND R.ReceivedByUserId = FR.ForwardedToUserId
CROSS JOIN dbo.TwoRows
GO
CREATE UNIQUE CLUSTERED INDEX ix ON
dbo.FailIfForwardedUserEqualToReceivedByUser(C)
One way is to disallow update, insert, delete rights on the tables, and enforce the business requirement using a stored procedure. For example,
create procedure dbo.AddRequestForward(
#requestId int
, #forwardedToUserId int)
as
insert ForwardedRequests
(ForwardedRequests, ForwardedRequests)
select #requestId
, #forwardedToUserId
where not exists
(
select *
from Requests
where Id = #requestId
and #forwardedToUserId = #forwardedToUserId
)
if ##rowcount = 0
return -1 -- Forwarded and Received identical user
return 1 -- Success
go