RedShift Cheat Sheet
General Admin
-- Show running queries
SELECT user_name, db_name, pid, query
FROM stv_recents
WHERE status = 'Running';
-- Show recent queries (td, join with user table)
SELECT userid,query,pid,substring,starttime,endtime,elapsed,aborted
FROM svl_qlog
ORDER BY starttime DESC
LIMIT 100;
-- Show recent connections
select recordtime, username, dbname, remotehost, remoteport
from stl_connection_log
where event = 'initiating session'
and pid not in
(select pid from stl_connection_log
where event = 'disconnecting session')
order by 1 desc;
-- Move a table from one schema to another (remaps data, drop dependecies)
CREATE TABLE pwtest.customer (LIKE public.customer);
ALTER TABLE pwtest.customer APPEND FROM public.customer;
DROP TABLE public.customer;
Users
-- Show current user
SELECT current_user;
-- Show all Users
SELECT * FROM pg_user;
-- Impersonate User (requires supeuser)
SET SESSION AUTHORIZATION 'finance';
RESET SESSION AUTHORIZATION;
-- Create/drop new user
CREATE USER pete PASSWORD 'r4nd0mZ1KpasswUrd0';
DROP USER pete;
-- Change a users password
ALTER USER pete PASSWORD 'r4nd0mqeXpasswUrd0';
-- Create new temporary user (with expiry date) ++ with timestamp
CREATE USER pete_expire PASSWORD 'r4nd0mdj9passwUrd0' VALID UNTIL '2020-05-19 06:15:00+00';
-- Create a new user that expires tomorrow
CREATE USER pete_expire_tomorrow PASSWORD 'r4nd0mD0JpasswUrd0' VALID UNTIL sysdate+1;
-- Create new superuser
CREATE USER pete CREATEUSER PASSWORD 'r4nd0mX8vpasswUrd0'
-- Amend user, give/remove superuser access
ALTER USER pete CREATEUSER;
ALTER USER pete NOCREATEUSER;
Groups
-- Show all Groups
SELECT *
FROM pg_group;
-- Create a Group
CREATE GROUP test_group WITH USER pete;
-- Create a Group and Add Users
CREATE GROUP test_group WITH USER pete1, pete2;
-- Add a User to a Group
ALTER GROUP test_group ADD USER pete1;
-- Amend a Group Name
ALTER GROUP test_group RENAME TO group_test
-- Show Users & their accosiated Groups
SELECT usename, groname
FROM pg_user, pg_group
WHERE pg_user.usesysid = ANY(pg_group.grolist)
AND pg_group.groname in (SELECT DISTINCT pg_group.groname from pg_group);
Create Tables/Views/MViews
-- Show all Schemas
SELECT * FROM pg_namespace;
-- Create a Schema
CREATE SCHEMA pwtest
-- Show all tables
SELECT * FROM pg_table_def
-- Create a Table
CREATE TABLE pwtest.customer
(
customerid INT8 NOT NULL,
customername VARCHAR(25) NOT NULL,
phone CHAR(15) NOT NULL,
nationid INT4 NOT NULL,
marketsegment CHAR(10) NOT NULL,
accountbalance NUMERIC(12,2) NOT NULL
);
CREATE TABLE pwtest.nation
(
nationid INT4 NOT NULL,
nationname CHAR(25) NOT NULL
);
-- Drop a table
DROP TABLE pwtest.customer
-- Insert rows to Table
INSERT INTO pwtest.customer VALUES
(1, 'Customer#000000001', '33-687-542-7601', 3, 'HOUSEHOLD', 2788.52),
(2, 'Customer#000000002', '13-806-545-9701', 1, 'MACHINERY', 591.98),
(3, 'Customer#000000003', '13-312-472-8245', 1, 'HOUSEHOLD', 3332.02),
(4, 'Customer#000000004', '23-127-851-8031', 2, 'MACHINERY', 9255.67),
(5, 'Customer#000000005', '13-137-193-2709', 1, 'BUILDING', 5679.84)
;
INSERT INTO pwtest.nation VALUES
(1, 'UNITED STATES'),
(2, 'AUSTRALIA'),
(3, 'UNITED KINGDOM');
-- Updates to tables
UPDATE customer
SET accountbalance = 1000
WHERE marketsegment = 'BUILDING';
-- Create View
CREATE OR REPLACE VIEW pwtest.customer_vw
AS SELECT customername, phone, marketsegment, accountbalance,
CASE WHEN accountbalance < 1000 THEN 'low' WHEN accountbalance > 1000 AND accountbalance < 5000 THEN 'middle'
ELSE 'high' END AS incomegroup
FROM pwtest.customer;
-- Drop a View
DROP VIEW pwtest.customer_vw
-- Create Materialized View
CREATE MATERIALIZED VIEW pwtest.customernation_mv
AS SELECT customername, phone, nationname, marketsegment, sum(accountbalance) AS accountbalance
FROM pwtest.customer c
INNER JOIN pwtest.nation n
ON c.nationid = n.nationid
GROUP BY customername, phone, nationname, marketsegment;
-- Drop a Materialized View
DROP MATERIALIZED VIEW pwtest.customernation_mv
Permissions (Schema/Table/Column)
-- Grant usage on a schema for a user (public schema is allowed by default)
GRANT USAGE ON SCHEMA pwtest.customer TO pete_restricted;
REVOKE USAGE ON TABLE pwtest.customer FROM pete_restricted;
-- Grant & revoke select permissions on a table for a user
GRANT SELECT ON pwtest.customer TO pete_restricted;
REVOKE SELECT ON TABLE pwtest.customer FROM pete_restricted;
-- Grant & revoke select & update permissions for a group
GRANT SELECT, UPDATE ON pwtest.customer TO GROUP devs;
REVOKE SELECT, UPDATE ON TABLE pwtest.customer FROM GROUP devs;
-- Grant & revoke select & update on 2 columns of a table for a user
GRANT SELECT (marketsegment, accountbalance), UPDATE (marketsegment, accountbalance) ON pwtest.customer TO pete_restricted;
REVOKE SELECT (marketsegment, accountbalance), UPDATE (marketsegment, accountbalance) ON pwtest.customer FROM pete_restricted;
Permissions (Auditing)
-- Impersonate User (requires supeuser)
SET SESSION AUTHORIZATION 'finance';
RESET SESSION AUTHORIZATION;
-- Show which users have column-level access control (table-scoped)
SELECT b.attacl, b.attname, c.relname
FROM pg_catalog.pg_attribute_info b
JOIN pg_class c ON c.oid=b.attrelid
WHERE c.relname in ('customer','customer_vw','customernation_mv')
AND b.attacl IS NOT NULL
ORDER BY c.relname, b.attname;
-- View all Grants by Schema or User
SELECT *
FROM
(
SELECT
schemaname
,objectname
,usename
,HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'select') AND has_schema_privilege(usrs.usename, schemaname, 'usage') AS sel
,HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'insert') AND has_schema_privilege(usrs.usename, schemaname, 'usage') AS ins
,HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'update') AND has_schema_privilege(usrs.usename, schemaname, 'usage') AS upd
,HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'delete') AND has_schema_privilege(usrs.usename, schemaname, 'usage') AS del
,HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'references') AND has_schema_privilege(usrs.usename, schemaname, 'usage') AS ref
FROM
(
SELECT schemaname, 't' AS obj_type, tablename AS objectname, schemaname + '.' + tablename AS fullobj FROM pg_tables
WHERE schemaname not in ('pg_internal')
UNION
SELECT schemaname, 'v' AS obj_type, viewname AS objectname, schemaname + '.' + viewname AS fullobj FROM pg_views
WHERE schemaname not in ('pg_internal')
) AS objs
,(SELECT * FROM pg_user) AS usrs
ORDER BY fullobj
)
WHERE (sel = true or ins = true or upd = true or del = true or ref = true)
and schemaname='<opt schema>'
and usename = '<opt username>';
-- View all Grants by Group
select relacl ,
'grant ' || substring(
case when charindex('r',split_part(split_part(array_to_string(relacl, '|'),pu.groname,2 ) ,'/',1)) > 0 then ',select ' else '' end
||case when charindex('w',split_part(split_part(array_to_string(relacl, '|'),pu.groname,2 ) ,'/',1)) > 0 then ',update ' else '' end
||case when charindex('a',split_part(split_part(array_to_string(relacl, '|'),pu.groname,2 ) ,'/',1)) > 0 then ',insert ' else '' end
||case when charindex('d',split_part(split_part(array_to_string(relacl, '|'),pu.groname,2 ) ,'/',1)) > 0 then ',delete ' else '' end
||case when charindex('R',split_part(split_part(array_to_string(relacl, '|'),pu.groname,2 ) ,'/',1)) > 0 then ',rule ' else '' end
||case when charindex('x',split_part(split_part(array_to_string(relacl, '|'),pu.groname,2 ) ,'/',1)) > 0 then ',references ' else '' end
||case when charindex('t',split_part(split_part(array_to_string(relacl, '|'),pu.groname,2 ) ,'/',1)) > 0 then ',trigger ' else '' end
||case when charindex('X',split_part(split_part(array_to_string(relacl, '|'),pu.groname,2 ) ,'/',1)) > 0 then ',execute ' else '' end
||case when charindex('U',split_part(split_part(array_to_string(relacl, '|'),pu.groname,2 ) ,'/',1)) > 0 then ',usage ' else '' end
||case when charindex('C',split_part(split_part(array_to_string(relacl, '|'),pu.groname,2 ) ,'/',1)) > 0 then ',create ' else '' end
||case when charindex('T',split_part(split_part(array_to_string(relacl, '|'),pu.groname,2 ) ,'/',1)) > 0 then ',temporary ' else '' end
, 2,10000)
|| ' on '||namespace||'.'||item ||' to "'||pu.groname||'";' as grantsql
from
(SELECT
use.usename as subject,
nsp.nspname as namespace,
c.relname as item,
c.relkind as type,
use2.usename as owner,
c.relacl
FROM
pg_user use
cross join pg_class c
left join pg_namespace nsp on (c.relnamespace = nsp.oid)
left join pg_user use2 on (c.relowner = use2.usesysid)
WHERE
c.relowner = use.usesysid
and nsp.nspname NOT IN ('pg_catalog', 'pg_toast', 'information_schema')
ORDER BY
subject, namespace, item
) join pg_group pu on array_to_string(relacl, '|') like '%'||pu.groname||'%'
where relacl is not null
and pu.groname='devs'
order by 2