Related
DO
$$BEGIN
EXECUTE FORMAT('create table prouduct_pivots AS ' ||
'SELECT * FROM CROSSTABLE(%L, %L) AS ct(day date, %s)',
'SELECT DATE_TRUNC(''day'', s.transation_date) AS day, product.name, count(*) cnt FROM sale s, product p WHERE s.product_id = product.id GROUP BY DATE_TRUNC(''day'', sale.transation_date), product.name
ORDER BY 1'
'SELECT DISTINCT name FROM product ORDER BY 1',
(SELECT STRING_AGG(replace(name, '', '_') || 'text', ',') FROM product ORDER BY 1)
);
END$$;
SELECT * FROM product_pivot;
I am using listagg to group users having same permissions, based on the query from the below stack question, tweaked it a bit for my needs.
How do I view grants on Redshift
This fails saying listagg is compute node function and should be used on user created table. Any way to use listagg on catalog tables and has_*_privilege function both of which runs on leader node?
with cte1 as (
SELECT *
FROM
( SELECT
fullobj
,usename
,case when HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'select') AND has_schema_privilege(usrs.usename, schemaname, 'usage') then 'S' else '' end ||
case when HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'insert') AND has_schema_privilege(usrs.usename, schemaname, 'usage') then 'I' else '' end ||
case when HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'update') AND has_schema_privilege(usrs.usename, schemaname, 'usage') then 'U' else '' end ||
case when HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'delete') AND has_schema_privilege(usrs.usename, schemaname, 'usage') then 'D' else '' end ||
case when HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'references') AND has_schema_privilege(usrs.usename, schemaname, 'usage') then 'R' else '' end AS perm
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 usename::text FROM pg_user) AS usrs
ORDER BY fullobj
) WHERE perm != '')
select fullobj, perm, listagg(usename,',') from cte1 group by fullobj, perm;
SQL Error [500310] [XX000]: [Amazon](500310) Invalid operation: One or more of the used functions must be applied on at least one user created tables. Examples of user table only functions are LISTAGG, MEDIAN, PERCENTILE_CONT, etc;
I tried to store the query output in a table, but its not allowing to store the table since the has_table_privilege function is leader-only function
create table user_perms as
SELECT *
FROM
( SELECT
fullobj
,usename
,case when HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'select') AND has_schema_privilege(usrs.usename, schemaname, 'usage') then 'S' else '' end ||
case when HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'insert') AND has_schema_privilege(usrs.usename, schemaname, 'usage') then 'I' else '' end ||
case when HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'update') AND has_schema_privilege(usrs.usename, schemaname, 'usage') then 'U' else '' end ||
case when HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'delete') AND has_schema_privilege(usrs.usename, schemaname, 'usage') then 'D' else '' end ||
case when HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'references') AND has_schema_privilege(usrs.usename, schemaname, 'usage') then 'R' else '' end AS perm
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 usename::text FROM pg_user) AS usrs
ORDER BY fullobj
) WHERE perm != '';
SQL Error [500310] [0A000]: [Amazon](500310) Invalid operation: Specified types or functions (one per INFO message) not supported on Redshift tables.;
Is there any solution to this issue of being able to run listagg on leader node function/tables?
No.
As you have correctly understood, listagg is a function implemented by Redshift, rather than being inherited from Postgres/Paraccel, and it has been implemented only on the worker nodes.
The has function is from Postgres, and is implemented only on the leader-node.
The query planner will not permit a query using a leader-node only function to recruit worker nodes, so you cannot call listagg.
(BTW, if I remember correctly, that 'v' for reltype is also going to pick up materialized views.)
As an aside, you can in fact obtain the information you are looking for directly from the system tables, but this is a long and complex undertaking. I am a Redshift specialist and it took me two months for the first version, although I was working at the time.
I am having problems with a report generated in SSRS producing different data than that datasource/dataset does otherwise, explained in detail here.
I found a suggestion on another post that "You may want to comment out your print statements and try that."
So I looked at the SP/dataset in question and see that it does have two Print statements:
Print(#Price)
. . .
Print(#SQLstring)
Execute(#SQLstring)
I don't know what the advantage might be of having print statements like this in a SP in the first place. Are there any possible negative repurcussions from commenting them out?
UPDATE
When I tried to go ahead and "just do it" and alter the SP in Database Workbench (a product I heartily recommend, BTW, and have no affiliation with) by commenting out the two print statements, it told me I had a syntax error, but I don't know where it might be, as there are gobs of "("s in the SP. Here is what it told me:
Incorrect syntax near '('.
while executing:
ALTER Procedure [dbo].[sp_ViewPriceMatrix_Variance_RockBottom]
. . .
Is there a T-SQL Lint online tool that could tell me which left paren is problematic? I googled for one, but couldn't find anything. The entire SP is:
ALTER Procedure [dbo].[sp_ViewPriceMatrix_Variance_RockBottom]
#Unit varchar(4000),
#BegDate datetime,
#EndDate datetime,
#SortBy varchar(20)
AS
DECLARE
#SQLstring varchar(max),
#Statement varchar(8000),
#ShortName varchar(50),
#ItemCode varchar(25),
#PriceWeek varchar(30),
#LastPriceWeek varchar(30),
#Week int,
#WherePriceWeek varchar(2000),
#Price varchar(25),
#Contractprice int,
#CalendarBegDate datetime,
#CalendarEndDate datetime
ALTER table #Temp
(
Unit varchar(50),
ShortName varchar(25),
ItemCode varchar(50),
Description varchar(250),
regionorder int,
Contractprice varchar(50),
Price varchar(25),
Variance varchar(25),
PriceWeek varchar(50),
Week varchar(10)
)
-- create temp table
Select up.Unit, mm.ShortName,
up.ItemCode, Description=(Select Description from MasterProducts where ItemCode=up.itemcode),
mm.regionorder, up.Contractprice
into #TempContract From UnitProducts up
Inner Join Unitmembers um on up.Unit=um.Unit and abs(um.pricesheet) = 1
Inner Join Members mm on um.memberno = mm.memberno
where up.Unit = #Unit
Select #CalendarBegDate = C.BeginDate From Calendar C where #BegDate between C.BeginDate and C.EndDate
Select #CalendarEndDate = C.EndDate From Calendar C where #EndDate between C.BeginDate and C.EndDate
-- get weeks and where clause
SET #WherePriceWeek = ' Where '
Declare GetPriceWeek Cursor For
Select [PriceWeek] = C.Description, C.BeginDate
From Calendar C
where C.BeginDate <= #CalendarEndDate and C.EndDate >= #CalendarBegDate
Order By 2
Open GetPriceWeek
fetch next from GetPriceWeek into #PriceWeek, #BegDate
while ##fetch_status = 0
begin
Select #Statement = ('Alter Table #TempContract Add [' + #PriceWeek + '] numeric(8,2) ')
exec (#Statement)
IF(#WherePriceWeek<>' Where ')
Begin
SET #WherePriceWeek = #WherePriceWeek + 'or '
End
SET #WherePriceWeek = #WherePriceWeek + 'IsNull(['+#PriceWeek+'],''0.00'') <> ''999.99'' '
fetch next from GetPriceWeek into #PriceWeek, #BegDate
end
Close GetPriceWeek
Deallocate GetPriceWeek
-- build member data by weeks
Declare GetMemberColumns Cursor For
SELECT distinct ShortName,ItemCode
FROM #TempContract
Order by ShortName,ItemCode
Open GetMemberColumns
fetch next from GetMemberColumns into #ShortName,#ItemCode
while ##fetch_status = 0
begin
Declare GetMemberPrice Cursor For
Select [PriceWeek] = C.Description, convert(varchar(20),
cast(IsNull(mp.Price,0) as numeric(8,2))) as Price,
up.Contractprice
From MemberPrice mp
Inner Join UnitProducts up on mp.unit=up.unit and mp.itemcode=up.itemcode
Inner Join Unitmembers um on mp.memberno=um.memberno and mp.unit=um.unit and abs
(um.pricesheet) = 1
Inner Join Members mm on mp.memberno = mm.memberno
Inner Join Calendar C on mp.CYear=C.CYear and mp.Cweek=C.CWeek
where mp.Unit = #Unit and C.BeginDate <= #CalendarEndDate and C.EndDate >= #CalendarBegDate
and mm.ShortName = #ShortName and Mp.ItemCode = #ItemCode
Open GetMemberPrice
fetch next from GetMemberPrice into #PriceWeek,#Price,#Contractprice
while ##fetch_status = 0
begin
--Print(#Price)
Select #Statement = ('Update #TempContract Set [' + #PriceWeek + ']=''' +
IsNull(#Price,'0.00') + ''' where ItemCode=''' + #ItemCode + ''' and Unit=''' + #Unit + ''' and
[ShortName]=''' + #ShortName +'''')
exec (#Statement)
fetch next from GetMemberPrice into #PriceWeek,#Price,#Contractprice
end
Close GetMemberPrice
Deallocate GetMemberPrice
fetch next from GetMemberColumns into #ShortName,#ItemCode
end
Close GetMemberColumns
Deallocate GetMemberColumns
--Select * From #TempContract
-- final select statement
SET #Week = 0
SET #LastPriceWeek = ''
SET #SQLstring = ''
Declare SetPriceWeekSQL Cursor For
Select [PriceWeek] = C.Description, C.BeginDate
From Calendar C
where C.BeginDate between #CalendarBegDate and #CalendarEndDate
Order By 2
Open SetPriceWeekSQL
fetch next from SetPriceWeekSQL into #PriceWeek, #BegDate
while ##fetch_status = 0
begin
SET #Week = #Week + 1
IF(#SQLstring='')
Begin
SET #SQLstring = #SQLstring + 'Insert Into #Temp Select Unit, ShortName, ItemCode,
Description, regionorder, Contractprice, IsNull('+
'['+#PriceWeek+'],''0.00'') as Price, (convert(decimal(10,3),''-0.001'')) as
Variance,
'''+#PriceWeek+''' as PriceWeek, ''WK'+convert(varchar(2),#Week)+''' as Week From
#TempContract'+#WherePriceWeek
IF(#SortBy='Members')
Begin
SET #SQLstring = #SQLstring + ' UNION Select Unit, ShortName, '''',
''zzzz'', '''', '''', ''0'' as Price, ''-0.001'' as Variance, '''' as PriceWeek, ''WK'+convert(varchar
(2),#Week)+''' as Week From #TempContract'+#WherePriceWeek
End
Else
Begin
SET #SQLstring = #SQLstring + ' UNION Select Unit, '''', ItemCode,
Description, ''1000'', Contractprice, ''0'' as Price, ''-0.001'' as Variance, '''' as PriceWeek,
''WK'+convert(varchar(2),#Week)+''' as Week From #TempContract'+#WherePriceWeek
End
End
ELSE
Begin
SET #SQLstring = #SQLstring + ' UNION '
SET #SQLstring = #SQLstring + 'Select Unit, ShortName, ItemCode, Description,
regionorder, Contractprice, IsNull('+
'['+#PriceWeek+'],''0.00'') as Price, IsNull(convert(decimal(10,2),['+#PriceWeek
+'])-convert(decimal(10,2),['+#LastPriceWeek+']),''0.00'') as Variance,
'''+#PriceWeek+''' as PriceWeek, ''WK'+convert(varchar(2),#Week)+''' as Week From
#TempContract'+#WherePriceWeek
IF(#SortBy='Members')
Begin
SET #SQLstring = #SQLstring + ' UNION Select Unit, ShortName, '''',
''zzzz'', '''', '''', ''0'' as Price, ''0'' as Variance, '''' as PriceWeek, ''WK'+convert(varchar
(2),#Week)+''' as Week From #TempContract Where IsNull(['+#LastPriceWeek+'],''0.00'') <> ''999.99'' or
IsNull(['+#PriceWeek+'],''0.00'') <> ''999.99'' '
End
Else
Begin
SET #SQLstring = #SQLstring + ' UNION Select Unit, '''', ItemCode,
Description, ''1000'', Contractprice, ''0'' as Price, ''0'' as Variance, '''' as PriceWeek, ''WK'+convert
(varchar(2),#Week)+''' as Week From #TempContract Where IsNull(['+#LastPriceWeek+'],''0.00'') <> ''999.99''
or IsNull(['+#PriceWeek+'],''0.00'') <> ''999.99'' '
End
End
SET #LastPriceWeek = #PriceWeek
fetch next from SetPriceWeekSQL into #PriceWeek, #BegDate
end
Close SetPriceWeekSQL
Deallocate SetPriceWeekSQL
--Print(#SQLstring)
Execute(#SQLstring)
Drop Table #TempContract
IF(#SortBy='Members')
Begin
Select
Unit,
ShortName,
ItemCode,
Description,
regionorder,
Contractprice,
convert(varchar(20),convert(decimal(10,2),Price)) as Price,
sum(convert(money,Variance)) as Variance,
VarianceAverage = convert(varchar(25),convert(decimal(10,2),(Select sum(convert
(money,Variance)) From #Temp Where ShortName=T.ShortName and Week=T.Week) / Replace(((Select count
(regionorder) From #Temp Where ShortName=T.ShortName and Week=T.Week)-count(Variance)),'0','1'))),
PriceWeek,Week
From #Temp T
Group By
Unit,
ShortName,
ItemCode,
Description,
regionorder,
Contractprice,
Price,
PriceWeek,Week
Order By Week,ShortName,Description
End
ELSE
Begin
Select
Unit,
ShortName,
ItemCode,
Description,
regionorder,
Contractprice,
convert(varchar(20),convert(decimal(10,2),Price)) as Price,
sum(convert(money,Variance)) as Variance,
VarianceAverage = convert(varchar(25),convert(decimal(10,2),(Select sum(convert
(money,Variance)) From #Temp Where ItemCode=T.ItemCode and Week=T.Week) / Replace(((Select count
(regionorder) From #Temp Where ItemCode=T.ItemCode and Week=T.Week)-count(Variance)),'0','1'))),
PriceWeek,Week
From #Temp T
Group By
Unit,
ShortName,
ItemCode,
Description,
regionorder,
Contractprice,
Price,
PriceWeek,Week
Order By Week,Description,regionorder
End
Drop Table #Temp
The Print statements are for debug. You can "just do it".
Change "ALTER table #Temp" for "CREATE table #Temp".
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
below is the program written in oracle plsql when this program is run by giving P_LOC value as 'DALLAS'
it gives error as -904 ORA-00904: "DALLAS": invalid identifier please provide a solution
create or replace
PROCEDURE PR_EMP_LST1
( P_LOC IN VARCHAR2
, P_MIN_SAL IN NUMBER
, P_MAX_SAL IN NUMBER
, P_REF_CUR OUT SYS_REFCURSOR
) AS
TYPE TY_LST_REFCURSOR IS REF CURSOR ;
cur_emp_lst TY_LST_REFCURSOR;
v_inv_query VARCHAR2(2000);
V_USG_CL VARCHAR2(200);
BEGIN
IF P_LOC IS NULL AND p_min_sal IS NULL AND p_max_sal IS NULL THEN
v_inv_query :='SELECT ENAME
FROM EMP ';
ELSE
v_inv_query :='SELECT ENAME
FROM EMP WHERE ';
IF P_LOC IS NULL AND p_min_sal IS NOT NULL AND p_max_sal IS NOT NULL THEN
v_inv_query :=v_inv_query ||' SAL BETWEEN '
||p_min_sal
||' AND '
|| p_max_sal;
-- v_inv_query :=v_inv_query ||' SAL BETWEEN :1 AND :2 ';
dbms_output.put_line('2');
-- V_USG_CL:= ' USING '||p_min_sal||' , '|| p_max_sal;
ELSIF P_LOC IS NOT NULL AND p_min_sal IS NOT NULL AND p_max_sal IS NOT NULL THEN
dbms_output.put_line('1');
v_inv_query :=v_inv_query||' SAL BETWEEN '
||p_min_sal || ' AND '|| p_max_sal
|| ' AND DEPTNO IN (SELECT DEPTNO
FROM DEPT
WHERE LOC= '
|| p_loc
||' )';
dbms_output.put_line('2');
ELSIF P_LOC IS NOT NULL AND p_min_sal IS NULL AND p_max_sal IS NOT NULL THEN
v_inv_query :=v_inv_query||' SAL <= '
||p_max_sal
||' AND DEPTNO IN (SELECT DEPTNO
FROM DEPT
WHERE LOC= '
|| p_loc
||' )';
ELSIF P_LOC IS NOT NULL AND p_min_sal IS NOT NULL AND p_max_sal IS NULL THEN
v_inv_query :=v_inv_query||' SAL >= '
||p_min_sal
||' AND DEPTNO IN (SELECT DEPTNO
FROM DEPT
WHERE LOC= '
||p_loc
||' )';
ELSIF P_LOC IS NULL AND p_min_sal IS NULL AND p_max_sal IS NOT NULL THEN
v_inv_query :=v_inv_query||' SAL <= '
||p_max_sal;
ELSIF P_LOC IS NULL AND p_min_sal IS NOT NULL AND p_max_sal IS NULL THEN
v_inv_query :=v_inv_query||' SAL >= '
|| p_min_sal;
ELSIF P_LOC IS NOT NULL AND p_min_sal IS NULL AND p_max_sal IS NULL THEN
v_inv_query :=v_inv_query||' DEPTNO IN (SELECT DEPTNO
FROM DEPT
WHERE LOC= '
||p_loc
||' )';
END IF;
END IF;
dbms_output.put_line('3');
dbms_output.put_line(v_inv_query );
OPEN cur_emp_lst FOR v_inv_query ;
dbms_output.put_line('4');
P_REF_CUR:=cur_emp_lst;
END PR_EMP_LST1;
'SELECT DEPTNO FROM DEPT WHERE LOC= ''' || p_loc ||''' )';
As Dallas is string, you need to handle it as string: 'DALLAS' and not as DALLAS. Inside of string you have to use ''
P_LOC parameter is string type, the parameter value should be enclosed within single quotes.
In existing dynamic SQL condition, the single quotes are not present.
Please replace below condition with new condition.
Existing Condition:
|| ' AND DEPTNO IN (SELECT DEPTNO FROM DEPT WHERE LOC= ' || p_loc ||' )';
New Condition:
|| q'[ AND DEPTNO IN (SELECT DEPTNO FROM DEPT WHERE LOC= ']' || p_loc || q'[' )]';
Thank you...