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...
Related
I have a very big table but as an example I will only provide a very small part of it as following:-
col1 col2 col3 col4
10 2 12
13 4 11
0 1
3 5 111
I know how to find null values in one column. What I want to find is how many null values are there in each column just by writing one query.
Thanks in advance
You can use an aggregate with a filter:
select count(*) filter (where col1 is null) as col1_nulls,
count(*) filter (where col2 is null) as col2_nulls,
count(*) filter (where col3 is null) as col3_nulls,
count(*) filter (where col4 is null) as col4_nulls
from the_table;
I think you can generate this query on the fly. Here is an example of one way you can approach it:
CREATE OR REPLACE FUNCTION null_counts(tablename text)
RETURNS SETOF jsonb LANGUAGE plpgsql AS
$func$
BEGIN
RETURN QUERY EXECUTE 'SELECT to_jsonb(t) FROM (SELECT ' || (
SELECT string_agg('count(*) filter (where ' || a.attname::text || ' is null) as ' || a.attname || '_nulls', ',')
FROM pg_catalog.pg_attribute a
WHERE a.attrelid = tablename::regclass
AND a.attnum > 0
AND a.attisdropped = false
) || ' FROM ' || tablename::regclass || ') as t';
END
$func$;
SELECT null_counts('your_table') AS val;
The search filter in the function below doesn't seem to work. If I don't provide a search parameter, it works, otherwise I get no recordset back. I'm assuming I am making a mess of the single-quoting and ILIKE, but not sure how to re-write this properly. Suggestions?
CREATE OR REPLACE FUNCTION get_operator_basic_by_operator(
_operator_id UUID DEFAULT NULL,
_search TEXT DEFAULT NULL,
_page_number INTEGER DEFAULT 1,
_page_size INTEGER DEFAULT 10,
_sort_col TEXT DEFAULT 'username',
_sort_dir TEXT DEFAULT 'asc',
_include_deleted BOOLEAN DEFAULT FALSE
)
RETURNS TABLE (
id UUID,
party_id UUID,
party_name TEXT,
username VARCHAR(32),
profile_picture_uri VARCHAR(512),
first_name VARCHAR(64),
last_name VARCHAR(64),
street VARCHAR(128),
specifier VARCHAR(128),
city VARCHAR(64),
state VARCHAR(2),
zipcode VARCHAR(9),
primary_email CITEXT,
primary_phone VARCHAR(10),
secondary_email CITEXT,
secondary_phone VARCHAR(10),
last_login TIMESTAMP WITH TIME ZONE,
created TIMESTAMP WITH TIME ZONE,
deleted TIMESTAMP WITH TIME ZONE
)
AS $$
DECLARE
_offset BIGINT;
BEGIN
IF (_page_number < 1 OR _page_number IS NULL) THEN
RAISE EXCEPTION '_page_number cannot be null or less than 1.';
END IF;
IF (_page_size < 1 OR _page_size IS NULL) THEN
RAISE EXCEPTION '_page_size cannot be null or less than 1.';
END IF;
IF (_sort_dir <> 'asc' AND _sort_dir <> 'desc') THEN
RAISE EXCEPTION '_sort_dir must be "asc" or "desc".';
END IF;
_offset := (_page_size * (_page_number-1));
RETURN QUERY EXECUTE '
SELECT
o.id,
p.id,
p.party_name,
o.username,
o.profile_picture_uri,
o.first_name,
o.last_name,
o.street,
o.specifier,
o.city,
o.state,
o.zipcode,
o.primary_email,
o.primary_phone,
o.secondary_email,
o.secondary_phone,
o.last_login,
o.created,
o.deleted
FROM
operator o
LEFT JOIN
party p ON o.party_id = p.id
WHERE ( -- include all or only those active, based on _include_deleted
$1 OR o.deleted > statement_timestamp()
)
AND o.party_id IN ( -- limit to operators in same party
SELECT oi.party_id FROM operator oi WHERE oi.id = $2
)
AND ( -- use optional search filter
$3 IS NULL
OR
o.username ILIKE ''%$3%''
OR
o.first_name ILIKE ''%$3%''
OR
o.last_name ILIKE ''%$3%''
OR
o.primary_email ILIKE ''%$3%''
)
ORDER BY ' || quote_ident(_sort_col) || ' ' || _sort_dir || '
LIMIT
$4
OFFSET
$5'
USING _include_deleted, _operator_id, _search, _page_size, _offset;
END;
The parameter is inserted as a text with quotes, so you should use it this way:
...
o.username ILIKE concat(''%'', $3, ''%'')
...
Personally I would use format() and dollar-quotes.
Strings handles as is, you should to pass ready to use values:
EXECUTE '... o.username ILIKE $3 ...' using ..., '%' || _search || '%', ...
I want to get the SUM of two different SMALLINT fields from different tables in select procedure. I am using SQL Manager for Interbase and Firebird
The values of field TRAINING_SRCVDAYS in Table E are 1 and 2 while the value of field LEAVE_WITHPAY_NUMDAY in Table A is 2.
Table E Table A
1 2
2
Expected output(Sum) 3 2
real output to my procedure 3 4
here is my code. please help
CREATE PROCEDURE AAAASAMPLE(
UPDATEHANDLER VARCHAR(50) CHARACTER SET ISO8859_1 COLLATE ISO8859_1,
WHAT_YEAR VARCHAR(50) CHARACTER SET ISO8859_1 COLLATE ISO8859_1)
RETURNS(
FULLNAME VARCHAR(100) CHARACTER SET ISO8859_1 COLLATE ISO8859_1,
TRAINING_SRCVDAYS SMALLINT,
LEAVE_WITHPAY_NUMDAY SMALLINT,
SICKLEAVE SMALLINT)
AS
BEGIN
FOR
SELECT
C.EMP_SURNAME || ', ' || C.EMP_FIRSTNAME || ' ' || C.EMP_MIDDLENAME || ' '||C.EMP_SUFFIXNAME,
SUM(E.TRAINING_SRCVDAYS),
SUM(A.LEAVE_WITHPAY_NUMDAY),
SUM(E.TRAINING_SRCVDAYS) - SUM(A.LEAVE_WITHPAY_NUMDAY)
FROM LEAVE_TABLE A, POSITION_TABLE B, EMP_TABLE C, TRAINTRN_TABLE D, TRAINTYP_TABLE E
WHERE
(A.EMP_PK =: UPDATEHANDLER AND A.LEAVE_FROM_YEAR =: WHAT_YEAR AND A.EMP_PK = C.EMP_PK
AND A.POSITION_PK = B.POSITION_PK AND B.POSITION_CLASS_REF = 0 )
AND
(D.EMP_PK = C.EMP_PK AND D.TRAINING_PK = E.TRAINING_PK AND D.EMP_PK =: UPDATEHANDLER
AND E.TRAINING_SRVCCRDT = 'Yes' AND E.TRAINING_FROMYEAR =: WHAT_YEAR)
GROUP BY
C.EMP_SURNAME || ', ' || C.EMP_FIRSTNAME || ' ' || C.EMP_MIDDLENAME || ' '|| C.EMP_SUFFIXNAME
INTO
:FULLNAME,
:TRAINING_SRCVDAYS,
:LEAVE_WITHPAY_NUMDAY,
:SICKLEAVE
DO
BEGIN
SUSPEND;
END
END;
I have a few tables in Netezza, DB2 and PostgreSQL databases, for which I need to reconcile and the best way we have come out with is to do a SUM() across all the NUMERIC Table columns on all the 3 databases.
Does anyone have a quick and simple way to find all the COLUMNS which are either NUMERIC or INTEGER or BIGINT and then run a SUM() on all these?
For comparing the results, I can do it manually also, or if someone has a way to capture these results in a common table and automatically check the differences in the SUM?
For DB2 you can use this metadata which will help you to find out the data type for each column
SELECT
COLUMN_NAME || ' ' || REPLACE(REPLACE(DATA_TYPE,'DECIMAL','NUMERIC'),'CHARACTER','VARCHAR') ||
CASE
WHEN DATA_TYPE = 'TIMESTAMP' THEN ''
ELSE
' (' ||
CASE
WHEN CHARACTER_MAXIMUM_LENGTH IS NOT NULL THEN CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR(30))
WHEN NUMERIC_PRECISION IS NOT NULL THEN CAST(NUMERIC_PRECISION AS VARCHAR(30)) ||
CASE
WHEN NUMERIC_SCALE = 0 THEN ''
ELSE ',' || CAST(NUMERIC_SCALE AS VARCHAR(3))
END
ELSE ''
END || ')'
END || ',' "SQLCOL",
COLUMN_NAME,
DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, NUMERIC_SCALE, ORDINAL_POSITION
FROM SYSIBM.COLUMNS
WHERE TABLE_NAME = 'insert your table name'
AND TABLE_SCHEMA = 'insert your table schema'
ORDER BY ORDINAL_POSITION
For Netezza, I got the following query:
SELECT 0 AS ATTNUM, 'SELECT' AS SQL
UNION
SELECT ATTNUM, 'SUM(' || ATTNAME || ') AS S_' || ATTNAME || ',' AS COLMN
FROM _V_RELATION_COLUMN RC
WHERE NAME = '<table-name>'
AND FORMAT_TYPE= 'NUMERIC'
UNION
SELECT 10000 AS ATTNUM, ' 0 AS FLAG FROM ' || '<table-name>'
ORDER BY ATTNUM
Still looking how to do this across DB2 and PostgreSQL.
Here is a sample of my code
v_sql_main:= ' SELECT min_createdate, max_createdate, createdate, customerid::integer, deviceid::integer, null::bigint as sourceip, null::bigint as sourceip_int, service, total, end_recordid::bigint '||
' FROM ( '||
' SELECT min(date_trunc( '||quote_literal('HOUR')||' , firstoccurrence)) as min_createdate, '||
' max(date_trunc( '||quote_literal('HOUR')||' , firstoccurrence)) as max_createdate, '||
' date_trunc( '||quote_literal('DAY')||' , firstoccurrence) as createdate, '||
' customerid::integer, '||
' deviceid::integer, '||
' service, '||
case when v_days < 4 then
' count(1) as total '
else
' sum(summcount) as total '
end ||', max(recordid) as end_recordid'
' FROM '|| v_tablename||
' LEFT OUTER JOIN '|| v_child_tablename||
' ON ' ||v_tablename||'.SERVICE_ID = '|| v_child_tablename||'.SERVICE_ID '||
' WHERE '||
' customerid = v_customerid AND '||
' deviceid = v_deviceid AND '||
' date_trunc( '||quote_literal('DAY')||' , firstoccurrence) = date_trunc( '||quote_literal('DAY')||' ,now()- interval '1 day') '||
' group by date_trunc( '||quote_literal('DAY')||' , firstoccurrence), customerid, deviceid, service ) as a order by total desc limit 10;;';
When I try to execute this I am getting the following error
ERROR: syntax error at or near "1"
LINE 144: ...unc( '||quote_literal('DAY')||' ,now()- interval '1 day') '|...
What i need is to get: date-1
Thanks in Advance
SHABEER
Replace the line:
' date_trunc( '||quote_literal('DAY')||' , firstoccurrence) = date_trunc( '||quote_literal('DAY')||' ,now()- interval '1 day') '||
by:
' date_trunc( '||quote_literal('DAY')||' , firstoccurrence) = date_trunc( '||quote_literal('DAY')||' ,now()- interval '' 1 day'') '||
Please take a look to the Interval syntax documentation