apart from checking if table already exists, how can we verify if it is current user-defined table in postgres
CREATE TABLE IF NOT EXISTS tbl1()
how can we verify it was created by current user if already exists?
Try Like This
SELECT count(*) as cnt FROM pg_tables t where tableowner=current_user
and tablename='Tablename' and schemaname='schemaneme'
if cnt = 0 then (CREATE Table TableName)
Related
I want to rename a table as part of a migration, but only if the table has not been renamed already. I'm currently running:
ALTER TABLE IF EXISTS old_name RENAME TO new_name
however, if new_name already exists it will still run. Is there a way to run this statement if and only if new_name does not exist?
You could always write an anonymous code block (or also a user defined function/procedure) similar to:
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_tables WHERE tablename = 'z') THEN
EXECUTE 'ALTER TABLE a RENAME TO z';
END IF;
END$$;
As far as I know you cannot specify it with the ALTER TABLE command directly.
I'm trying to execute an S3 copy operation via Spark-Redshift and I'm looking to modify the Redshift table structure before running the copy command in order to add any missing columns (they should be all VARCHAR).
What I'm able to do is send an SQL query before running the copy, so ideally I would have liked to ALTER TABLE ADD COLUMN IF NOT EXISTS column_name VARCHAR(256). Unfortunately, Redshift does not offer support for ADD COLUMN IF NOT EXISTS, so I'm currently looking for a workaround.
I've tried to query the pg_table_def table to check for the existence of the column, and that works, but I'm not sure how to chain that with an ALTER TABLE statement. Here's the current state of my query, I'm open to any suggestions for accomplishing the above.
select
case when count(*) < 1 then ALTER TABLE tbl { ADD COLUMN 'test_col' VARCHAR(256) }
else 'ok'
end
from pg_table_def where schemaname = 'schema' and tablename = 'tbl' and pg_table_def.column = 'test_col'
Also, I've seen this question: Redshift: add column if not exists, however the accepted answer isn't mentioning how to actually achieve this.
I'm trying to avoid using PGSQL for some simple queries, but I want to store the schema name as a variable and use it later in multiple queries:
WITH p AS (SELECT 'testSchema' AS schemaName)
CREATE SCHEMA IF NOT EXISTS p.schemaName;
create table if not exists p.schemaName.table1;
Perhaps "with" is not the right way, or may by I need to use it differently.
You should use the SQL statement SET, perhaps with the LOCAL option, but that won't work with CREATE SCHEMA.
Something like this:
BEGIN; -- start transaction
CREATE SCHEMA IF NOT EXISTS testschema;
SET LOCAL search_path = 'testschema'; -- only for this transaction
CREATE TABLE IF NOT EXISTS table1 ...; -- will be created in testschema
COMMIT;
I have one table USER and some other tables like USER_DETAILS ,USER_QUALIFICATION etc USER_ID references to all such table i want to remove those USER_ID which are not present in any other tables.
Deleting all of the users that are not present in a connected table:
DELETE FROM table WHERE user_id NOT IN (SELECT user_id FROM other_table)
If you want to delete only users that are not found in any table than you can add
AND NOT IN (SELECT user_id FROM another_table)
Alternatively you can create a tmp table and merge in all the user_ids that you want to keep and use that table in the sub-select for the NOT IN.
Use a DELETE with a not exists condition for all related tables:
delete from "USER" u
where not exists (select *
from user_details ud
where ud.user_id = u.user_id)
and not exists (select *
from user_qualification uq
where uq.user_id = u.user_id);
Note that user is a reserved word, and thus needs to be quoted to be usable as a table name. But quoting makes it case-sensitive. So "USER" and "user" are two different table names. As you have not included the DDL for your tables I cannot tell if your table is named "USER" or "user".
In general I would strongly recommend to avoid using double quotes for identifies completely.
Here's what I've been reading:
http://www.postgresql.org/docs/9.2/static/rules-views.html
http://www.postgresql.org/docs/9.2/static/rules-privileges.html
My goal is to allow a login to see only those rows that it "owns", so to speak.
Let's say every table in the database inherits from this table:
create table WHOAMI
(
tenant varchar(25) not null default current_user
);
for example:
create table FOO
(
id int primary key,
invoicedate date
) inherits (WHOAMI);
insert into FOO(id, invoicedate) values(1,now()::date);
select * from FOO;
--abclogin|1|2013-02-01
Is there such a thing in PostgreSQL as a schema-level select rule, affecting all tables and views in the schema, that appends to every select, insert, update, or delete statement a condition that says, in effect, ..AND WHERE TENANT = current_user? If there isn't such a global rule, can it be done on a table-by-table basis? I am not having any success with my attempts, and am probably misunderstanding a few things about how rules are created. Here is what I have tried to do:
I try to create a select-rule:
CREATE RULE "_RETURN" AS ON SELECT TO FOO DO INSTEAD
SELECT * FROM FOO where tenant = current_user;
but get this error: ERROR: could not convert table "foo" to a view because it has indexes
I try to create a view with a security-barrier:
CREATE VIEW TENANTFOO WITH (security_barrier) AS
SELECT * FROM FOO WHERE tenant=current_user;
and then attempt an insert:
insert into TENANTFOO(id,invoicedate)
values(2,(now()::date);
but get this error:
`ERROR: cannot insert into view "tenantfoo"
HINT: You need an unconditional ON INSERT DO INSTEAD rule
or an INSTEAD OF INSERT trigger.`
What steps are required to implement row-level security barriers on tables?
In your last example, you'd need to run the INSERT against the table or create another RULE: ON INSERT TO TENANTFOO DO INSTEAD.
What you're looking for is a Row-Level Security, it is not yet available, although some work had been done on this thing. I hope this patch will make it into the upcoming 9.3 release.
Meanwhile, I've been working with the following design a while ago.
Requirements were similar, views should have been delivering only those rows intended for the CURRENT_USER. In our case access had been done quite simple: a table that specified whether given user had access for the given relation and given key, smth like:
CREATE TABLE user_grants (
user_id integer,
entity_name text, -- should exist in pg_class
entity_id integer
);
Then, say for the tasks, the following view had been created:
CREATE VIEW tasks_v AS
SELECT t.*
FROM tasks t
JOIN user_grants ug ON t.user_id = ug.user_id
AND ug.entity_name='TASKS' AND ug.entity_id = t.task_id;
Of course, the setup is not complete without a number of helper functions, triggers and rules. Also it was necessary to make sure some reasonable default privileges are always granted.