Using Sequence for inserting - sql

I want to insert a new row in my table.
There I want to put the ID with the help of seq_name.nextval.
So how to know the sequence name for that particular table?

To use a sequence to generate IDs, you create it normally in the schema where the table is.
As user application user GEM_APP:
CREATE TABLE my_table (id NUMBER, col1 ...);
CREATE SEQUENCE my_seq;
The application user itself (and f.i. it's stored procedures) can use the sequence directly:
INSERT INTO my_table (id, col1) VALUES (my_seq.nextval, 'bla');
However, other users need the correct privileges. Usually, you grant select rights on the sequence to the same users or roles you grant insert rights on the table:
GRANT SELECT, INSERT ON my_table TO user_xy;
GRANT SELECT ON my_seq TO user_xy;
Then the other user can insert data into the table, but must qualify the schema:
INSERT INTO gem_app.my_table(id, col1) VALUES (gem_app.my_seq.nextval, 'bla');
You can create aliases to hide the schemas, some people like them, some not, but I would definitely not recommend to use PUBLIC synonyms as they are hard to control and create all kind of namespace clashes.

Related

Is there a way to give a user access to different columns on different rows of a table in PostgreSQL?

Is there a way to give a PostgreSQL user access to a different columns on different rows of a table? For example in the following table, is there some combination of GRANT or POLICY or ??? that would only allow the user to view the "allowed" cells?
CREATE TABLE my_table (
id INT,
col_a TEXT,
col_b TEXT
);
INSERT INTO my_table VALUES
(1, 'allowed', 'allowed'),
(2, 'allowed', 'forbidden')
;
I think it can be done by splitting the columns in to different tables, but is it possible with only a single table?
One possible solution suggested by O. Jones - use a view:
CREATE OR REPLACE VIEW my_secure_view AS
SELECT
id,
col_a,
CASE WHEN id = 1 THEN col_b ELSE NULL END AS col_b
FROM my_table;
GRANT SELECT ON my_secure_view TO whatever_user;
REVOKE SELECT ON my_table FROM whatever_user;
Is there a better way?
You can do this by creating a VIEW containing the rows and columns you allow your user to see, then granting the user SELECT access to the view but not the underlying table.
For example
CREATE OR REPLACE VIEW my_secure_view AS
SELECT allowedcol1, allowedcol2
FROM my_table
WHERE col_b <> 'forbidden';
GRANT SELECT ON my_secure_view TO whatever_user;
REVOKE SELECT ON my_table TO whatever_user;
You can also, if you wish, write stored procedures and grant access to them to the users you choose, while revoking access to the underlying tables.

Role to access the table only but not data from Table in Oracle Exadata

Users have create table statement with select statement from multiple tables from multiple schema. I want to restrict them to read data and allow them to create empty table in their schema with metadata only not data. This I want to do at user access and roles level.
Please tell me how I can do this?
I have tried giving them read access on underlying tables but users can see data as well.
Create table cust_acct_details
as
select *
from ep_rel.acct a
inner join ep_dnf.Cust_account ca
on a.acct_id = ca.acct_id
Tables should create without data.
Add below condition to your code
-- condition to add where 1<>1
Create table cust_acct_details
as
select *
from ep_rel.acct a
inner join ep_dnf.Cust_account ca
on a.acct_id = ca.acct_id
where 1<>1
Please make sure there are unique column names in your select statement. Oracle will not allow same column name in one table. Please use alias instead of *.
If you remove all tablespace privileges from a user they can still create tables but they won't be able to populate them.
For example, if you run this PL/SQL block to revoke all tablespace quotas from one user:
begin
for users in
(
select 'alter user '||username||' quota 0 on '||tablespace_name v_sql
from dba_ts_quotas
where username = 'TEST_USER'
order by 1
) loop
execute immediate users.v_sql;
end loop;
end;
/
Now the user can create tables but will get an error if they try to add rows:
SQL> create table test1(a number);
Table created.
SQL> insert into test1 values(1);
insert into test1 values(1)
*
ERROR at line 1:
ORA-01536: space quota exceeded for tablespace 'USERS'
For metadata, users can always see the metadata in their own schema. To allow them to view the metadata in other schema, run a grant like:
grant select_catalog_role to the_user;
Then that user can view the metadata either in the ALL_ data dictionary views, or using DBMS_METADATA.GET_DDL.

PostgreSQL query using table without permission

I am dealing with a remote data base where I have permission to only access specific tables.
The relevant data has the form:
CREATE TABLE t_a(v_a VARCHAR(32), v_b VARCHAR(32));
CREATE TABLE t_b(v_b VARCHAR(32), v_c VARCHAR(32));
INSERT INTO t_a VALUES ('one', 'abc1');
INSERT INTO t_a VALUES ('two', 'abc2');
INSERT INTO t_a VALUES ('three', 'abc3');
INSERT INTO t_b VALUES ('abc1', 'eins');
INSERT INTO t_b VALUES ('abc2', 'zwei');
INSERT INTO t_b VALUES ('abc3', 'drei');
My query looks like:
SELECT DISTINCT ON (v_a) v_a, v_c FROM t_a, t_b WHERE t_a.v_b = t_b=v_b;
Now the actual question: Can I somehow get the same information without permission to read from t_b? Is there another approach I could try?
EDIT
Sadly, I do not have the rights to change the permissions. My line of thought was that since I only want to have an association between v_a and v_c, I could get away with not selecting any columns from t_b. After a bit more thinking, I can see why this should not be allowed by the permission system - after all, I try to read some information from t_b.
I was also hoping that maybe there are different permission layers where one of them permits non-selecting queries.
You can create that table with a different account that either owns it or has been GRANTED read to the table. You than create a stored function created by the same account that owns or has rights to read the table. GRANT EXECUTE to the new function to you personal account that doesn't have rights to the table. Execute the new function and you can get at the data. This is called SECURITY DEFINER and more can be read here http://www.postgresql.org/docs/9.3/static/sql-createfunction.html
With this setup your account won't have access to the table directly, like by doing select * from your_table. You can only get to it via the function. Same can be done with views and is how a lot of database designs setup access to tables. The function or view is the public interface

Automatically create record when another is created

I have two tables in my database: Users, Roles and Membership. The Membership table assigns users to specific Roles.
How could I automatically create the Membership record for anytime a new record is inserted in Users.
Example: When a user is created and assigned an ID number (# 562), The database would automatically add them to the Membership table with a specific role ID.
How could I do this?
Write an AFTER INSERT TRIGGER on Users TABLE, that will INSERT the new Row in the Membership table.
http://msdn.microsoft.com/en-us/magazine/cc164047.aspx
Assuming you have a Default RoleID for your new Membership row, when a new User is inserted in Users table, something like this should work.
CREATE TRIGGER TRI_USERS_INSERT on Users
AFTER INSERT
AS
SET NOCOUNT ON
-- If you have a Default RoleID, select that into a variable and use it in the INSERT below.
-- For this example, I am using just the number 1
-- Also assumes that the ID for Memberships table is AUTO GENERATED, so it's not in INSERT list.
INSERT INTO Memberships (UserID, RoleID)
SELECT ID, 1 FROM INSERTED
GO

How do I make one user see a different table with same name

Goal: When everybody else does SELECT * FROM mytable they see one version of the table. But when a specific user does SELECT * FROM mytable they see another version of the table.
I think I'm like halfway there with creating a new role and putting the single user in it. Then creating a copy of the default table with SELECT * INTO newrole.mytable FROM dbo.mytable. But when the user does SELECT * FROM mytable they still see the dbo.mytable. How do I get them to default to the newrole.mytable? I still need them to see all the other dbo tables just not this one.
Create a new schema, and a duplicate table (or view onto dbo.table if that's what you want) in it - eg., otheruser.table. Then, set the user's login to default to that schema:
USE atest
GO
CREATE ROLE [arole]
GO
CREATE SCHEMA [aschema] AUTHORIZATION [arole]
GO
CREATE USER [auser] FOR LOGIN [modify_user] WITH DEFAULT_SCHEMA = aschema
GO
EXEC sp_addrolemember 'arole', 'auser'
GO
CREATE TABLE dbo.atable ( col1 int )
GO
CREATE TABLE aschema.atable (col2 varchar(10))
GO
INSERT INTO dbo.atable( col1 ) VALUES( 1 )
GO
INSERT INTO aschema.atable( col2 ) VALUES( 'One' )
GO
PRINT 'dbo'
SELECT * FROM atable
GO
EXECUTE AS USER = 'auser'
GO
PRINT 'aschema'
SELECT * FROM atable
GO
REVERT
GO
I don't know if this may help but you may be able to make a view of a different table with the same name, here is an excerpt from http://www.w3schools.com/SQl/sql_view.asp:
In SQL, a view is a virtual table based on the result-set of an SQL statement.
A view contains rows and columns, just like a real table. The fields in a view are fields from one or more real tables in the database.
You can add SQL functions, WHERE, and JOIN statements to a view and present the data as if the data were coming from one single table.
I use Postgres primarily, so YMMV, but in postgres you need to
1) Create the new schema, preferably owned by the new role, and put the table in it
2) Set the search_path variable to include that schema BEFORE the other one.
Hope it helps.
This is a very bad idea. I'm not sure why people try all these crazy methods to improve security but it's just plain counter productive.
Ultimately every security system comes down to some line like the following if(User.HasAccessTo(object)). In fact, if you've designed a well thought out security system that's almost exactly how it should work. The more disjointed your authentication checks, the more likely you'll make a mistake. If only some users have access to certain record information you should add a flag to those records and verify access based on that.