Teradata For Loop without Cursor - teradata

How to define FOR LOOP without Cursor in Teradata?
Actually I'm having code like this:
CREATE PROCEDURE TEST1()
BEGIN
DECLARE VAR1 VARCAHR(200);
DECLARE VAR2 VARCAHR(200);
FOR FOR_LOOP1 AS CUR_NAME CURSOR FOR
DO
---------SQL STATEMENT-------
FOR FOR_LOOP2 AS CUR_NAME1 CURSOR FOR
DO
---------SQL STATEMENT-------
END FOR;
END FOR;
END;
I need to execute NESTED CURSOR or FOR LOOP in Teradata, by taking the output of first cursor value, I need do execute the second cursor.
Can any one guide me, please!

Looks like you worked on Oracle before :-)
Although this is possible in Teradata using exactly the syntax you provided it's not recommended as cursors are sequential by nature while Teradata is a parallel DBMS. Cursors are already evil, but nested cursors are even worse.
Most cursors processing data can be rewritten, e.g. using Windowed Aggregate Functions (best case), have a look at George Coleman's blog
Can you provide the actual code?

Related

How to add a date with an INSERT INTO SELECT in PL SQL?

For my homework I need to make a package that contains a procedure that removes all records from the table dwdimartist and then fills the table with all records from the table artist and add a field with the date of today.
This is what I've created, it works but I don't know if it's performant enough. Is it better to use a cursor that loops over each record in the table artist?
CREATE OR REPLACE PACKAGE BODY dwh AS
PROCEDURE filldwh IS
today_date DATE := SYSDATE;
BEGIN
DELETE FROM dwdimartist;
INSERT INTO dwdimartist (artistkey, name) (SELECT artistid, name FROM artist);
UPDATE dwdimartist SET added = today_date;
END filldwh;
END dwh;
Simple SQL query like you did is better choice than a cursor or implicit loop.
possible improvement:
You should do it at once without update: set the date during insert.
INSERT INTO dwdimartist (artistkey, name, added)
(SELECT artistid, name, sysdate FROM artist);
Hope it helps
You don’t need to use cursors. You can hardly beat Insert ... select since it’s SQL itself and in most cases it works better than any programmatic structure due to native dbms optimization. However, you can do better if you decrease number of I/O operations. You don’t need update here. Simply add sysdate to your select and insert everything together.
insert into dwdimartist(artistkey, name, added) select artistid, name, sysdate from artist;
Another thing to improve is your ‘delete’. While it’s small table for learning purposes you won’t feel any difference between delete and truncate but for real ETL tasks and big tables you’ll see it definitely. Yes you cannot use truncate directly in your PL/SQL but there are 3 ways to do it:
execute immediate ‘truncate dwdimartist’;
Dbms_utility.exec_ddl_statement(‘truncate ...;’);
DBMS_SQL package
However, remember that calling truncate will execute commit like any ddl command. So delete may be the only option sometimes. But even if it is, you should avoid it for the whole table.

PLSQL: No output displayed when using dynamic query inside Stored Procedure

I have been asked to create an SP which creates temporary table and insert some records.
I am preparing some sample code for the same as mentioned below but the output is not displayed.
create or replace procedure Test
is
stmt varchar2(1000);
stmt2 varchar2(1000);
begin
stmt := 'create global temporary table temp_1(id number(10))';
execute immediate stmt;
insert into temp_1(id) values (10);
execute immediate 'Select * from temp_1';
execute immediate 'Drop table temp_1';
commit;
end;
When i am executing the SP by (Exec Test) desired O/P is not displayed.
I am expecting O/P of "Select * from temp_1" to be displayed. But it is not happening. Please suggest where i am doing wrong.
But i am interesting in knowing why ( execute immediate 'Select * from temp_1';) do not yield any result
For two reasons. Firstly because as #a_horse_with_no_name said PL/SQL won't display the result of a query. But more importantly here, perhaps, the query is never actually executed. This behaviour is stated in the documentation:
If dynamic_sql_statement is a SELECT statement, and you omit both into_clause and bulk_collect_into_clause, then *execute_immediate_statement( never executes.
You would have to execute immediate into a variable, or more likely a collection if your real scenario has more than one row, and then process that data - iterating over the collection in the bulk case.
There is not really a reliable way to display anything from PL/SQL; you can use dbms_output but that's more suited for debugging than real output, and you usually have no guarantee that the client will be configured to show whatever you put into its buffer.
This is all rather academic since creating and dropping a GTT on the fly is not a good idea and there are better ways to accomplish whatever it is you're trying to do.
The block you showed shouldn't actually run at all; as you're creating temp_1 dynamically, the static SQL insert into temp_1 will error as that table does not yet exist when the block is compiled. The insert would have to be dynamic too. Any dynamic SQL is a bit of a warning sign you're maybe doing something wrong, though it is sometimes necessary; having to do everything dynamically suggests the whole approach needs a rethink, as does creating objects at runtime.

difference between cursor and select in a loop

I have been having this question for while now
we can Implement a cursor for Example
SET serveroutput ON;
DECLARE
CURSOR test_cursor
IS
SELECT * FROM employees;
BEGIN
FOR i IN test_cursor
LOOP
DBMS_OUTPUT.PUT_LINE(i.employee_id||' '||i.First_name);
END LOOP;
END;
Also we can implement the same in below way
SET serveroutput ON;
BEGIN
FOR rec IN
(SELECT * FROM employees
)
LOOP
DBMS_OUTPUT.PUT_LINE(rec.employee_id ||' ' ||rec.First_name);
END LOOP;
END;
Why do we need a cursor here then? Please could you let me know the differences and its advantages/disadvantages?
In both cases, you actually use cursors.
The first one is declared and named (explicit).
The second one is anonymous (implicit).
http://docs.oracle.com/cd/B10501_01/appdev.920/a96624/01_oview.htm#740.
I usually use explicit cursors for better code readability and in cases, when I want to reuse the cursor, I can fetch the data from result cache or fetch the data into variable and iterate through an array.
Also, as far as I know, execution plan is not generated as often as while using the implicit cursor (the DB searches for the query in SGA by query's hash and can find already stored execution plan, thus skips the execution plan generation).
https://docs.oracle.com/database/121/TGSQL/tgsql_sqlproc.htm#TGSQL175
So firstly, these are both known as cursor FOR LOOPs.
http://docs.oracle.com/database/121/LNPLS/cursor_for_loop_statement.htm#LNPLS1143
One usability difference between the two forms is that the second form places the SQL that is executing directly before the code in which the result set is used. This can make it easier to understand the code.
One useful syntax difference is that in the first form you can pass parameters into the cursor to modify its behaviour (see above link for syntax). So if you use the same basic cursor definition multiple times, but with different parameters to pass in, then use the former.

SQLite Function that performs additional queries

I have written a custom SQLite function that transforms a string as it is copied from one table to another. It's very basic and has does its job well for quite a while. The query looks like this:
INSERT INTO Table2 (field1) SELECT MYTRANSFORM(field2) FROM Table2;
Now I need to modify the behavior of that function so that it does a lookup on another table and factors the result into how it transforms the value. Is that possible? Has anyone done it successfully?
This is possible; you can execute other SQL queries from within your function, as long as you do not call your function recursively.

Use cursor in a select statement

Hope you can help me, Im trying to use a cursor in a sql query. I'm 99% sure this can be done, so please any suggestions? this is my code
FUNCTION filter (c_cur_trip_menu IN c_menu_tripulantes)
RETURN c_menu_tripulantes IS
BEGIN
SELECT *
FROM c_cur_trip_menu , opciones_migradas
WHERE mnu.mnu_idemnu = id_opcion;
RETURN c_cur_trip_menu;
END filter;
What I want is to use the cursor as a table.
thanks in advance.
You can copy data from cursor to temporary table, but you cant use a cursor like a table. If the function you want to build in oracle you can't use select syntax to display data:
FOR cur in c_cur_trip_menu
LOOP
dbms_output.put_line(cur.col1||' 'cur.col2);
END LOOP;
You can't select from cursor (but you could create cursor from any select statement (using cursor(your query))) but table or pipelined functions could help you with your task. http://www.oracle-base.com/articles/misc/pipelined-table-functions.php helps you. Nevertheless I've never understood trying to move function approach for retrieving data in sql based DB - views solve it perfect. Functions are weak to be estimated by CBO so you create the place to make your queries work slower in advance. What for - no idea....

Resources