The table ALL_CONS_OBJ_COLUMNS table does not have data - sql

I'm trying to obtain data from de data dictionary that Oracle provides to its databases. When I execute the query:
SELECT TABLE_NAME
FROM ALL_CONSTRAINTS;
I get the names from the tables I own as user and the tables other users have granted me access to (Around 130). Now, when I try to execute
SELECT TABLE_NAME
FROM ALL_CONS_OBJ_COLUMNS;
I get nothing, the result is an empty table. Does that make sense? As the docs says "displays information about the types that object columns (or attributes) or collection elements have been constrained to, in the tables accessible to the current user.", I think it should display the same table the previous query did.

I was wrong: I'm looking for ALL_CONS_COLUMNS. That table does not have all the names of the preiovus one, but has the ones I need. I guess I not fully understand the notion of objects yet.

Related

Fetch all views in oracle db along with details like number of rows,columns, primary keys etc

I'm trying to write a query for retrieving all the views in oracle database along with number of rows, columns and primary keys of each view.
i tried 'all_views', but it doesn't give what i need.
Can someone help me with this?
Thanks in advance
all_views tells you the name of the views (that you have access to, there may be more in the system). all_tab_columns will give you the names of the columns. As #GerardH.Pille points out, views do not have primary keys. You'd need to run a select against each view in turn to determine the number of rows it can return (remembering that a view could have logic that filters by a session variable, a context, or some other session-specific setting) so that different users or different sessions may get different results. That could get rather expensive depending on your system.

How do I give different users access to different rows without creating separate views in BigQuery?

In this question: How do I use row-level permissions in BigQuery? it describes how to use an authorized view to grant access to only a portion of a table. But I'd like to give different users access to different rows. Does this mean I need to create separate views for each user? Is there an easier way?
Happily, if you want to give different users access to different rows in your table, you don't need to create separate views for each one. You have a couple of options.
These options all make use of the SESSION_USER() function in BigQuery, which returns the e-mail address of the currently running user. For example, if I run:
SELECT SESSION_USER()
I get back tigani#google.com.
The simplest option, then, for displaying different rows to different users, is to add another column to your table that is the user who is allowed to see the row. For example, the schema: {customer:string, id:integer} would become {customer:string, id:integer, allowed_viewer: string}. Then you can define a view:
#standardSQL
SELECT customer, id
FROM private.customers
WHERE allowed_viewer = SESSION_USER()
(note, don't forget to authorize the view as described here).
Then I'd be able to see only the fields where tigani#google.com was the value in the allowed_viewer column.
This approach has its own drawbacks, however; You can only grant access to a single user at a time. One option would be to make the allowed_viewer column a repeated field; this would let you provide a list of users for each row.
However, this is still pretty restrictive, and requires a lot of bookkeeping about which users should have access to which row. Chances are, what you'd really like to do is specify a group. So your schema would look like: {customer:string, id:integer, allowed_group: string}, and anyone in the allowed_group would be able to see your table.
You can make this work by having another table that has your group mappings. That table would look like: {group:string, user_name:string}. The rows might look like:
{engineers, tigani#google.com}
{engineers, some_engineer#google.com}
{administrators, some_admin#google.com}
{sales, some_salesperson#google.com}
...
Let's call this table private.access_control. Then we can change our view definition:
#standardSQL
SELECT c.customer, c.id
FROM private.customers c
INNER JOIN (
SELECT group
FROM private.access_control
WHERE SESSION_USER() = user_name) g
ON c.allowed_group = g.group
(note you will want to make sure that there are no duplicates in private.access_control, otherwise it could records to repeat in the results).
In this way, you can manage the groups in the private.access_control separately from the data table (private.customers).
There is still one piece missing that you might want; the ability for groups to contain other groups. You can get this by doing a more complex join to expand the groups in the access control table (you might want to consider doing this only once and saving the results, to save the work each time the main table is queried).

User defined data types in T-sql

I had a look in the tables I am using in my database based on Rapid SQL. In one of the table i was just checking columns used in that table. I used sp_help table_name to find out the details of columns, datatypes and other things. I found some data types as T_gender_domain, T_name_domain, T_phone_domain. Are they used as a user defined data types???

How to restrict SQL columns based on id of requester?

In my application a requester has permission to query only certain columns. The columns may differ between requesters. The where clause changes between requests so that the rows returned change with each query. What is the best way to handle this access control? Should I use an array to store permitted columns and then do the check in my application?
I'm on PostgreSQL 9.x
Example:
We have medical professionals that can access records of patients but not all medical professionals should be able to access all information. They try to request arbitrary information about any patient (which have a uid) but we should enforce access controls.
So say the info is name, date of birth, blood type and illness
Doctor A has permission for all fields
Doctor B can see everything except blood type
Administrator can only see name and date of birth
Hematologist can only see blood type
To implement option 2, I would have a column permissions table something like the following:
CREATE TABLE ColumnPerms
(
user_or_role Varchar(50),
table_name Varchar(50),
column_name Varchar(50),
)
CREATE INDEX ix_Columnperms(user_or_role, table_name)
The *table_name* column is to allow this functionality to be implemented on more than just a single table in your app: if it's unnecessary, don't use it. You could adopt the convention that role names start with a '#' character, to ensure that there is no collision with user names.
Now, when you build your dynamic query, you can do something like
SELECT column_name
FROM ColumnPerms
WHERE user_or_role = '#manager'
AND table = 'Payroll'
AND column_name IN ('first_name', 'last_name', 'hire_date', 'base_salary', 'bonus')
(the IN clause should include EVERY column potentially to be returned).
The result of this query is a list of the column names that user is allowed to see. Just iterate through it to build your column list when constructing the dynamic SQL.
There are two approaches you could take:
Use Postgres to enforce the security using column level permissions for each user (or user role). Look at the syntax for GRANT here: http://www.postgresql.org/docs/current/static/sql-grant.html
Build dynamic sql statements limiting what rows may be returned for each user. This could become pretty tedious if there are many users, or many different column combinations. You'll probably want to keep a table of user ids, and "selectable" table, column names for building the query statement. If you want this generalized to many different queries, you could either build them on top of a table-returning function that does the column filtering, or revert to option 1.
For option 1, make sure that columns used in the join are selectable...

How can i design a DB where the user can define the fields and types of a detail table in a M-D relationship?

My application has one table called 'events' and each event has approx 30 standard fields, but also user defined fields that could be any name or type, in an 'eventdata' table. Users can define these event data tables, by specifying x number of fields (either text/double/datetime/boolean) and the names of these fields. This 'eventdata' (table) can be different for each 'event'.
My current approach is to create a lookup table for the definitions. So if i need to query all 'event' and 'eventdata' per record, i do so in a M-D relaitionship using two queries (i.e. select * from events, then for each record in 'events', select * from 'some table').
Is there a better approach to doing this? I have implemented this so far, but most of my queries require two distinct calls to the DB - i cannot simply join my master 'events' table with different 'eventdata' tables for each record in in 'events'.
I guess my main question is: can i join my master table with different detail tables for each record?
E.g.
SELECT E.*, E.Tablename
FROM events E
LEFT JOIN 'E.tablename' T ON E._ID = T.ID
If not, is there a better way to design my database considering i have no idea on how many user defined fields there may be and what type they will be.
There are four ways of handling this.
Add several additional fields named "Custom1", "Custom2", "Custom3", etc. These should have a datatype of varchar(?) or similiar
Add a field to hold the unstructured data (like an XML column).
Create a table of name /value pairs which are associated with some type of template. Let them manage the template. You'll have to use pivot tables or similiar to get the data out.
Use a database like MongoDB or another NoSql style product to store this.
The above said, The first one has the advantage of being fast but limits the number of custom fields to the number you defined. Older main frame type applications work this way. SalesForce CRM used to.
The second option means that each record can have it's own custom fields. However, depending on your database there are definite challenges here. Tried this, don't recommend it.
The third one is generally harder to code for but allows for extreme flexibility. SalesForce and other applications have gone this route; including a couple I'm responsible for. The downside is that Microsoft apparently acquired a patent on doing things this way and is in the process of suing a few companies over it. Personally, I think that's bullcrap; but whatever. Point is, use at your own risk.
The fourth option is interesting. We've played with it a bit and the performance is great while coding is pretty darn simple. This might be your best bet for the unstructured data.
Those type of joins won't work because you will need to pivot the eventdata table to make it columns instead of rows. Therefore it depends on which database technology you are using.
Here is an example with MySQL: How to pivot a MySQL entity-attribute-value schema
My approach would be to avoid using a different table for each event, if that's possible.
I would use something like:
Event (EventId, ..., ...)
EventColumnType (EventColumnTypeId, EventTypeId, ColumnName)
EventColumnData (EventColumnTypeId, Data)
You are them limited to the type of data you can store (everything would have to be strings, for example), but you the number of events and columns are unrestricted.
What I'm getting from your description is you have an event table, and then a separate EventData table for each and every event.
Rather than that, why not have a single EventCustomFields table that contains a foreign key to the event table, a field Name (event+field being the PK) and a field value.
Sure it's not the best. You'd be stuck serializing the value or storing everything as a string. And you'd still be stuck doing two queries, one for the event table and one to get it's custom fields, but at least you wouldn't have a new table for every event in the system (yuck x10)
Another, (arguably worse) option is to serialize the custom fields into a single column of the and then deserialize when you need. So your query would be something like
Select E.*, C.*
From events E, customFields C
Where E.ID = C.ID
Is it possible to just impose a limit on your users? I know the tables underneath Sharepoint 2007 had a bunch of columns for custom data that were just named like CustomString1, CustomDate2, etc. That may end up easier than some of the approaches above, where everything is in one column (though that's an approach I've taken as well), and I would think it would scale up better.
The answer to your main question is: no. You can't have different rows in the result set with different columns. The result set is kind of like a table, so each row has to have the same columns. You can fake it with padding and dummy columns, but that's probably not much better.
You could try defining a fixed event data table, with (say) ten of each type of column. Then you'd store the usage metadata in a separate table and just read that in at system startup. The metadata would tell you that event type "foo" has a field "name" mapped to column string0 in the event data table, a field named "reporter" mapped to column string1, and a field named "reportDate" mapped to column date0. It's ugly and wastes space, but it's reasonably flexible. If you're in charge of the database, you can even define a view on the table so to the client it looks like a "normal" table. If the clients create their own tables and just stick the table name in the event record, then obviously this won't fly.
If you're really hardcore you can write a database procedure to query the table structures and serialize everything to a lilst of key/type/value tuples and return that in one long string as the last column, but that's probably not much handier than what you're doing now.