HSQL DB Declaring variables using created types - hsqldb

I am converting PL/SQL stored procedures into HSQLDB procedures. I am trying to declare variables inside my procedure that references that I have created. When I use this type for a parameter to the procedure, it works fine. But when I try to use it as a local variable type, it does not know how to use it.
Example:
CREATE TYPE MY_DECLARED_TYPE AS INTEGER;
CREATE PROCEDURE TEST (IN TEMP MY_DECLARED_TYPE) MODIFIES SQL DATA DYNAMIC RESULT SET 1
BEGIN ATOMIC
DECLARE l_var_1 MY_DECLARED_TYPE;
BEGIN ATOMIC
--Do some stuff--
END;
Is there some clause in HSQLDB that does not allow for the use of declared types in a declare statement? Or is there something else that I am missing?

This works in the latest HSQLDB version (2.3.4).
CREATE PROCEDURE TEST (IN TEMP MY_DECLARED_TYPE) MODIFIES SQL DATA DYNAMIC RESULT SETS 1
BEGIN ATOMIC
DECLARE IVAR MY_DECLARED_TYPE;
BEGIN ATOMIC
SET IVAR = 0;
END;
END;

Related

Is there a way to declare an array variable which accepts a cursor ROWTYPE as its datatype in Postgres?

I am facing a problem in PL/pgSQL while trying to convert some procedures from Oracle to Postgres RDBMS. At the original procedure in PL/SQL, one of these procedures has declared within the DECLARE clause: a bounded cursor, a TYPE which is a TABLE OF ROWTYPE of that bounded cursor and a variable which takes the datatype of this predefined TYPE.
In a few words (as far as I've understood), a bounded cursor and an ARRAY of its type - meaning that each position of that array is actually a ROWTYPE of that cursor - are declared. I have tried to research ways to get around this in Postgres but no success, yet.
This isn't the original I am trying to migrate from Oracle to Postgres, but I think it clarifies what I am trying to reach:
CREATE OR REPLACE PROCEDURE schema.procedure_name (arguments)
AS
$BODY$
DECLARE
CUR_FILMS2 CURSOR (year INTEGER) for
SELECT *
FROM film
WHERE release_year = year;
TYPE TYPE_EXAMPLE IS TABLE OF CUR_FILMS2%ROWTYPE;
V_TYPE_EXAMPLE TYPE_EXAMPLE;
...
BEGIN
OPEN CUR_FILMS2(2022);
FETCH CUR_FILMS2 BULK COLLECT INTO V_TYPE_EXAMPLE;
CLOSE CUR_FILMS2;
...
-- Later on, that variable is iterated to execute some code beneath.
FOR I IN 1 .. V_TYPE_EXAMPLE.COUNT LOOP
...
END LOOP;
END;
$BODY$
I have already thought about the RECORD datatype using, but it only accepts one record per time, and as far as I know there isn't a sort of TABLE variable in Postgres. The Postgres version I am using is PostgreSQL 14.3.
What is the easiest way to get around this problem? Is there a way?
Postgres does not have table variables - and no BULK COLLECT for cursors in PL/pgSQL. You might work with temporary tables.
Seems like you can replace all the overhead with a plain FOR loop (and its implicit cursor) using a generic record variable for the row type:
CREATE OR REPLACE PROCEDURE schema.procedure_name (_year int) AS
$func$
DECLARE
_rec record;
BEGIN
FOR _rec IN
SELECT *
FROM film
WHERE release_year = _year
LOOP
...
END LOOP;
END
$func$;
See:
Cursor based records in PostgreSQL
Loop on tables with PL/pgSQL in Postgres 9.0+

Oracle: Setting Session Parameters in Packages and Procedures

I'm a SQL Server DBA currently getting up to speed on Oracle. I'm trying to create something very similar to sp_WhoIsActive for SQL Server but for Oracle without reinventing the wheel. Essentially all I'm doing is selecting some values from v$session and inserting them into a table (poor man's ASH/AWR).
It would seem that in Oracle 12.1, there's a bug when querying dictionary views where it can take forever due to bad parsing logic (Bug 22225899 : SLOW PARSE FOR COMPLEX QUERY). The work-around is to set a session parameter:
alter session set "_optimizer_squ_bottomup"=false;
In T-SQL, I could very easily execute a stored procedure in-session and set this variable at runtime. However in Oracle, it wouldn't seem thats the case.
Sample Code:
CREATE OR REPLACE PROCEDURE SP_DB_ACTIVITY
(
v_temp NUMBER :=1
) IS
BEGIN
alter session set "_optimizer_squ_bottomup"=false;
INSERT INTO SY_DB_ACTIVITY
SELECT
<fields>
FROM
v$session;
commit;
When I run this, I get the error:
"PLS-00103: Encountered symbol 'ALTER' when expecting one of the following..."
Right now, the only way I know how to do this is via a utility like SQL Plus that initiates an interactive user session. Can anyone give me some direction as to how Oracle handles this situation? I'd like to bundle this up into a SP or a Package and then call it from Oracle Scheduler.
Hre is a simple example how to execute alter session inside of the procedure:
CREATE PROCEDURE SP_DB_ACTIVITY IS
BEGIN
EXECUTE IMMEDIATE 'alter session set "_optimizer_squ_bottomup"=false';
END;
/
Here is the way you can combine that with your select and insert statement:
CREATE OR REPLACE PROCEDURE SP_DB_ACTIVITY
(v_temp IN number) AS
v_Id NUMBER;
BEGIN
EXECUTE IMMEDIATE 'alter session set "_optimizer_squ_bottomup"=false';
SELECT 1
INTO v_Id
FROM dual;
INSERT INTO SY_DB_ACTIVITY (id) VALUES(v_Id);
END SP_DB_ACTIVITY;
/
Here is a small DEMO where you can see what will procedure do when you call it and how you can call it. Also, in this example you are calling procedure with and IN parameter. So you can use that parameter for something and in the example above is the procedure without any parameters...
You can also, of course, insert into table directly:
CREATE OR REPLACE PROCEDURE SP_DB_ACTIVITY
(v_temp IN number) AS
v_Id NUMBER;
BEGIN
EXECUTE IMMEDIATE 'alter session set "_optimizer_squ_bottomup"=false';
INSERT INTO SY_DB_ACTIVITY(id)
select 1
from dual;
END SP_DB_ACTIVITY;
/

Can I Create a variable that is useful in SQL Statement and PL SQL Script as well?

I have defined a variable in sql script as below:
DEFINE USER_NAME="TEST_DB";
DEFINE PASSWORD="abc";
Now in my script I have few sql statement where I can use above variable with &USER_NAME and it's serve my purpose.
Now I have PL SQL block also:
DECLARE
BEGIN
CONST_MASTER_USER varchar2(100) := 'TEST_DB';
-- FEW CODE
END
Now I want to use USER_NAME variable in this PL/SQL Block, but when I replace 'TEST_DB' with &USER_NAME, SQL Developer gives me following error:
PLS-00201: identifier 'TEST_DB' must be declared
As I am not expert in SQL, do we have any solution where we can define a variable once and use it in SQL as well as PLSQL statements?
It sounds like you removed the quotes, which are still needed with substitution variables:
DECLARE
CONST_MASTER_USER varchar2(100) := '&USER_NAME.';
BEGIN
-- FEW CODE
END

How to call stored procedure inside another stored procedure and set the values as in variable in DB2

I need to call stored procedure into another stored procedure and return value stored in variable in db2.
Thanks
One examples could be this one:
DECLARE STMT STATEMENT;
PREPARE STMT FROM 'CALL MODIFY_DESCENDANTS (?, ?)';
EXECUTE STMT USING LOG_ID, LEVEL;
Taken from log4db2 - https://github.com/angoca/log4db2/blob/master/src/main/sql-pl/03-UtilityBody.sql#L729
If the stored procedure returns a result set, and you want to take values from that, then you need to call the stored procedure and use the associate and allocate statements. For an example, you can visit https://www.toadworld.com/platforms/ibmdb2/w/wiki/7460.call-allocate-and-associate
CALL EMPR;
ASSOCIATE RESULT SET LOCATOR (LOC1) WITH PROCEDURE EMPR;
ALLOCATE C1 CURSOR FOR RESULT SET LOC1;

Oracle Sql : Procedure which can create temporary tables inside it

I am new to Oracle Sql and facing an issue :
I want to create a temporary table inside procedure .
LIKE:
CREATE PROCEDURE P
AS
BEGIN
CREATE TEMPORARY TABLE A(ID int);
END P;
BUT THIS IS GIVING ME AN ERROR
How Can I Create a temporary table inside procedure.
I have seen other answers on stackoverflow but that doesn't answer my question properly
Can you please help me out ?
Why do you want to create a temporary table in a stored procedure in the first place?
It is relatively common to create temporary tables in other databases (SQL Server and MySQL, for example). It is very, very rare to do the same thing in Oracle. In almost every case where you are tempted to create a temporary table in Oracle, there is a better architectural approach. There is a thread over on the DBA stack that discusses alternatives to temporary tables and why they are not commonly needed in Oracle.
Programmatically, you can create objects using dynamic SQL
CREATE OR REPLACE PROCEDURE dont_do_this
AS
BEGIN
EXECUTE IMMEDIATE 'CREATE GLOBAL TEMPORARY TABLE a( id INTEGER )';
END;
If you create a temporary table dynamically, however, every reference to that table will also need to be via dynamic SQL-- you won't be able to write simple SELECT statements against the table. And the definition of a temporary table in Oracle is global so it is visible to every session. If you have two different sessions both trying to create the same table, the second session will get an error. If you expect the table to have a different definition in different sessions, you've got even more problems.
You could use Dynamic SQL with EXECUTE IMMEDIATE:
CREATE OR REPLACE
PROCEDURE p
AS
BEGIN
EXECUTE IMMEDIATE 'CREATE TEMPORARY TABLE A(id NUMBER)...etc';
END p;
Edit: Obviously you'll have to ensure your syntax is correct within the EXECUTE IMMEDIATE statement.
Hope it helps.
You must declare your procedure as:
create or replace PROCEDURE MYPROCEDURE AUTHID CURRENT_USER IS
script varchar(4000);
BEGIN
script:= 'CREATE GLOBAL TEMPORARY TABLE BNMCODIAGNOSTICASSOCIE_TEMP
ON COMMIT PRESERVE ROWS
as select ........';
EXECUTE IMMEDIATE script;
commit;
END;