Count giving wrong results in stored procedure - stored-procedures

I am getting incorrect count from a query ran inside a stored procedure.
When we run the same query ( after hard-coding the values of table name and schema name ) it gives the correct result.
Preliminary analysis , hints the fact that the query run inside the stored procedure is for some reason ignoring the second filter ( i.e where ... and ... , the second part is being ignored ).
CREATE OR REPLACE PROCEDURE dev.gp_count (tablename VARCHAR(256))
AS
$$ DECLARE schema_name VARCHAR(64);
table_name VARCHAR(128);
check_count_1 INT;
check_count_2 INT;
BEGIN
schema_name:= SPLIT_PART(tablename,'.',1);
table_name:= SPLIT_PART(tablename,'.',2);
check_count_1 := (select count(*) from information_schema.tables where table_schema = schema_name and table_name like '%' + table_name +'%');
raise info 'check_count_1 - %',check_count_1;
end;
$$
language plpgsql;
And calling the above procedure as-
call dev.gp_count ('dev.gp_test1');
The result obtained from stored procedure is -
Warnings:
check_count_1 - 925
If we run the same query after substituting the values for table name and schema then -
select count(*) from information_schema.tables where table_schema = 'dev' and table_name like '%gp_test1%';
RESULT -
count
3
Now investigating the issue further -
The count obtained from stored procedure is same as the count obtained from this query -
select count(*) from information_schema.tables where table_schema = 'dev';
RESULT-
count
925
My Guess -
So this hints that , maybe inside stored procedure the second filter condition is being ignored.
Besides helping me with other alternatives , please do help me find the reason behind this anomaly too .
Thanks in Advance.

I think your problem lies in 1) your string concatenation and 2) use of table_name as a variable:
check_count_1 := (select count(*) from information_schema.tables where table_schema = schema_name and table_name like '%' + table_name +'%');
PostgreSQL string concatenation uses ||, so it should look like this:
check_count_1 := (select count(*) from information_schema.tables where table_schema = schema_name and table_name like '%' || table_name || '%');
Try changing it to look like this:
CREATE OR REPLACE PROCEDURE gp_count (tablename VARCHAR(256))
AS
$$ DECLARE
schema_name VARCHAR(64);
table_name1 VARCHAR(128);
check_count_1 INT;
check_count_2 INT;
BEGIN
schema_name:= SPLIT_PART(tablename,'.',1);
table_name1:= SPLIT_PART(tablename,'.',2);
check_count_1 := (select count(*) from information_schema.tables f where table_schema = schema_name and f.table_name like '%' || table_name1 || '%');
raise info 'check_count_1 - %',check_count_1;
end;
$$
language plpgsql;
Disclosure: I work for EnterpriseDB (EDB)

Related

How to write multi line query in snowflake scripting in stored procedure

create or replace procedure create_src_table()
returns table (name varchar, age number(10,0),dob date)
language sql as
$$
declare
create_query varchar;
res resultset;
begin
create_query := `CREATE TEMPORARY TABLE SRC_TEMP_TBL AS SELECT * FROM
(WITH CTE_1 AS (SELECT * FROM "DB"."DW"."USER_TBL" WHERE name='rahul'),
CTE_2 AS (SELECT * FROM CTE_1 WHERE CAST(DOB AS DATE)<2000-05-01)
SELECT name,age,dob FROM CTE_2 limit 10)`;
res := (execute immediate : create_query);
return table(res);
end;
$$;
call create_src_table();
Could someone please help in how to write multiline sql query. I found few answers that indicate using backtick in javascript but not sure how to achieve it in sql.
Multi-statement SQL should be wrapped inside BEGIN ... END block:
EXECUTE IMMEDIATE 'BEGIN
statement1;
statement2;
...
END;';
Sample:

Solve the syntax error with Redshift operator does not exist and add explicit casts

I am a newbie in the area of redshift data modeling and got myself into trouble with an error.ERROR:
--Final version
syntax error ERROR: operator does not exist: text | record Hint: No
operator matches the given name and argument type(s). You may need to
add explicit type casts. Where: SQL statement "SELECT 'create temp
table ' || $1 || ' as select * from' | $2 |" PL/pgSQL function "egen"
line 36 at execute statement [ErrorId:
1-61dc32bf-0a451f5e2c2639235abb8876]
I am trying to do a simple transformation that gets returned in output when the procedure is called. (As of now I got to find from the documentation we have to use either temp table or cursors to achieve this)
Pseudocode:
I am trying to restrict data to its latest one in (2019) Get the
list of managers create columns if a person is a manager or not from the list.
Return it as a result
Data looks as follows Employee Data
My Select query works fine out of the procedure, please find my complete code below.
CREATE OR REPLACE PROCEDURE EGEN(tmp_name INOUT varchar(256) )
AS $$
DECLARE
--As i have less data managed to create it as an array or please use temp or table and join it with the actual query to perform transformation
MGR_RECORD RECORD;
DATAS RECORD;
item_cnt int := 0;
V_DATE_YEAR int := 0;
BEGIN
--EXECUTE (select cast(extract(year from current_date) as integer)-3) INTO V_DATE_YEAR;
--Manager Records are stored here below
SELECT DISTINCT managerid from "dev"."public"."emp_salary" INTO MGR_RECORD;
SELECT employeeid,
managerid,
promotion,
q_bonus,
d_salary,
case when contractor = 'x'
then 'TemporaryEmployee'
else 'PermanentEmployee'
END as EmployeeType,
-- IFstatement not supported under select query
case when employeeid in (select distinct managerid FROM "dev"."public"."emp_salary" )
then 'Manager'
else 'Ordinary FTE'
END as FTETYPE
FROM "dev"."public"."emp_salary" where cast(extract(year from promotion) as int ) >= 2019 into DATAS;
--COMMIT;
tmp_name := 'ManagerUpdatedTable';
EXECUTE 'drop table if exists ' || tmp_name;
EXECUTE 'create temp table ' || 'ManagerUpdatedTable' || ' as select * from' |DATAS| ;
END;
$$ LANGUAGE plpgsql;
-- Call tests CALL EGEN('myresult'); SELECT * from myresult;
Also, additional query (Can we replace )
case when employeeid in (select distinct managerid FROM "dev"."public"."emp_salary" )
then 'Manager'
else 'Ordinary FTE'
END as FTETYPE
this transform in query to IF , if possible please provide details.
Thanks and Regards,
Gabby

Convert Procedure from Oracle to DB2, Error when try to update table on runtime

Hello DB2 Experts I need your assistance in converting below Procedure to something more dynamic.
We have to update multiple sequences with max of id column for each table.
CREATE PROCEDURE mySchema.UPDATE_SEQUENCE ( )
DYNAMIC RESULT SETS 1
MODIFIES SQL DATA
----------------------------------------------------------------------
-- SQL Stored Procedure
----------------------------------------------------------------------
P1: BEGIN
DECLARE counter BIGINT;
DECLARE q VARCHAR(500);
set (counter) = (select max(N_PRI_KEY) from mySchema.myTable);
set q = 'alter sequence mySchema.mySequence RESTART WITH ' || counter;
EXECUTE IMMEDIATE q;
END P1
#
This is what I have written from the above code:
Here I want N_PRI_KEY to be dynamic and mySchema.myTable to be updated on run time with the values from the table.
CREATE OR REPLACE PROCEDURE getText ()
LANGUAGE SQL
DYNAMIC RESULT SETS 1
BEGIN
DECLARE maxval INTEGER DEFAULT 0;
CALL DBMS_OUTPUT.PUT( 'a' );
FOR vrows AS
SELECT NAME, SEQUENCENAME, TBNAME FROM MAXSEQUENCE WHERE SEQUENCENAME='ASSETSEQ'
DO
SELECT MAX(vrows.NAME) INTO maxval FROM vrow.TBNAME; -- This is where I am getting error.
EXECUTE IMMEDIATE 'ALTER SEQUENCE '||vrows.SEQUENCENAME||' RESTART WITH '|| maxval;
END FOR;
END#
This is the error that I am getting when I try to create the Procedure.
DB21034E The command was processed as an SQL statement because it was not a
valid Command Line Processor command. During SQL processing it returned:
SQL0204N "VROW.TBNAME" is an undefined name. LINE NUMBER=18. SQLSTATE=42704
When I run this line it works and inserts the max value in the TEMPOUTPUT table.
execute immediate 'INSERT INTO TEMPOUTPUT VALUES (select max('||vrow.NAME||') from '||vrow.TBNAME||')';
I have tried doing this but it did not work.
execute immediate 'ALTER SEQUENCE '||SEQUENCENAME||' RESTART WITH select max('||vrow.NAME||') from '||vrow.TBNAME;
Just for Reference - This is a procedure which is written in Oralce which is doing something similar.
declare
maxval int;
seqval int;
begin
for i in ( select ucc.column_name, s.sequence_name, uc.table_name
from user_cons_columns ucc,
user_constraints uc,
user_sequences s
where uc.constraint_name = ucc.constraint_name
and uc.constraint_type = 'P'
and ucc.position = 1
and s.sequence_name = 'SEQ_'||uc.table_name
)
loop
execute immediate 'select max('||i.column_name||') from '||i.table_name into maxval;
execute immediate 'select '||i.sequence_name||'.nextval from dual' into seqval;
dbms_output.put_line(maxval||','||seqval);
if maxval > seqval then
execute immediate 'alter sequence '||i.sequence_name||' increment by '|| ( maxval - seqval );
execute immediate 'select '||i.sequence_name||'.nextval from dual' into seqval;
execute immediate 'alter sequence '||i.sequence_name||' increment by 1';
execute immediate 'select '||i.sequence_name||'.nextval from dual' into seqval;
dbms_output.put_line(maxval||','||seqval);
end if;
end loop;
end;
Try the following instead of the row with SELECT MAX(...) where you get the error:
PREPARE S1 FROM 'SET ? = (SELECT MAX(' || vrows.NAME || ') FROM ' || vrows.TBNAME || ')';
EXECUTE S1 INTO maxval;

Dynamic query in Cursor for %rowtype

I need to create a record type to contain the result set of the above query of
V_SQL VARCHAR2(200) := 'SELECT T1.'||record_id||',T1.'||card_no||',T2.TEST_CARD_NO, T1.'||type_cc||' FROM '|| table_name||' T1
INNER JOIN TEST T2 ON
T2.ID = T1.'||record_id;
So that I can use t1 C_BRNGB_EXTRACT%ROWTYPE (plus another column for t2.col4%TYPE inside l_BRNGB_EXTRACT) inside loop execute statement
CREATE OR REPLACE PROCEDURE "GCCPMAINT"."FUNCTION_CURSOR"(table_name VARCHAR2,record_id VARCHAR2,card_no VARCHAR2,type_cc VARCHAR2)
AS
limit_in NUMBER:=100;
V_SQL VARCHAR2(200) := 'SELECT T1.'||record_id||',T1.'||card_no||',T2.TEST_CARD_NO, T1.'||type_cc||' FROM '|| table_name||' T1
INNER JOIN TEST T2 ON
T2.ID = T1.'||record_id;
TYPE BRNGB_EXTRACT IS REF CURSOR;
C_BRNGB_EXTRACT BRNGB_EXTRACT;
TYPE BRNGB_EXTRACT1 IS TABLE OF C_BRNGB_EXTRACT%ROWTYPE;
l_BRNGB_EXTRACT BRNGB_EXTRACT1;
BEGIN
OPEN C_BRNGB_EXTRACT FOR V_SQL;
LOOP
FETCH C_BRNGB_EXTRACT BULK COLLECT INTO l_BRNGB_EXTRACT LIMIT limit_in;
EXIT WHEN l_BRNGB_EXTRACT.COUNT = 0;
FORALL indx IN 1 .. l_BRNGB_EXTRACT.COUNT
EXECUTE IMMEDIATE 'UPDATE table_name SET CARD_NO=:1 WHERE CARD_NO=:2 AND RECORD_ID=:3' USING l_BRNGB_EXTRACT(indx).test_card_no,l_BRNGB_EXTRACT(indx).CARD_NO,l_BRNGB_EXTRACT(indx).RECORD_ID;
END LOOP;
CLOSE C_BRNGB_EXTRACT;
COMMIT;
END;
For a above stored procedure I'm getting the following error
PLS-00320: the declaration of the type of this expression is
incomplete or malformed PL/SQL: Item ignored PLS-00597: expression
'L_BRNGB_EXTRACT' in the INTO list is of wrong type PL/SQL: SQL
Statement ignored PLS-00487: Invalid reference to variable
'C_BRNGB_EXTRACT%ROWTYPE'
Please help me to solve this.
i got the solution
TYPE BRNGB_EXTRACT IS REF CURSOR;
C_BRNGB_EXTRACT BRNGB_EXTRACT;
-- TYPE BRNGB_EXTRACT1 IS TABLE OF C_BRNGB_EXTRACT%ROWTYPE;
TYPE BRNGB_EXTRACT1 IS RECORD (
record_id varchar(30),
card_no varchar(30),
TEST_CARD_NO varchar(30)
);
type test_rec_arr is table of BRNGB_EXTRACT1 index by pls_integer;
l_BRNGB_EXTRACT test_rec_arr;

check the null values for input parameters with oracle stored procedure

I am preparing stored procedure with oracle .I m using multiple inner joins with the same table where an input parameter value is checked within each inner join. I want to eliminate particular inner join if the input parameter is null
You would need to use dynamic SQL to construct the appropriate query for the parameters like this:
PROCEDURE myproc (p1 VARCHAR2) IS
l_sql LONG;
l_cursor SYS_REFCURSOR;
BEGIN
l_sql := 'SELECT a, b, c FROM table1';
IF p1 IS NOT NULL THEN
l_sql := l_sql || ' JOIN table2 ON table2.x = table1.x';
END IF;
l_sql := l_sql || ' WHERE table1.y = :bind1';
OPEN l_cursor FOR l_sql USING 123;
...
END;

Resources