I have a compile error that unable to declare variables in procedure PL/SQL which trying solutions from other sources. Can anybody help to check what is the problem?
CREATE OR REPLACE PROCEDURE add_vaccine
(p_id IN VARCHAR, d_id IN VARCHAR, p_vdate IN DATE, p_vaccinated IN VARCHAR)
AS
BEGIN
DECLARE counter NUMBER(MAX);
--Prompt user to input vaccination and visit detail
DBMS_OUTPUT.PUT_LINE('Patient ID = ' || p_id);
DBMS_OUTPUT.PUT_LINE('Doctor ID = ' || d_id);
DBMS_OUTPUT.PUT_LINE('Date = ' || p_vdate);
DBMS_OUTPUT.PUT_LINE('Vaccinated = ' || p_vaccinated);
END;
/
The code is unfinished but I'm stuck at the variable declaration.
Whenever you have a DECLARE section, you must have a BEGIN and END with some code.
If you don't need to declare inside, you can always declare them after AS.
CREATE OR REPLACE PROCEDURE STH()
AS
<DECLARE VARIABLES HERE>
BEGIN
DECLARE
<YOU CAN DECLARE HERE AS WELL>
BEGIN
DBMS_OUTPUT.PUT_LINE('HELLO');
END;
-- Do something here
END;
There is an implict DECLARE before the first BEGIN in your procedure hence
SQL> CREATE OR REPLACE PROCEDURE add_vaccine
2 (p_id IN VARCHAR, d_id IN VARCHAR, p_vdate IN DATE, p_vaccinated IN VARCHAR)
3 AS
4
5 counter NUMBER;
6 BEGIN
7 --Prompt user to input vaccination and visit detail
8 DBMS_OUTPUT.PUT_LINE('Patient ID = ' || p_id);
9 DBMS_OUTPUT.PUT_LINE('Doctor ID = ' || d_id);
10 DBMS_OUTPUT.PUT_LINE('Date = ' || p_vdate);
11 DBMS_OUTPUT.PUT_LINE('Vaccinated = ' || p_vaccinated);
12 END;
13 /
Procedure created.
Related
I am trying to call a procedure inside a procedure but this gives me an error like:
Uncaught exception of type 'STATEMENT_ERROR' on line 19 at position 2 : This session warehouse WH_STD_EDWQA_ANALYST no longer exists.
My parent procedure construct is like creating a warehouse & the child procedure is to populate a metadata table(custom) by use of table(result_scan(last_query_id())).
Parent procedure construct:
create or replace procedure wh_resource_govern(type varchar, env varchar, ..., varchar)
returns varchar not null
language sql
as
$$
declare
wh_name varchar;
wh_setup varchar;
lv_acct_name varchar;
begin
wh_name := 'WH_' || type || '_' || env || '_' || team;
wh_setup := 'CREATE OR REPLACE WAREHOUSE' || ' ' || wh_name || ' ' || 'WITH' || ' '
|| 'WAREHOUSE_SIZE = ' || v_wh_size || ' '
...,
|| 'COMMENT= '|| '"' || v_created_by || '"' ;
execute immediate wh_setup;
commit;
call load_all_warehouse_metadata('a', 'b', 'c'); ----> This is where it is getting stuck.
end;
$$
;
Child procedure construct is given as below:
create or replace procedure load_all_warehouse_metadata(wh_type varchar, wh_env varchar, wh_team varchar)
returns varchar not null
language sql
as
$$
declare
lv_acct_name varchar;
begin
select current_account() into lv_acct_name;
show warehouses;
insert into ALL_WAREHOUSE_METADATA (account_name, warehouse_type, .., .., )
select :lv_acct_name, :wh_type, :wh_env, :wh_team, "name", ..., ...,
from table(result_scan(last_query_id()));
end;
$$
;
Any inputs on how to address this would be really helpful.
Creating a warehouse immediately makes it the current warehouse for the session, example:
create or replace warehouse FOO;
select current_warehouse(); -- FOO
drop warehouse FOO();
select current_warehouse(); -- NULL
When you run execute immediate wh_setup; in the first SP, it's setting the session's warehouse to the one you just created. Calling a child SP using owner's rights (default) from a warehouse that isn't the one that started the SP is causing context problems for the warehouse.
You can reproduce this error as follows:
create or replace procedure SP1()
returns varchar not null
language sql
--execute as caller
as
$$
declare
currentWarehouse varchar;
begin
select current_warehouse() into currentWarehouse;
create or replace warehouse FOO;
call SP2();
return currentWarehouse;
end;
$$;
create or replace procedure SP2()
returns varchar not null
language sql
--execute as caller
as
$$
declare
currentWarehouse varchar;
begin
select current_warehouse() into currentWarehouse;
create or replace temp table FOO(s string);
insert into FOO(S) values ('Bar');
return 'Done';
end;
$$;
call SP1();
You can fix this code sample immediately by uncommenting the two commented-out ownership options for SP1 and SP2:
--execute as caller (Remove the comment markers and recreate both SPs.)
You can also run a SQL command to use warehouse <wh_name> in your SP(s), but you must run the SP as caller in order to change warehouse context this way.
First of all my question will be, if there is a way of auto-generation partitions (like interval in Oracle for range partitioning) while inserting data into the partitioned table in DB2?
At the moment I have a schema with some hundreds of tables, which are not partitioned. And I suppose to partition them.
My steps will be:
rename all the tables to OLD_table_name
execute DDLs for those tables but already partitioned (by load_id column int data type)
execute for all, insert into table_name select * from OLD_table_name
...and here it starts.
(Of course the process must be automatically and I don't know which values contain load_id column + they will be all different for all the tables, otherwise it would be possible to generate simply alter statements and execute them).
Therefore I would go for cursor.
For the moment I have solution which is working but I don't like it:
BEGIN
FOR CL AS MYCURS INSENSITIVE CURSOR FOR
select distinct 'alter table '||tb_nm||'
add partition PART_'||lpad(load_id,5,0)||'
starting from '||load_id||'
ending at '||load_id v_alt
from (
select load_id,'Table_01' tb_nm from Table_01
union
select load_id ,'Table_02'from Table_02
union
....
/*I have generated this union statements for whole set of tables*/)
do
execute immediate v_alt;
end for;
end
Also, I have tried some more elegant (on my opinion) variant, but didn't sucseed:
BEGIN
DECLARE v_stmnt VARCHAR(1000);
DECLARE v_check_val int;
DECLARE v_prep_stmnt STATEMENT;
for i as (select table_name
from sysibm.tables
where TABLE_SCHEMA ='shema_name'
)
do
SET v_stmnt = 'set ? = (SELECT distinct(load_id) FROM '||table_name||')';
PREPARE v_prep_stmnt FROM v_stmnt;
/*and here I stuck. I assume there must be possibility to run next execute as well in loop, but
all my attempts were not succsesfull*/
--EXECUTE v_prep_stmnt into v_check_val ;
end for;
END
Would highly appreciate any hint.
Try something like this:
--#SET TERMINATOR #
SET SERVEROUTPUT ON#
BEGIN
DECLARE L_TABSCHEMA VARCHAR(128) DEFAULT 'SCHEMA_NAME';
DECLARE L_COLNAME VARCHAR(128) DEFAULT 'LOAD_ID';
DECLARE L_VALUE INT;
DECLARE L_STMT VARCHAR(1024);
DECLARE SQLSTATE CHAR(5);
DECLARE C1 CURSOR FOR S1;
FOR I AS
SELECT TABNAME
FROM SYSCAT.COLUMNS
WHERE TABSCHEMA = L_TABSCHEMA AND COLNAME = L_COLNAME
DO
PREPARE S1 FROM 'SELECT DISTINCT(' || L_COLNAME || ') FROM ' || L_TABSCHEMA || '."' || I.TABNAME ||'"';
OPEN C1;
L1: LOOP
FETCH C1 INTO L_VALUE;
IF SQLSTATE<>'00000' THEN LEAVE L1; END IF;
SET L_STMT =
'alter table ' || L_TABSCHEMA || '."' || I.TABNAME || '" '
||'add partition PART_' || lpad(L_VALUE, 5, 0) || ' starting from ' || L_VALUE || ' ending at ' || L_VALUE;
--CALL DBMS_OUTPUT.PUT_LINE(L_STMT);
EXECUTE IMMEDIATE L_STMT;
END LOOP;
CLOSE C1;
END FOR;
END
#
I have a table name resultado, that is created by calling and executing another stored procedures or functions. As a result a have a column that contains '1' and '0' as a vector like this '111100001'. Also I have a store procedured that count the numbers of 1 in the 'vector' as it follows.
ALTER PROC [dbo].[CharCount](#String VARCHAR(4000),#caracter VARCHAR(2))
AS
BEGIN
DECLARE #long INT
DECLARE #numeroveces INT =0
DECLARE #consecutivo INT =0
DECLARE #consecutivo1 INT =0
SET #numeroveces=0
SET #long=LEN(#String)
WHILE #long>=0
BEGIN
IF #caracter=SUBSTRING(#String,#long,1)
BEGIN
set #numeroveces = #numeroveces + 1
set #consecutivo = #consecutivo + 1
END
IF #caracter<>SUBSTRING(#String,#long,1) or (#long = 0)
BEGIN
IF #consecutivo > #consecutivo1
BEGIN
set #consecutivo1 = #consecutivo
END
set #consecutivo = 0
END
SET #long=#long-1
END
SELECT #numeroveces
SELECT #consecutivo1
END
What I need is to execute the store procedure over a column from my table resultado and update the column with the result of the SP.
OriginalColumn--->SPResult---->UpdatedColumn
110111 ---> 5 ----> 5
Your procedure has 2 result sets the way you have it coded. Since in the example you posted here you are only trying to get the count of a given character I would strongly advise you to not use this procedure. It is horribly inefficient for such a simple task. This simple code will get the number of occurrences of a character without doing any looping. If you also need the longest consecutive count of occurrences there are better ways to do that too.
declare #String varchar(4000) = '111100001'
, #caracter VARCHAR(2) = '1'
select LEN(#String) - LEN(Replace(#String, #caracter, ''))
In the stored procedure below, I simply want to create a column alias based on a parameter value. It looks simple, but I could not find my answer.
CREATE OR REPLACE PROCEDURE "SP"(INTEGER, INTEGER)
RETURNS INTEGER
EXECUTE AS OWNER
LANGUAGE NZPLSQL AS
BEGIN_PROC
DECLARE
whichyear ALIAS FOR $1;
BEGIN
Select x as "Some Text" + whichyear from some table...
;
END;
END_PROC;
Tab is right that this would require dynamic SQL in Netezza. Here is an example.
CREATE OR REPLACE PROCEDURE "SP"(INTEGER)
RETURNS INTEGER
EXECUTE AS OWNER
LANGUAGE NZPLSQL AS
BEGIN_PROC
DECLARE
whichyear ALIAS FOR $1;
vSQL varchar(30000);
BEGIN
drop table the_results if exists;
vSQL := 'CREATE TABLE THE_RESULTS AS SELECT COL1 "SOME TEXT ' || whichyear || '" FROM TABLE_A;';
execute immediate vSQL;
END;
END_PROC;
Here's the output.
TESTDB.ADMIN(ADMIN)=> exec SP(5);
SP
----
(1 row)
TESTDB.ADMIN(ADMIN)=> select * from the_results;
SOME TEXT 5
-------------
2
3
1
(3 rows)
In SQL Server, you would use dynamic sql like this:
DECLARE #sql varchar(max) = 'Select x as SomeText' + #whichyear + ' from sometable';
EXEC(#sql);
DECLARE
#countFlag INT,
#maxNum INT = 5,
#addingName NVARCHAR(6)
SET #countFlag = 1
WHILE (#countFlag <= #maxNum)
BEGIN
SET #addingName = 'name' + CAST(#countFlag AS NVARCHAR(2))
ALTER TABLE TableName
ADD
#addingName NVARCHAR(30)
SET #countFlag = #countFlag + 1
END
========================================================
This is called at the beginning of a set of procedures. #maxNum is actually passed in based on a question to the operator and changes the 'shape' of an existing db to include more columns. I would like to have the resulting column names be something like "name1" "name2" etc. but I am getting an "Incorrect syntax near '#addingName'" after the ADD statement when I execute it. What am I doing wrong here?
You cannot do it in that way, you should compose the query dynamically and execute it with Exec:
DECLARE #sqlCommand varchar(200)
SET #sqlCommand = 'ALTER TABLE TableName ADD ' + #addingName + ' NVARCHAR(30) '
EXEC (#sqlCommand)