Posgresql create table use information_schema - database

I'm facing this problem, I created a database with multiple schemas other than public. When I connect with postgres user role (using pgAdmin, if I execute a create table statement, the table is not created but if I browse information_schema.tables that table is listed as table_schema=information_schema, even if in create statement I qualify the table with public schema. After that, if I create another table that reference the first one or just select from that table, postgres complains that the relation does not exixts. Then I have to drop the table to procede anyway.
If I connect with another user role, that have superuser property set, the table is created in public schema.
Is there any database property that I have to set or something other I have to do to avoid the above problem?

Please try creating tables with mentioning schema name like (create table schemaname.tablename(...)) may be it solve your problem.

May be you type
set search_path = information_schema;
to make some queries in the information_schema. But when you create the table, it was created in the information_schema. That was because the first schema name in set search_path is the default for creating objects.

Related

Why do tables in postgresql get created in public schema despite a different search path?

I am trying to have a specific role have access only to a specific schema.
I have schema public, and a schema python. I would like to set the default search_path for a role to schema python:
ALTER ROLE user2 SET search_path = python;
However when I try to create tables they still get placed into public schema, do I have to specify schema name every time when making tables?
CREATE TABLE table ();
-- vs.
CREATE TABLE python.table ();
ALTER ROLE ... SET ... will take effect at next login. For an immediate effect in the current session (only), use SET search_path TO myschema;

CREATE TABLE returns error referring to sp_changeobjectowner and a non-existing schema

A little challenge for the MS Sql Server experts out there...
I have a database on a SQL Server 2008 R2 server.
I have created a schema named MPP and a handful of table for this schema.
The tables were originally created in the default dbo schema and then moved to the new schema using the sp_changeobjectowner procedure. The tables were however created and dropped a few times before I got it to work as I wanted.
To the problem... Whenever I now create a new table, regardless in the default dbo schema or I get one error message per table in the new schema referring to an error in the sp_changeobjectowner procedure:
CREATE TABLE dbo.test (d INT);
Msg 15001, Level 16, State 1, Procedure sp_changeobjectowner, Line 64
Object 'ASBJOR.TEST_TABELL' does not exist or is not a valid object for this operation.
There is a database user named ASBJOR, but no schema.
If I add a new table to the MPP schema the number of error messages will increase and one of the messages refers to the new table.
I've tried to create a new table in the default dbo schema and move it to the MPP schema using the ALTER SCHEMA MPP TRANSFER... command, but new table still appears in the error messages.
I've looked through the sys.objects, sys.tables, sys.schemas and sys.database_principals tables but I can't find anything wrong.
Any ideas what could cause this error message or where I can look for more hardcore details in the database?
You should never use sp_changeobjectowner - it's been deprecated since 2005. Always use ALTER SCHEMA ... TRANSFER.
As for the error, check for a DDL trigger in that database:
SELECT * FROM sys.triggers WHERE parent_class = 0;
Then check to see what those triggers are doing.

Way to show db name on tables

I use sql-server-2005,My database contains many tables.
When I explore my db, I see all table names are prefixed with "dbo". I want to replace the "dbo" with the database name see below:
dbo is a schema name, it has nothing to do with database name. SQL server uses 4 part names : [ServerName].[Database name].[Schema name].[Table/View/Trigger/SP/Function/etc Name]. Default schema is dbo, but you can name it after database if you want (see http://msdn.microsoft.com/en-us/library/ms189462.aspx for details)
As other have said dbo is the default schema. I'm not sure why you would want to create a schema that has the same name as the database, but to accomplish what you've asked you would have to do something like the following:
Create a new schema using the CREATE SCHEMA statement
Move your tables from the default schema to the new schema using the ALTER SCHEMA statement.
An example would be:
IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name ='iMature_US')
EXEC dbo.sp_executesql #statement=N'CREATE SCHEMA iMature_US';
GO
ALTER SCHEMA iMature_US TRANSFER dbo.PODetail
GO
You could write a script to transfer all the tables using data from the INFORMATION_SCHEMA.TABLES view.

Multi-Schema Privileges for a Table Trigger in an Oracle Database

I'm trying to write a table trigger which queries another table that is outside the schema where the trigger will reside. Is this possible? It seems like I have no problem querying tables in my schema but I get:
Error: ORA-00942: table or view does not exist
when trying trying to query tables outside my schema.
EDIT
My apologies for not providing as much information as possible the first time around. I was under the impression this question was more simple.
I'm trying create a trigger on a table that changes some fields on a newly inserted row based on the existence of some data that may or may not be in a table that is in another schema.
The user account that I'm using to create the trigger does have the permissions to run the queries independently. In fact, I've had my trigger print the query I'm trying to run and was able to run it on it's own successfully.
I should also note that I'm building the query dynamically by using the EXECUTE IMMEDIATE statement. Here's an example:
CREATE OR REPLACE TRIGGER MAIN_SCHEMA.EVENTS
BEFORE INSERT
ON MAIN_SCHEMA.EVENTS REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
DECLARE
rtn_count NUMBER := 0;
table_name VARCHAR2(17) := :NEW.SOME_FIELD;
key_field VARCHAR2(20) := :NEW.ANOTHER_FIELD;
BEGIN
CASE
WHEN (key_field = 'condition_a') THEN
EXECUTE IMMEDIATE 'select count(*) from OTHER_SCHEMA_A.'||table_name||' where KEY_FIELD='''||key_field||'''' INTO rtn_count;
WHEN (key_field = 'condition_b') THEN
EXECUTE IMMEDIATE 'select count(*) from OTHER_SCHEMA_B.'||table_name||' where KEY_FIELD='''||key_field||'''' INTO rtn_count;
WHEN (key_field = 'condition_c') THEN
EXECUTE IMMEDIATE 'select count(*) from OTHER_SCHEMA_C.'||table_name||' where KEY_FIELD='''||key_field||'''' INTO rtn_count;
END CASE;
IF (rtn_count > 0) THEN
-- change some fields that are to be inserted
END IF;
END;
The trigger seams to fail on the EXECUTE IMMEDIATE with the previously mentioned error.
EDIT
I have done some more research and I can offer more clarification.
The user account I'm using to create this trigger is not MAIN_SCHEMA or any one of the OTHER_SCHEMA_Xs. The account I'm using (ME) is given privileges to the involved tables via the schema users themselves. For example (USER_TAB_PRIVS):
GRANTOR GRANTEE TABLE_SCHEMA TABLE_NAME PRIVILEGE GRANTABLE HIERARCHY
MAIN_SCHEMA ME MAIN_SCHEMA EVENTS DELETE NO NO
MAIN_SCHEMA ME MAIN_SCHEMA EVENTS INSERT NO NO
MAIN_SCHEMA ME MAIN_SCHEMA EVENTS SELECT NO NO
MAIN_SCHEMA ME MAIN_SCHEMA EVENTS UPDATE NO NO
OTHER_SCHEMA_X ME OTHER_SCHEMA_X TARGET_TBL SELECT NO NO
And I have the following system privileges (USER_SYS_PRIVS):
USERNAME PRIVILEGE ADMIN_OPTION
ME ALTER ANY TRIGGER NO
ME CREATE ANY TRIGGER NO
ME UNLIMITED TABLESPACE NO
And this is what I found in the Oracle documentation:
To create a trigger in another user's
schema, or to reference a table in
another schema from a trigger in your
schema, you must have the CREATE ANY
TRIGGER system privilege. With this
privilege, the trigger can be created
in any schema and can be associated
with any user's table. In addition,
the user creating the trigger must
also have EXECUTE privilege on the
referenced procedures, functions, or
packages.
Here: Oracle Doc
So it looks to me like this should work, but I'm not sure about the "EXECUTE privilege" it's referring to in the doc.
What you are experiencing is a feature of Oracle's security model. The entire point of using schemas is to control access to the data. The tables in my schema are mine, you cannot even see them until I grant you privileges on them.
The syntax is quite simple: the owner schema issues
grant select, insert on my_table to you
/
Alternatively an account with the GRANT ANY privilege (such as a DBA) can pass privileges on any user's objects.
grant select, insert on apc.my_table to you
/
The grantee can be either a user or a role. However, note that we can only build program units - stored procedures, views, triggers - using privileges which have been granted directly through to our user.
So, if you get the other schema owner to grant you the necessary privileges you will be able to build your trigger.
edit
When referencing an object in another schema we need to qualify the object with the schema name ....
insert into apc.whatever_table values ...
or else we need to create a synonym for it
create synonym whatever for apc.whatever_table;
I feel someone should add the obvious - the other schema's table must be qualified with the schema name or a private/public synonym is needed. I wonder if the original problem was merely a name resolution issue. If not, APC's answer is a good explanation of the Oracle security model.
You should execute this for every table and schema involved:
grant select on OTHER_SCHEMA_%.table_name to MAIN_SCHEMA;

Database name while referencing tables - Sybase

How do I get away with hardcoding the database name in referencing a table within a stored procedure. For example there are two databases db1 and db2. I am writing a stored procedure in db2 which references two tables, one from db1 and another from db2. Both are on the same sybase server.
If I understand your question correctly, on the one hand, in your stored procedure you can refer to the table in the same database directly by name
SELECT ...
FROM table_in_db2
You can refer to a table in database db1 by prefixing the database name and an empty owner:
SELECT ...
FROM db1..table_in_db1
On the other hand, if you want to avoid hard-coding database names in the procedure you might create a view in database db2 that references the db1 table:
CREATE VIEW view_in_db2
AS
SELECT *
FROM db1..table_in_db1
and use that in the procedure:
SELECT ...
FROM view_in_db2
You need to keep the code portable, involve 2 databases, but avoid referencing databases by name. Then you can create proxy tables (or proxy views, if such views exist in 12.5). Refer to proxy tables as to local objects.
This will work, but will require some extra care, every time you move/change databases. But anyway the separation of concerns you are after can be achieved.

Resources