PosgreSQL - ERROR: relation "table_name" does not exist. How to query without schema name? - sql

I am migrating from oracle to postgreSQL.
In my application I have a lot of queries like this
ResultSet resultSet = statement.executeQuery("SELECT NAME FROM Table_name");
But I am failing with exception
ERROR: relation "table_name" does not exist.
As far as I understood I need also provide schema name, and when I am performing like this, it works:
ResultSet resultSet = statement.executeQuery("SELECT NAME FROM schema_name.Table_name");
So basically my question is - How could I avoid refactor all queries?

You want to put the tables in Postgres into the public schema (the default) or use a search path.
The documentation explains this.

searchpath defines the order and list of schemas to be search for unqualified names. By default it is "$user", public so first user schema and then public is looked to.
You can change this order via:
SET search_path TO schema_name,public;
More details on this are here.
You can configure this after connection is open for example.
Alternatively you can set this for user once:
ALTER ROLE username SET search_path = schema_name,public;

This command, as mentioned above, will set search path for current session
SET search_path TO schema_name,public;
However if there is need to do it for all session, just correct config file - pgsql/11/data/postgresql.conf add search path
search_path = '"$user", YOUR_SCHEMA'
Restart the DB.

Related

Is it possible to alter schema of a database I am not connected to?

Is it possible to alter schema of a database I am not connected to? More specifically I need to change an owner of a schema (but it doesn't matter for the questions' sake).
As documentation says schemata can be altered using a clause like:
ALTER SCHEMA name OWNER TO { new_owner | CURRENT_USER | SESSION_USER }
and it sure works, but only on a database I am currently connected in.
Sure I can reconnect to the other database and do it manually, but I am interested whether it is possible to do it from a connection to another (typically postgres) database. It would be quite helpful for automation processes.
I have tried something like:
ALTER DATABASE ALTER SCHEMA name OWNER TO ...
ALTER SCHEMA "db_name".name OWNER TO ...
But without success - so I am interested whether it is possible at all.
I tried to search for this information using one popular search engine and StackOverflow search feature as well. Unsuccessfully - hence the question.
As #a_horse_with_no_name and #JacobH pointed out in comments it is not possible to alter schema of a database you are not currently connected to.
So I ended up using a command like this in order to achieve the schema alteration:
psql $PG_DATABASE -c "ALTER SCHEMA \"<schema-name>\" OWNER TO $PG_USER";

Change default schema for user

create schema bla;
-- then create table table_name into this schema
Then I want change default schema for user (user is postgres)
I do: ALTER ROLE postgres SET search_path TO bla; (Query returned successfully with no result).
When I try SELECT * FROM table_name gives error relation "table_name" does not exist
Though SELECT * FROM bla.table_name works fine.
What is wrong in my attempt to change default schema for user?
I think you need to relogin for that. With ALTER USER ... SET you change
Session defaults for run-time configuration variables
Also from ALTER ROLE SET manual:
Role-specific variable settings take effect only at login;
But don't apply changes to current session. If you want immediate change use:
SET search_path TO bla;
It will change path on session level
In PostGres the exact command would be
ALTER USER 'your-user' set SEARCH_PATH = 'schema_name';

DBA readonly account

I had a schema in one oracle DB as ui_prod. I asked my DBA team guys to create exactly same schema like ui_prod but as read only and name it ui_prod_readonly. Usually I will use Oracle SQL developer to connect a DB and query directly with table name like below.
--Connect to ui_prod
select * from table
but why I requested to put owner name infront when query for readonly schema they created for me, as without putting it, I get error table not exist.
--Connect to ui_prod_readonly
select * from ui_prod.table
I have project files which hardcode the sql query with only table names and adding owner name in front will cause many changes and effort. Can anyone explain me on this? or provide me any document/link to read. Thanks
You should look into synonyms, apparently the user you are connecting to the database as is not the owner of the objects. So to view the object you have to prepend the names with the schema name (the owner of the object themselves).
http://www.techonthenet.com/oracle/synonyms.php
CREATE OR REPLACE SYNONYM ui_prod_readonly.synonym_name
FOR ui_prod.object_name
It seems to me that your dbas have not created another set of tables but just granted the existing tables to the user ui_prod_readonly.
When you log in to Oracle, the current schema is the name of the user you used to log in. So if you log in with ui_prod_readonly Oracle checks that schema for the table if you do not qualify it with the owner (=schema).
If you want to change the current schema so that you don't need to fully qualify the tables, you can do that with ALTER SESSION
alter session set current_schema = ui_prod;
Once you have done that, you don't need to fully qualify the table with the owner (=schema).
if you need a user to read the data only
its simple to create new user and grant it only select privilege
you can create user and grant select privilege using
CREATE USER [user] IDENTIFIED BY [your_password];
grant select on table to [user]

is it possible to selecting table in current_schema independent of public synonym

Is there a way, to select data only form the own schema, even if there is an public synonym?
something like: Select * from current_schema.Table1
more info:
I got a public synonym on table1 on schema1.
now I have a package(on schema2) that selects table1, I want to select table1 of schema2 not schema1.
My problem is, I dont what the user to change the identifier when he uses the package at his server.
edit
I see my question is not clear, what i wanted to know is is there a placeholder for my current schema?
at the moment i need to do this:
Select * from schema2.Table1
and i want is something Like this :
Select * from MySchema.Table1
or
Select * from this.Table1
or
Select * from current_schema.Table1
does something like this exists in oracle?
The scoping rules are quite clear. When the databse parses a query it looks for objects matching the identifiers in your statement in the following order of precedence:
objects of that name in your schema
private synonyms of that name (in your schema)
public synonys of that name
But if you want to be clear certainly you can prefix your table references with the specific schema name. That is helpful in communicating your intent to others looking at your code.
Furthermore, if you have a table TABLE1 in your schema and there is a public synonym called TABLE1 pointing at a table in another schema which you want to query instead you must prefix your reference with that other schema.
"what i wanted to know is is there a placeholder for my current
schema"
No, because it's not necessary. The default is always your current schema. That is, this statement ...
SQL> select * from t23;
... will always select from T23 in your current schema, if it has a table (or a private synonym) with that name.
Note that it is possible to change the value of your current schema, with the ALTER SESSION command:
SQL> alter session set current_schema=scott;
Now if you executed the previous select it would return results from SCOTT.T23 providing the SCOTT schema had such a table, and taht you had privileges on it. You can find out more about Oracle schemas in a blog piece I wrote a while back.
I was trying to understand what problem you were having, and I noticed that your scenario is one user executing a package owned by another user. Now, by default a package owned by SCHEMA2 will run against objects owned by SCHEMA2 and use the privileges on other objects granted to SCHEMA2.
But PL/SQL offers us the ability to change that: the AUTHID clause determines whether the package runs with the definer's privileges (that is the package owner) or invoker's privileges (the current user. So if SCHEMA2 defined their package with AUTHID CURRENT_USER when SCHEMA1 runs it the instance of TABLE2 will be the one in scope of SCHEMA1, which would be the one owned by SCHEMA1 or the one indicated by a public synonym.
Find out more.

SQL server : Login issue while querying

I have a web application running with a SQL server 2005 DB as back end.I took the db back of the production site and restored in my development machine.Then i tried to query this database using the login "sa".When trying to execute the "select * from Customers" query, i am getting a message like "Invalid object name 'Customers"
But when i run "SELECT * FROM [352974_mg4l1].[Customers]", It is returning records.
352974_mg4l1 is a user for this database present when i restored the db backup from production.
What i have to do for getting the records using with simple select query which i used initially("select * from Customers" ). I know it is something related to login issue.Can any one tell me how to solve this ?
The Customers database object is not owned by the dbo schema.
And by referencing Customers as 'sa' you are looking for [dbo].[Customers] ?
I would suggest to:
either provide the object's full name
either change it's schema
Edit:
To alter the schema of said table try this:
ALTER SCHEMA dbo TRANSFER [352974_mg4l1].Customers;
Reference: http://msdn.microsoft.com/en-us/library/ms173423.aspx
Look up sp_changeobjectowner in Books on line. That will help you change the owner. The real question is how the object got created to a specific owner to begin with. If this is true on prod, you could have some major issues with other people accesssing the database.