Loop through names and delete those not matching specified name - named-ranges

I've attempted to implement the solution from this Q/A: loop through names and delete those not matching specified pattern and keep getting an error. Is there a limitation on the quantity of AND statements you can include in this?
Sub DeleteBCEDetailNames()
Dim myName As Name
For Each myName In ThisWorkbook.Names
If myName.NameLocal <> "bce_bid_country" And
myName.NameLocal <> "bce_Currency" And
myName.NameLocal <> "bce_Exchange_Rate_to_GBP" And
myName.NameLocal <> "bce_Siebel_ID" And
myName.NameLocal <> "bce_Bid_ID" And
myName.NameLocal <> "bce_MP_Authorised_Budget" And
myName.NameLocal <> "bce_Bid_Start_Date" And
myName.NameLocal <> "bce_Make_Pursuit_Date" And
myName.NameLocal <> "bce_Qualification_Bid_SignOn_Date" And
myName.NameLocal <> "bce_Mid_Point_Review_Date" And
myName.NameLocal <> "bce_Bid_Sign_Off_1_Date" And
myName.NameLocal <> "bce_Bid_Sign_Off_2_Date" And
myName.NameLocal <> "bce_Bid_Sign_Off_3_Date" And
myName.NameLocal <> "bce_Contract_Sign_Off_Date" And
myName.NameLocal <> "bce_Expected_Close_Date" And
myName.NameLocal <> "bce_WD_BS_MP" And
myName.NameLocal <> "bce_WD_MP_QBSO" And
myName.NameLocal <> "bce_WD_QBSO_MPR" And
myName.NameLocal <> "bce_WD_MPR_BSOff1" And
myName.NameLocal <> "bce_WD_BSOff1_BSOff2" And
myName.NameLocal <> "bce_WD_BSOff2_BSOff3" And
myName.NameLocal <> "bce_WD_BSOff_CSO" And
myName.NameLocal <> "bce_WD_CSO_ECD" And
myName.NameLocal <> "bce_Total_Working_Days" And
myName.NameLocal <> "bce_Labour_BS_MP" And
myName.NameLocal <> "bce_Labour_MP_QBSO" And
myName.NameLocal <> "bce_Labour_QBSO_MPR" And
myName.NameLocal <> "bce_Labour_MPR_BSOff" And
myName.NameLocal <> "bce_Labour_BSOff_CSO" And
myName.NameLocal <> "bce_Labour_CSO_ECD" And
myName.NameLocal <> "bce_Non_Labour_BS_MP" And
myName.NameLocal <> "bce_Non_Labour_MP_QBSO" And
myName.NameLocal <> "bce_Non_Labour_QBSO_MPR" And
myName.NameLocal <> "bce_Non_Labour_MPR_BSOff" And
myName.NameLocal <> "bce_Non_Labour_BSOff_CSO" And
myName.NameLocal <> "bce_Non_Labour_CSO_ECD" And
myName.NameLocal <> "bce_TotalStageCost_BS_MP" And
myName.NameLocal <> "bce_TotalStageCost_MP_QBSO" And
myName.NameLocal <> "bce_TotalStageCost_QBSO_MPR" And
myName.NameLocal <> "bce_TotalStageCost_MPR_BSOff" And
myName.NameLocal <> "bce_TotalStageCost_BSOff_CSO" And
myName.NameLocal <> "bce_TotalStageCost_CSO_ECD" And
myName.NameLocal <> "bce_Labour_BidSupportCost" And
myName.NameLocal <> "bce_Labour_Bought_inCost" And
myName.NameLocal <> "bce_Labour_SectorCost" And
myName.NameLocal <> "bce_Total_LabourCost" And
myName.NameLocal <> "bce_Non_Labour_PeopleRelatedCost" And
myName.NameLocal <> "bce_Non_Labour_OtherCost" And
myName.NameLocal <> "bce_Total_Non_LabourCost" And
myName.NameLocal <> "bce_Total_BCE_ExcludingOverhead" And
myName.NameLocal <> "bce_Labour_OverheadCost" And
myName.NameLocal <> "bce_Fixed_Charge_per_FTECost" And
myName.NameLocal <> "bce_Total_Overhead_Estimate" And
myName.NameLocal <> "bce_Total_BCE" And
myName.NameLocal <> "bce_BCE_PercentofTOV" And
myName.NameLocal <> "bce_BCE_PercentofICV" Then
my.Name.Delete
End If
Next
End Sub

Related

Update table after counting matches from another table

I am confused how to write this query
I have 2 tables where the data in table1 needs to be updated based on the results from table2
For instance, if t1.a is available in either t2.a, t2.b, t2.c, t2.d, t2.e then the result should be 1, but based on the below formula I'm getting sum of the available matches from t2
UPDATE public.table1 AS t1 SET result = (select sum(
CASE WHEN t1.a IN (t2.a, t2.b, t2.c, t2.d, t2.e) THEN 1 ELSE 0 END +
CASE WHEN t1.b IN (t2.a, t2.b, t2.c, t2.d, t2.e) THEN 1 ELSE 0 END +
CASE WHEN t1.c IN (t2.a, t2.b, t2.c, t2.d, t2.e) THEN 1 ELSE 0 END +
CASE WHEN t1.d IN (t2.a, t2.b, t2.c, t2.d, t2.e) THEN 1 ELSE 0 END +
CASE WHEN t1.e IN (t2.a, t2.b, t2.c, t2.d, t2.e) THEN 1 ELSE 0 END )
FROM public.table2 AS t2 )
Basically my requirement is if the result of t1.a>0 then 1 else 0 + if t1.b>0 then 1 else 0 and so on..
I would prefer to use the query as following where i have added >0 but isn't working;
UPDATE public.table1 AS t1 SET result = (select sum(
CASE WHEN t1.a IN (t2.a, t2.b, t2.c, t2.d, t2.e)>0 THEN 1 ELSE 0 END +
CASE WHEN t1.b IN (t2.a, t2.b, t2.c, t2.d, t2.e)>0 THEN 1 ELSE 0 END +
CASE WHEN t1.c IN (t2.a, t2.b, t2.c, t2.d, t2.e)>0 THEN 1 ELSE 0 END +
CASE WHEN t1.d IN (t2.a, t2.b, t2.c, t2.d, t2.e)>0 THEN 1 ELSE 0 END +
CASE WHEN t1.e IN (t2.a, t2.b, t2.c, t2.d, t2.e)>0 THEN 1 ELSE 0 END )
FROM public.table2 AS t2 )
Based on your problem definition:
create table table1 (id integer, a integer, result integer);
create table table2 (id integer, a integer, b integer, c integer, d integer, e integer);
insert into table1 values (1, 3, 0);
insert into table2 values (1, 9,2,5,4,3);
insert into table1 values (1, 8, 0);
select case when coalesce(t1.a in(t2.a, t2.b, t2.c, t2.d, t2.e), 'f') then 1 else 0 end from table1 as t1, table2 t2;
case
------
1
0
update table1 as t1 set result = (select case when coalesce(t1.a in(t2.a, t2.b, t2.c, t2.d, t2.e), 'f') then 1 else 0 end from table2 t2);
select * from table1;
id | a | result
----+---+--------
1 | 3 | 1
1 | 8 | 0

Multiple case in update postgres

I need to update 2 columns in table with same conditions. I know, that each of them would take a lot of time. How can I concatenate 2 updates into 1, which can be faster?
-- first update
update t1
set col1 =
case when cc1 is not NULL and cc1 <> 0 then 'A'
when cc2 is not NULL and cc2 <> 0 then 'B'
when cc3 is not NULL and cc3 <> 0 then 'C'
else null
end;
-- with same cond
update t1
set col2 =
case when cc1 is not NULL and cc1 <> 0 then 'qwe rty'
when cc2 is not NULL and cc2 <> 0 then 'qzaz wsx'
when cc3 is not NULL and cc3 <> 0 then 'zxcv asdf'
else 'pl ok'
end;
-- my effort to concatenate, dont work
update t1
set (col1, col2) =
(select c1, c2 from
(select case when t2.cc1 is not NULL and t2.cc1 <> 0 then 'A' as c1, 'qwe rty' as c2
when t2.cc2 is not NULL and t2.cc2 <> 0 then ('B', 'qaz wsx')
when t2.cc3 is not NULL and t2.cc3 <> 0 then ('C', ' zxcv asdf')
else (null, 'pl ok')
end
from t1 as t2 where t1.key_column1 = t2.key_column1 and t1.key_column2 = t2.key_column2 and t1.key_column3 = t2.key_column3) f)
;
This is the way I would do it.
WITH cte AS (SELECT * FROM
(VALUES(1, 'A', 'qwe rty'),(2, 'B', 'qaz wsx'),(3, 'C', 'zxcv asdf'),(4, NULL, 'pl ok')) v (id,c1,c2))
UPDATE so_demo
SET col1 = cte.c1, col2 = cte.c2
FROM cte WHERE cte.id = CASE WHEN COALESCE(cc1, 0) <> 0 THEN 1
WHEN COALESCE(cc2, 0) <> 0 THEN 2
WHEN COALESCE(cc3, 0) <> 0 THEN 3
ELSE 4 END;
By way of explanation, I have put the possible values into a cte assigning them an id in addition to the values. I can then put the case statement in the where clause generating the necessary id. Note the use of COALESCE to make the WHENs simpler to read.
One way is to use arrays.
UPDATE t1
SET (col1,
col2) = (SELECT x[1],
x[2]
FROM (SELECT CASE
WHEN cc1 IS NOT NULL
AND cc1 <> 0 THEN
ARRAY['A',
'qwe rty']
WHEN cc2 IS NOT NULL
AND cc2 <> 0 THEN
ARRAY['B',
'qzaz wsx']
...
ELSE
ARRAY[NULL,
'pl ok']
END) AS x
(x));
But in terms of runtime optimization the gain compared to just UPDATE ... SET col1 = CASE ..., col2 = CASE ... should be neglectable, if any.

Parse Prefix First Middle Last Suffix from full name

I need to parse a full name in the format, prefix first middle last suffix, but not all parts may be included. I have the prefix first middle and last working, but Jr gets stuffed in with the last name. How do I get the suffix to come out in a suffix column? Example includes data.
SELECT
FIRST_NAME.INPUT_DATA
,FIRST_NAME.PREFIX
,FIRST_NAME.FIRST_NAME
,CASE WHEN 0 = CHARINDEX(' ',FIRST_NAME.REMAINING)
THEN NULL --no more spaces found, consider remaining to be last name
ELSE SUBSTRING(
FIRST_NAME.REMAINING
,1
,CHARINDEX(' ',FIRST_NAME.REMAINING)-1
)
END AS MIDDLE_NAME
,SUBSTRING(
FIRST_NAME.REMAINING
,1 + CHARINDEX(' ',FIRST_NAME.REMAINING)
,LEN(FIRST_NAME.REMAINING)
) AS LAST_NAME
FROM
(
SELECT
PREFIX.PREFIX
,CASE WHEN 0 = CHARINDEX(' ',PREFIX.REMAINING)
THEN PREFIX.REMAINING --no space found, return the entire string
ELSE SUBSTRING(
PREFIX.REMAINING
,1
,CHARINDEX(' ',PREFIX.REMAINING)-1
)
END AS FIRST_NAME
,CASE WHEN 0 = CHARINDEX(' ',PREFIX.REMAINING)
THEN NULL --no spaces found, consider to be first name
ELSE SUBSTRING(
PREFIX.REMAINING
,CHARINDEX(' ',PREFIX.REMAINING)+1
,LEN(PREFIX.REMAINING)
)
END AS REMAINING
,PREFIX.INPUT_DATA
FROM
(
SELECT --CLEAN_DATA
--if first three characters match list,
--parse as a "PREFIX". else return NULL for PREFIX.
CASE WHEN SUBSTRING(CLEAN_DATA.FULL_NAME,1,3) IN ('MR ','MS ','DR ','MRS')
THEN LTRIM(RTRIM(SUBSTRING(CLEAN_DATA.FULL_NAME,1,3)))
ELSE NULL
END AS PREFIX
,CASE WHEN SUBSTRING(CLEAN_DATA.FULL_NAME,1,3) IN ('MR ','MS ','DR ','MRS')
THEN LTRIM(RTRIM(SUBSTRING(CLEAN_DATA.FULL_NAME,4,LEN(CLEAN_DATA.FULL_NAME))))
ELSE LTRIM(RTRIM(CLEAN_DATA.FULL_NAME))
END AS REMAINING
,CLEAN_DATA.INPUT_DATA
FROM
(
SELECT
--trim leading & trailing spaces to prepare for processing
--replace extra spaces in name
REPLACE(REPLACE(LTRIM(RTRIM(FULL_NAME)),' ',' '),' ',' ') AS FULL_NAME
,FULL_NAME AS INPUT_DATA
FROM
(
--test with test data, or table
--table
--SELECT CONTACT AS FULL_NAME
--FROM CONTACT
--test data
--/*
SELECT 'Andy D Where' AS FULL_NAME
UNION SELECT 'Cathy T Landers' AS FULL_NAME
UNION SELECT 'Ms Annie Wint There' AS FULL_NAME
UNION SELECT 'Frank Fields' AS FULL_NAME
UNION SELECT 'Howdy U Pokes Jr.' AS FULL_NAME
--*/
) SOURCE_DATA
) CLEAN_DATA
) PREFIX
) FIRST_NAME
--credits to JStyons of course
Hope this helps. I have only added Generational SUFFIX titles(Sr, Jr), If more are needed you could add to the Case statement as needed. I am also assuming that your Db is case insensitive.
Assumption (Business Rules):
First Name has no spaces
Middle Name has no spaces
Last name has no spaces
Prefix's are only of the form 'MR ','MS ','DR ','MRS' with no period "."
Suffix's are only of the form 'Sr', 'Jr', 'Sr.', 'Jr.'
The Database is case insensitive
IF OBJECT_ID('tempdb..#cte_SpaceFix') IS NOT NULL
DROP TABLE #cte_SpaceFix
;WITH cte_OriginalData (FullName)
AS (
SELECT 'Andy D Where'
UNION
SELECT 'Cathy T Landers'
UNION
SELECT 'Ms Annie Wint There'
UNION
SELECT 'Ms Annie Wint There Jr'
UNION
SELECT 'Mrs Annie There Jr'
UNION
SELECT 'Frank Fields'
UNION
SELECT 'Howdy U Pokes Jr.'
UNION
SELECT 'Howdy U Pokes Sr.'
UNION
SELECT 'Cathy T Landers Jr'
UNION
SELECT 'Landers Jr'
)
,cte_FullNameRemoveTail AS
(
SELECT LTRIM(RTRIM(FullName)) AS FullName
FROM cte_OriginalData
)
,cte_Parse_Prefix(Prefix,FullFirst_Prefix,FullName) AS
(
SELECT CASE
WHEN SUBSTRING(FullName, 1, 3) IN ('MR ','MS ','DR ','MRS')
THEN LTRIM(RTRIM(SUBSTRING(FullName, 1, 3)))
ELSE NULL
END AS Prefix,
CASE
WHEN SUBSTRING(FullName, 1, 3) IN ('MR ','MS ','DR ','MRS')
THEN LTRIM(RTRIM(SUBSTRING(FullName, 4, 8000)))
ELSE LTRIM(RTRIM(FullName))
END AS FullFirst_Prefix,
FullName
FROM cte_FullNameRemoveTail
)
,cte_Parse_Suffix(Prefix,FullFirst_Prefix_Suffix,Suffix,FullName) AS
(
SELECT Prefix,
CASE
WHEN RIGHT(FullFirst_Prefix,3) = ' JR' THEN LTRIM(RTRIM(SUBSTRING(FullFirst_Prefix,1,LEN(FullFirst_Prefix)-3)))
WHEN RIGHT(FullFirst_Prefix,4) = ' JR.' THEN LTRIM(RTRIM(SUBSTRING(FullFirst_Prefix,1,LEN(FullFirst_Prefix)-4)))
WHEN RIGHT(FullFirst_Prefix,3) = ' SR' THEN LTRIM(RTRIM(SUBSTRING(FullFirst_Prefix,1,LEN(FullFirst_Prefix)-3)))
WHEN RIGHT(FullFirst_Prefix,4) = ' SR.' THEN LTRIM(RTRIM(SUBSTRING(FullFirst_Prefix,1,LEN(FullFirst_Prefix)-4)))
ELSE LTRIM(RTRIM(FullFirst_Prefix))
END AS FullFirst_Prefix_Suffix,
CASE
WHEN RIGHT(FullFirst_Prefix,3) = ' JR'
OR RIGHT(FullFirst_Prefix,4) = ' JR.'
THEN 'Jr'
WHEN RIGHT(FullFirst_Prefix,3) = ' SR'
OR RIGHT(FullFirst_Prefix,4) = ' SR.'
THEN 'Sr'
ELSE NULL
END AS Suffix,
FullName
FROM cte_Parse_Prefix
)
,cte_SpaceFix(Prefix, FullFirst_Prefix_Suffix, Suffix, FullName) AS
(
SELECT Prefix,
CASE
WHEN LEN(FullFirst_Prefix_Suffix) - LEN(REPLACE(FullFirst_Prefix_Suffix, ' ', '')) > 2 THEN REPLACE(REPLACE(REPLACE(REPLACE(FullFirst_Prefix_Suffix,SPACE(5), SPACE(1)),SPACE(4), SPACE(1)),SPACE(3), SPACE(1)),SPACE(2), SPACE(1))
ELSE FullFirst_Prefix_Suffix
END AS FullFirst_Prefix_Suffix,
Suffix,
FullName
FROM cte_Parse_Suffix
)
SELECT * INTO #cte_SpaceFix
FROM cte_SpaceFix
;WITH cte_Parse_FirstName(Prefix, FirstName, Suffix, FullFirst_Prefix_Suffix_FirstName, FullName) AS
(
SELECT Prefix,
CASE
WHEN FullFirst_Prefix_Suffix IS NULL THEN NULL
WHEN LEN(FullFirst_Prefix_Suffix) - LEN(REPLACE(FullFirst_Prefix_Suffix, ' ', '')) >= 1 THEN LEFT(FullFirst_Prefix_Suffix,CHARINDEX(' ',FullFirst_Prefix_Suffix))
WHEN LEN(FullFirst_Prefix_Suffix) - LEN(REPLACE(FullFirst_Prefix_Suffix, ' ', '')) = 0 THEN FullFirst_Prefix_Suffix
ELSE NULL
END AS FirstName,
Suffix,
CASE
WHEN FullFirst_Prefix_Suffix IS NULL THEN NULL
WHEN LEN(FullFirst_Prefix_Suffix) - LEN(REPLACE(FullFirst_Prefix_Suffix, ' ', '')) >= 1 THEN LTRIM(RTRIM(REPLACE(FullFirst_Prefix_Suffix,LEFT(FullFirst_Prefix_Suffix,CHARINDEX(' ',FullFirst_Prefix_Suffix)),'')))
WHEN LEN(FullFirst_Prefix_Suffix) - LEN(REPLACE(FullFirst_Prefix_Suffix, ' ', '')) = 0 THEN NULL
ELSE NULL
END AS FullFirst_Prefix_Suffix_FirstName,
FullName
FROM #cte_SpaceFix
)
,cte_Parse_LastName(Prefix, FirstName, LastName, Suffix, MiddleName, FullName) AS
(
SELECT Prefix,
FirstName,
CASE
WHEN FullFirst_Prefix_Suffix_FirstName IS NULL THEN NULL
WHEN LEN(FullFirst_Prefix_Suffix_FirstName) - LEN(REPLACE(FullFirst_Prefix_Suffix_FirstName, ' ', '')) >= 1 THEN SUBSTRING(FullFirst_Prefix_Suffix_FirstName,CHARINDEX(' ',FullFirst_Prefix_Suffix_FirstName)+1,8000)
WHEN LEN(FullFirst_Prefix_Suffix_FirstName) - LEN(REPLACE(FullFirst_Prefix_Suffix_FirstName, ' ', '')) = 0 THEN FullFirst_Prefix_Suffix_FirstName
ELSE NULL
END AS LastName,
Suffix,
CASE
WHEN FullFirst_Prefix_Suffix_FirstName IS NULL THEN NULL
WHEN LEN(FullFirst_Prefix_Suffix_FirstName) - LEN(REPLACE(FullFirst_Prefix_Suffix_FirstName, ' ', '')) >= 1 THEN LEFT(FullFirst_Prefix_Suffix_FirstName,CHARINDEX(' ',FullFirst_Prefix_Suffix_FirstName))
ELSE NULL
END AS MiddleName,
FullName
FROM cte_Parse_FirstName
)
SELECT Prefix, FirstName, MiddleName, LastName, Suffix--, FullName
FROM cte_Parse_LastName
IF OBJECT_ID('tempdb..#cte_SpaceFix') IS NOT NULL
DROP TABLE #cte_SpaceFix

How to generate revoke statement on postgresql 9.3.x

Team,
I am working on amazon RDS Postgres ( 9.3.1 / 9.3.2 / 9.3.3 )
pgtest=> select version();
version
--------------------------------------------------------------------------------------------------------------
PostgreSQL 9.3.3 on x86_64-unknown-linux-gnu, compiled by gcc (GCC) 4.6.3 20120306 (Red Hat 4.6.3-2), 64-bit
(1 row)
I am generating revoke statement dynamically using below script. this works on amazon redshift. but not in Postgres. it gives error. Could anyone correct me? I am able to fetch query output for subquery on this.
note: in redshift, as of now trigger is not supported. so I have excluded "trigger" in the revoke list. But I am trying to execute now in AMAZON RDS Postgres
select
'revoke ' || substring(
case when charindex('r',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',select ' else '' end
||case when charindex('w',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',update ' else '' end
||case when charindex('a',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',insert ' else '' end
||case when charindex('d',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',delete ' else '' end
||case when charindex('R',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',rule ' else '' end
||case when charindex('x',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',references ' else '' end
||case when charindex('X',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',execute ' else '' end
||case when charindex('U',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',usage ' else '' end
||case when charindex('C',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',create ' else '' end
||case when charindex('T',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',temporary ' else '' end
, 2,10000)
|| ' on '||namespace||'.'||item ||' from "'||pu.usename||'";' 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
) as AA join pg_user pu on array_to_string(relacl, '|') like '%'||pu.usename||'%'
where relacl is not null
and pu.usename='test_user55';
I am getting below error:
dbsa_db=> select
dbsa_db-> 'revoke ' || substring(
dbsa_db(> case when charindex('r',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',select ' else '' end
dbsa_db(> ||case when charindex('w',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',update ' else '' end
dbsa_db(> ||case when charindex('a',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',insert ' else '' end
dbsa_db(> ||case when charindex('d',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',delete ' else '' end
dbsa_db(> ||case when charindex('R',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',rule ' else '' end
dbsa_db(> ||case when charindex('x',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',references ' else '' end
dbsa_db(> ||case when charindex('X',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',execute ' else '' end
dbsa_db(> ||case when charindex('U',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',usage ' else '' end
dbsa_db(> ||case when charindex('C',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',create ' else '' end
dbsa_db(> ||case when charindex('T',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',temporary ' else '' end
dbsa_db(> , 2,10000)
dbsa_db-> || ' on '||namespace||'.'||item ||' from "'||pu.usename||'";' as grantsql
dbsa_db-> from
dbsa_db-> (SELECT
dbsa_db(> use.usename as subject,
dbsa_db(> nsp.nspname as namespace,
dbsa_db(> c.relname as item,
dbsa_db(> c.relkind as type,
dbsa_db(> use2.usename as owner,
dbsa_db(> c.relacl
dbsa_db(> FROM
dbsa_db(> pg_user use
dbsa_db(> cross join pg_class c
dbsa_db(> left join pg_namespace nsp on (c.relnamespace = nsp.oid)
dbsa_db(> left join pg_user use2 on (c.relowner = use2.usesysid)
dbsa_db(> WHERE
dbsa_db(> c.relowner = use.usesysid
dbsa_db(> and nsp.nspname NOT IN ('pg_catalog', 'pg_toast', 'information_schema')
dbsa_db(> ORDER BY subject, namespace, item
dbsa_db(> ) as AA join pg_user pu on array_to_string(relacl, '|') like '%'||pu.usename||'%'
dbsa_db-> where relacl is not null
dbsa_db-> and pu.usename='test_user55';
ERROR: function charindex(unknown, text) does not exist
LINE 3: case when charindex('r',split_part(split_part(a...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
dbsa_db=>
dbsa_db=>
dbsa_db=> SELECT
dbsa_db-> use.usename as subject,
dbsa_db-> nsp.nspname as namespace,
dbsa_db-> c.relname as item,
dbsa_db-> c.relkind as type,
dbsa_db-> use2.usename as owner,
dbsa_db-> c.relacl
dbsa_db-> FROM
dbsa_db-> pg_user use
dbsa_db-> cross join pg_class c
dbsa_db-> left join pg_namespace nsp on (c.relnamespace = nsp.oid)
dbsa_db-> left join pg_user use2 on (c.relowner = use2.usesysid)
dbsa_db-> WHERE
dbsa_db-> c.relowner = use.usesysid
dbsa_db-> and nsp.nspname NOT IN ('pg_catalog', 'pg_toast', 'information_schema')
dbsa_db-> ORDER BY subject, namespace, item;
subject | namespace | item | type | owner | relacl
-----------------+-----------+------------+------+-----------------+-------------------------------------------------------------------------------------------------------------------------
test_user55 | schema1 | table_mmar | r | test_user55 |
dbsa | schema1 | table1 | r | dbsa | {dbsa=arwdDxt/dbsa,service_user1=a*r*w*d*D*x*t*/dbsa,service_user2=a*r*w*d*D*x*t*/dbsa}
dbsa | schema1 | view1 | v | dbsa | {dbsa=arwdDxt/dbsa,service_user1=a*r*w*d*D*x*t*/dbsa,service_user2=a*r*w*d*D*x*t*/dbsa,test_user55=r/service_user1}
(3 rows)
dbsa_db=>
(ii) query2 :
below query iam using to extract if any grants given at schemalevel. this works fine in redshift. But not in postgre 9.3.3
select
'revoke ' || substring(
case when charindex('U',split_part(split_part(array_to_string(nspacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',usage ' else '' end
||case when charindex('C',split_part(split_part(array_to_string(nspacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',create ' else '' end
, 2,10000)
|| ' on schema '||nspname||' from "'||pu.usename||'";' as syntax
from pg_namespace pn,pg_user pu
where pu.usename='test_user55' and array_to_string(nspacl,',') like '%'||pu.usename||'%'
and nspowner >= 1 ;
dbsa_db=> select substring(
dbsa_db(> case when charindex('U',split_part(split_part(array_to_string(nspacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',usage ' else '' end , 2,10000),
dbsa_db-> substring(
dbsa_db(> case when charindex('C',split_part(split_part(array_to_string(nspacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',create ' else '' end , 2,10000)
dbsa_db-> ,nspname
dbsa_db-> from pg_namespace pn, pg_user pu
dbsa_db-> where pu.usename='test_user55' and array_to_string(nspacl,',') like '%'||pu.usename||'%'
dbsa_db-> and nspowner > 1 ;
ERROR: function charindex(unknown, text) does not exist
LINE 2: case when charindex('U',split_part(split_part(array_...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
dbsa_db=>
(iii) query3
below query I am using to check if any grant given at database level. this works fine with redshift, but not with rds postgres.
dbsa_db=> grant all on database dbsa_db to test_user55;
GRANT
dbsa_db=>
select pu.usename, pd.datname, substring(
case when charindex('C',split_part(split_part(array_to_string(datacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',create ' else '' end, 2,10000),
substring(
case when charindex('T',split_part(split_part(array_to_string(datacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',temp ' else '' end, 2,10000)
from pg_database pd,pg_user pu
where pu.usename='test_user55' and array_to_string(datacl,',') like '%'||pu.usename||'%'
and datdba > 1;
dbsa_db=> select pu.usename, pd.datname, substring(
dbsa_db(> case when charindex('C',split_part(split_part(array_to_string(datacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',create ' else '' end, 2,10000),
dbsa_db-> substring(
dbsa_db(> case when charindex('T',split_part(split_part(array_to_string(datacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',temp ' else '' end, 2,10000)
dbsa_db-> from pg_database pd,pg_user pu
dbsa_db-> where pu.usename='test_user55' and array_to_string(datacl,',') like '%'||pu.usename||'%'
dbsa_db-> and datdba > 1;
ERROR: function charindex(unknown, text) does not exist
LINE 2: case when charindex('C',split_part(split_part(ar...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
dbsa_db=>
Please guide me.
Thanks.
PostgreSQL does not have a charindex function, Amazon Redshift added this on as sort of a synonym to strpos. For Amazon RDS using PostgreSQL, you can use position or strpos functions instead.
Example: Amazon Redshift you can do this:
select charindex('fish', 'dogfish');
For Amazon RDS using PostgreSQL you can do one of these two:
select strpos('dogfish', 'fish');
select position('fish' in 'dogfish');
Note that the substring and string in strpos are reversed!!
All results will be 4.
In addition, here is documentation on PostgreSQL string functions:
http://www.postgresql.org/docs/8.3/static/functions-string.html

How to find the privileges granted to a user in AWS Redshift?

I am using a Redshift cluster.
Version:
PostgreSQL 8.0.2 on i686-pc-linux-gnu, compiled by GCC gcc (GCC) 3.4.2 20041017 (Red Hat 3.4.2-6.fc3), Redshift 1.0.735
I just need to drop a user but it gives the following error message:
redshiftpocdb=# drop user test_55;
ERROR: user "test_55" cannot be dropped because the user has a privilege on some object
Here is the output of the \dp command:
redshiftpocdb=# \dp
Access privileges
schema | name | type | access privileges
--------+---------+-------+-------------------
public | company | table |
public | test2 | table |
public | test22 | table |
public | test222 | table |
public | v_date | table |
(5 rows)
In a Postgresql environment, we have the command DROP OWNED BY but it does not work in Redshift.
How can I find out what privileges were granted to the TEST_55 user? Is there any system view we can query ( for e..g in Oracle, we have DBA_ROLE_PRIVS, DBA_TAB_PRIVS...DBA_SYS_PRIVS .etc )?
To be able to drop a user, you have to (at least)
if they own any objects, change the owner to a different user
remove grants from any objects
remove them from groups
remove grants from schemas
You can use this to find any tables they own (then run "alter table owner to "):
select * from pg_tables where tableowner = 'test_55'
You can use this to build the script to revoke any grants:
select relacl ,
'revoke ' || substring(
case when charindex('r',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',select ' else '' end
||case when charindex('w',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',update ' else '' end
||case when charindex('a',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',insert ' else '' end
||case when charindex('d',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',delete ' else '' end
||case when charindex('R',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',rule ' else '' end
||case when charindex('x',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',references ' else '' end
||case when charindex('t',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',trigger ' else '' end
||case when charindex('X',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',execute ' else '' end
||case when charindex('U',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',usage ' else '' end
||case when charindex('C',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',create ' else '' end
||case when charindex('T',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',temporary ' else '' end
, 2,10000)
|| ' on '||namespace||'.'||item ||' from "'||pu.usename||'";' 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_user pu on array_to_string(relacl, '|') like '%'||pu.usename||'%'
where relacl is not null
and pu.usename='test_55'
You can use a variation of this query to see if a user belongs to any groups (then use "alter group drop user "):
select usesysid, usename, nvl(groname,'default') from pg_user u
left join pg_group g on ','||array_to_string(grolist,',')||','
like '%,'||cast(usesysid as varchar(10))||',%'
where usename='test_55' order by 2,1;
You can use this query to see if they have any schema grants:
select * from pg_namespace where nspowner > 1 and array_to_string(nspacl,',') like '%test_55%';
Another variation, to get all users' privilege organized together:
WITH
usrs as (SELECT * FROM pg_user),
objs as (
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')
),
query as (
SELECT
schemaname,
objectname,
usename,
HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'select') AS sel,
HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'insert') AS ins,
HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'update') AS upd,
HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'delete') AS del,
HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'references') AS ref
FROM objs, usrs
ORDER BY fullobj
)
SELECT * FROM query
WHERE (
sel = TRUE
OR ins = TRUE
OR upd = TRUE
OR del = TRUE
OR ref = TRUE
) AND schemaname='[optional schemaname]'
AND usename = '[optional username]';
I had to use || to concatenate strings, and a little difference as I have case-sensitive object names
'"' || schemaname || '"."' || tablename || '"' AS fullobj
'"' || schemaname || '"."' || viewname || '"' AS fullobj
instead of
schemaname + '.' + tablename AS fullobj
schemaname + '.' + viewname AS fullobj