PostgreSQL query using table without permission - sql

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

Related

Chaining multiple queries in SQL

I'm using postgresql if that matters.
I need to write into 2 different tables when a new user is created and I want to make sure either both queries fail or both of them succeed. If one of them fails, the other should not succeed.
Lets say I've a table named users and another table named houses and whenever a user is created I give them a house.
user table:
userid(int,auto generated) , username(text), password(text)
houses table:
userid(int) , houseid(int)
when a new user is created, I should call following code:
INSERT INTO users (username , password ) VALUES ('a value', 'a value') RETURNING userid;
INSERT INTO houses (userid, houseid ) VALUES ('returned_value' , 'a value');
but if first query succeeds and the second one fails for whatever reason, that means this will create a user without home. How can I chain these 2 queries together so either both of them succeeds or both of them fails.
Transaction is the way you manage what you want to do here, I mean have one global commit only.
With postgresql, the syntax for managing transactions is the following:
BEGIN;
INSERT INTO users (username , password ) VALUES ('a value', 'a value') RETURNING userid;
INSERT INTO houses (userid, houseid ) VALUES ('returned_value' , 'a value');
COMMIT;

ORA-00942 cannot find table

I ran these statements:
create table SAMPLE(
ID INT
);
INSERT INTO SAMPLE VALUES(1);
COMMIT;
GRANT INSERT, SELECT, UPDATE, DELETE ON SAMPLE TO NEWLEC;
COMMIT;
But Eclipse says cannot find the table.
How can I resolve it?
You are connecting as the newlec user, and unqualified references to tables will look for them in that schema, not under other users.
You can qualify the table name:
SELECT * FROM real_owner.SAMPLE
For example, if you were connected as HR when you created the table, you would do:
SELECT * FROM HR.SAMPLE
You could also create a public synonym, which is probably overkill and can cause other issues and confusion; or create a private synonym for the newlec user which points to the rea table, e.g.:
CREATE SYNONYM SAMPLE FOR real_owner.SAMPLE;
SELECT * FROM SAMPLE;
so the unqualified query now sees the synonym, and through that the real table owned by someone else. Or you could set your current_schema after logon:
ALTER SESSION SET CURRENT_SCHEMA=real_owner;
SELECT * FROM SAMPLE;
so all unqualified queries now see objects owned by that user, not newlec.
However, if this is a basic assignment on a beginner course then you are probably just expected to qualify the name.

Using Sequence for inserting

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.

Can't see created tables in Object Explorer - Microsoft SQL Management Studio

I am trying to create some tables within a database, however the tables are not appearing in my object explorer view.
my code is as follows:
use testDB
GO
create table dbo.teacher (id varchar(5), name varchar(24));
insert into teacher values ('dm112', 'Magro, Deirdre');
insert into teacher values ('je232', 'Elkner, Jeff');
insert into teacher values ('cm147', 'Meyers, Chris');
insert into teacher values ('kr387', 'Reed, Kevin');
create table dbo.course (
number varchar(6),
name varchar(24),
credits int,
teacherid varchar(6)
);
insert into course values ('SDV100', 'College Success Skills', 1, 'dm112');
insert into course values ('ITD110', 'Web Page Design I', 3, 'je232');
insert into course values ('ITP100', 'Software Design', 3, 'je232');
insert into course values ('ITD132', 'Structured Query Language', 3, 'cm147');
insert into course values ('ITP140', 'Client Side Scripting', 4, 'kr378');
insert into course values ('ITP225', 'Web Scripting Languages', 4, 'kr387');
create table dbo.student (id varchar(3), name varchar(24));
insert into student values ('411', 'Perez, Gustavo');
insert into student values ('412', 'Rucker, Imani');
insert into student values ('413', 'Gonzalez, Alexis');
insert into student values ('414', 'Melgar, Lidia');
create table dbo.enrolled (studentId varchar(3), courseNumber varchar(6));
insert into enrolled values ('411', 'SDV100');
insert into enrolled values ('411', 'ITD132');
insert into enrolled values ('411', 'ITP140');
insert into enrolled values ('412', 'ITP100');
insert into enrolled values ('412', 'ITP14p');
insert into enrolled values ('412', 'ITP225');
insert into enrolled values ('413', 'ITD132');
insert into enrolled values ('413', 'ITP225');
insert into enrolled values ('414', 'SDV100');
insert into enrolled values ('414', 'ITD110');
I looked this up before posting and found this exact question:
Creating table with T-SQL - can't see created tables in Object explorer
However, he was using "tempdb", which I am not.
I ran the query
select name, type_desc from testDB.sys.objects
which returned:
name type_desc
---------------------------
...
teacher USER_TABLE
course USER_TABLE
student USER_TABLE
enrolled USER_TABLE
...
I can modify, select, drop, etc. on these tables, but I cannot see them. Am I missing something? Another question brought up the prospect of "test" and "production"? They didn't go into much detail and google did not help me
:(
Thank you for any help you can offer.
Edit: Karl below found the solution! Although clicking refresh (F5) on the object explorer does not update the database view, right clicking on the database and clicking refresh updates the tables.
This would happen if you have the tables node open in object explorer and don't refresh after running your DDL. It is annoying that SSMS doesn't autorefresh explorer after DDL. Refresh is available via the right-click context menu in object explorer.
I had a scenario in which refreshing the folders in Object Explorer did not lead to my missing table appearing in either of the Tables or Views folders. Like the original post, I am able to query the table - but not find it in Object Explorer.
The Microsoft docs on the FROM clause specify that FROM is followed by table_source which is a qualified table_or_view_name which is defined as "Is the name of a table or view". Yet while my FROM clause works, no such table or view name appears in Object Explorer (even after refresh). What's going on here?
The original question had the following query:
select name, type_desc from testDB.sys.objects
which simplifies to:
select name, type_desc from sys.objects;
and this gave me the answer to my scenario, which differed from the original question.
In the original question the missing table's type_desc value was USER_TABLE, but in my case it showed SYNONYM.
There is, in fact, another folder in Object Explorer for Synonyms - and this is where I found the "table" I was querying. (It would be helpful if Microsoft updated their doc to mention the fact that a Synonym name is also a valid value for use with the FROM clause - at least in my case, synonyms are not frequently used).
Try going to the SQL Server Object Explorer tab, and press that is located right of the refresh button ---> Group By Object.
It was simply showing another Local database server for me..
I had to explicitly click on "Add SQL Server" (the icon beside refresh) and select the correct "MSSQLLocalDB" local Server.
This could be helpful if you are working on multiple projects.
I think you have to update table in DB. if you used visual studio you would easy do it. when you create table you can see button "update" in the left corner of window.
enter image description here

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.