in oracle we have
decalre
v_data number ;
begin
select max(deptno) into v_data from dept;
end;
do we have this type of advatntage of in terdata like selecting the data from table into a variable
can u give the equivalent code in terdata
Thanks
In teradata you can use variables only in stored procedure, you cannot use the variables in Teradata SQl statements which are outside of the stored procedure.
You can load the max value into a temporary table and can access it for your manipulations
Related
I wanted to 'Call' MariaDB Procedure from Azure Data Factory.
How can this be achieved, are there any other service which can be integrated with ADF to call this MariaDB procedures
I tried calling the procedure by writing the query using lookup activity.
It fails while showing this error.
ErrorCode=InvalidParameter,'Type=Microsoft.DataTransfer.Common.Shared.HybridDeliveryException,Message=The value of the property 'columns' is invalid: 'Value cannot be null.
Parameter name: columns'.,Source=,''Type=System.ArgumentNullException,Message=Value cannot be null.
Parameter name: columns,Source=Microsoft.DataTransfer.Common,'
Lookup activity reads and returns the content of the query. I tried to repro this by creating three stored procedures in Azure SQL database for Maria DB.
First Stored procedure is written to update the data in the table.
DELIMITER $$
CREATE PROCEDURE update_inventory()
BEGIN
UPDATE inventory SET quantity = 150
WHERE id = 1;
END$$
DELIMITER ;
When this procedure is called in ADF lookup activity, error occurs.
Second stored procedure is written with select query.
DELIMITER $$
CREATE PROCEDURE select_inventory()
BEGIN
select * from inventory;
END$$
DELIMITER ;
When this SP is called, ADF pipeline is executed successfully.
In order to execute the stored procedure with update statements (or any statements), a select statement is added in the Stored procedure.
DELIMITER $$
CREATE PROCEDURE update_select_inventory()
BEGIN
UPDATE inventory SET quantity = 150
WHERE id = 1;
select * from inventory;
END$$
DELIMITER ;
When this stored procedure is called through Lookup activity, it got executed successfully.
Try adding select statement in the stored procedure and execute it in Lookup activity. Or add Select statement after Call stored procedure statement.
By selecting the 'query' option, you can call the stored procedure using lookup activity. From your error message, it looks like you are missing the parameter columns while calling the stored procedure.
Did you try executing the same code using the client tools like MySQL workbench? If you can execute the stored proc from other client tools, then you should be able to execute the same using the lookup activity.
I tested from my end and was able to execute the Stored procedure using lookup activity. Please see the below screenshot for your reference.
Below is my code
CREATE OR REPLACE PROCEDURE ds_grp_heatmap_product_test ()
SPECIFIC ds_grp_heatmap_product_test
LANGUAGE SQL
MODIFIES SQL DATA
DYNAMIC RESULT SETS 1
BEGIN
DECLARE c_hm_report(v_sal INTEGER)
CURSOR WITH RETURN FOR
select *
from emp where salary<v_sal;
open c_hm_report(2000);
END;
This code is giving compilation error any idea what i am doing wrong.
Your code is SQLPL (as distinct from PLSQL). Depending on your Db2 server version and configuration you can also write PLSQL (Oracle compatibility mode of Db2). You are getting compilation errors because the above syntax is not valid for SQLPL.
The code below might be what you seek: the parameter in this case is supplied as an input to the stored procedure, adjust the type as necessary, or you can set the variable v_sal via other means:
--#SET TERMINATOR #
CREATE OR REPLACE PROCEDURE ds_grp_heatmap_product_test (in v_sal integer)
SPECIFIC ds_grp_heatmap_product_test
LANGUAGE SQL
MODIFIES SQL DATA
DYNAMIC RESULT SETS 1
BEGIN
DECLARE c1 CURSOR WITH RETURN FOR
select *
from emp where salary < v_sal;
open c1;
END
#
I have a number of long SQL select queries( 150 lines+) that I want to use in a PL/SQL package. The package has procedures to execute the SQL queries and insert the results into a separate table, compare the SQL results to another table, delete rows etc
Its fairly easy to store the SQL results with:
INSERT into TABLE1
SELECT .... (150 line ugly select query goes here)
Problem is, I want to store the select SQL in a cursor/function/view/whatever-works so I don't have to paste the 150 lines query into each procedure where the SQL is used.
I can store the SQL as a cursor then loop through the cursor within a package procedure, fetching each row and eg inserting into my table. But this seems very inefficient considering my only motivation for using a cursor is reducing the amount of lines my package.
Is there a better way to call the SQL select query in different procedures without copying & pasting all 150 lines? If this was a script, I would store the SQL in a text file then just read the text file into a variable and pass the variable to sqlplus when needed. But I'm not very familiar with PL/SQL.
Code:
CREATE OR REPLACE PACKAGE BODY MyPackage
as
Cursor my_cursor
select (150+ lines goes here)
PROCEDURE PopulateTable
is
TYPE fetch_array IS TABLE OF my_cursor%ROWTYPE;
s_array fetch_array;
BEGIN
open my_cursor;
LOOP
FETCH tran_cursor BULK COLLECT INTO s_array;
FORALL counter in 1..s_array.COUNT
INSERT INTO my_table VALUES s_array(counter);
EXIT when s_array%NOTFOUND;
END LOOP;
close my_cursor;
COMMIT;
END PopulateTable;
END MyPackage;
I am not sure if this would be the best way to do, but what came to my mind, is a variable cursor. You could do that using SYS_REFCURSOR. You can build a function that contains your query, and returns ref curosr. In all your procedures, you can just call that function. This will save you writing 150+ lines query in every procedure. More important, it will limit your program to one copy of the query, and therefore easy to maintain.
The function that returns the ref cursor, could be something like this:
CREATE OR REPLACE FUNCTION my_ugly_query()
RETURN SYS_REFCURSOR
AS
my_cursor_ref SYS_REFCURSOR;
BEGIN
OPEN my_cursor_ref FOR
SELECT -- 150+ lines of query;
RETURN my_cursor_ref;
END;
This is how to use it:
CREATE OR REPLACE PACKAGE BODY MyPackage
as
PROCEDURE PopulateTable
IS
l_cur_refcur SYS_REFCURSOR;
s_array fetch_array;
BEGIN
l_cur_refcur := my_ugly_query();
LOOP
FETCH tran_cursor BULK COLLECT INTO s_array;
EXIT when s_array%NOTFOUND;
FORALL counter in 1..s_array.COUNT
INSERT INTO my_table VALUES s_array(counter);
END LOOP;
CLOSE my_cursor;
COMMIT;
END PopulateTable;
END MyPackage;
Create your cursor in the package specification rather than the package body. You may then refer to it from any package procedure/function using package_name.cursor_name
I have a scenario where I have to perform dynamic assignment to PLSQL type variable.
For example, below is a simple assignment of value to type my_tab_type. fn_get_value(varchar2) function returns value based on string passed.
my_tab_type.table_name.LEAD := fn_get_value('LEAD_ID');
Like these there will be hundreds of assignments. I want to store the mapping (LEAD,LEAD_ID) in a table, fetch these mapped values in a cursor and dynamically create assignment statement.
I want to avoid execute immediate or dbms_sql.execute for each dynamic assignment created as performance will be affected. Please help me come up with an feasible and effective approach.
(You might have a XY-problem.)
You don't tell us the types in your question so I assume nested table of records.
You can't assign a PL/SQL record "dynamically" without using dynamic PL/SQL (i.e. running PL/SQL with execute immediate). This also means that all uses of such "dynamically" created record have to take place dynamically. That's not the way PL/SQL is supposed to be used.
However if you can change your data type to associative array you can archive your goal with a plain boring static well-mannered PL/SQL !
Below you'll find an example that should get you started.
Example
create table so60 (
from_ varchar2(20)
,to_ varchar2(20)
);
insert into so60 values('A_FROM', 'A_TO');
insert into so60 values('B_FROM', 'B_TO');
insert into so60 values('C_FROM', 'C_TO');
declare
-- foo_t is an associative array
type foo_t is table of varchar2(32767) index by varchar2(32767);
v_foo foo_t;
function f(p_x in varchar2) return varchar2 is
begin
return lower(p_x);
end;
begin
-- initialize from table
for i in (select * from so60)
loop
v_foo(i.to_) := f(i.from_);
end loop;
dbms_output.put_line(v_foo('B_TO'));
end;
/
Example run
SQL> #so60
b_from
PL/SQL procedure successfully completed.
SQL>
Please help me in resolving below issue i am facing, i have to insert data into a table(table name genereted using variable value and table is created already) within FORALL..
Declare
TYPE dept_data_rec IS RECORD
(
Dept_no number,
Dept_name varchar2(100),
Dept_loc Varchar2(20)
);
TYPE nt_dept_data IS TABLE OF dept_data_rec ;
l_dept_data_nt nt_dept_data;
BEGIN
FORALL j IN 1..l_dept_data_nt.COUNT SAVE EXCEPTIONS
EXECUTE IMMEDIATE 'INSERT INTO '||l_get_dept_rec.dept_seq_no||'_Dept_Data VALUES '||
l_dept_data_nt(j);
COMMIT;
while compiling this code i am getting below error:
PLS-00306: wrong number or types of arguments in call to '||'
However when code using actual table name it works
FORALL j IN 1..l_dept_data_nt.COUNT SAVE EXCEPTIONS
INSERT INTO A1_dept_data VALUES
l_dept_data_nt(j);
COMMIT;
Oracle 10g -
In versions of Oracle prior to 11g, you can't use FORALL with EXECUTE IMMEDIATE, only with INSERT, UPDATE, or DELETE.
See http://docs.oracle.com/cd/B13789_01/appdev.101/b10807/13_elems021.htm
It's a special syntax
that reads like a FOR loop but isn't, and
is used by PL/SQL to perform bulked DML operations and only with the exact keyword, not with dynamic SQL or any other code.
Oracle 11g +
In 11g, the restriction on using EXECUTE IMMEDIATE was lifted. See http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/forall_statement.htm
However, the only variables allowed in the string are subscripted elements from a single array in the USING clause.
The documentation is unclear whether you can dynamically "change" the table per row using the FORALL syntax. Remember that the FORALL is used by PL/SQL to perform a bulk DML operation and that needs to go to one table for this to yield any performance benefit.
Best performance solution for the above problem
You should make two levels of arrays, the first defines which table and the second defines the data for that table.
Use an ordinary FOR loop over the table array and inside that loop use the special FORALL syntax to perform all the DML for the one table.