Save result of plsql script in Kettle variable - plsql

What I want to do is storing the result of a PLSQL Script in a variable of a Kettle Transformation.
The script is located in a table input step and basically creates a select statement for me and puts it in a varchar variable of that PLSQL Script.
DECLARE
Statement VARCHAR(2000);
BEGIN
-- Here happens some stuff
Statement := 'select * from Foo';
END;
I just can´t figure out how I can map the variable Statement to one that exists in the Kettle Transformation.
Any ideas?

After a couple days I was able to solve this.
What I haven´t realized when I wrote the question was that a mere PLSQL Script doesn´t return anything.
The solution is actually very simple:
Create a new Transformation in Spoon.
Create a PLSQL Function (which has a return value of course).
Inside the new Transformation create a step "Table Input" and there you can call the function like this:
select myFunction('$someParameter') AS Statement FROM dual
If you want to provide some parameters for the function like I did make sure to check "replace variables in script" in the Table Input Step.
Connect that Step with a "Set Variables" Step ("Copy Rows to Result" works as well) and in my case I added the field Statement to the step with a new Variable that is valid in the parent job.

Related

I am trying to save the result of show con_name to a variable in ORACLE PL/SQL SQLPLUS

I want to write something like this:
exec SHOW CON_NAME into :=connection_name
but this doesnt work.
I know I can do this but I want to know for future reference if there is any way to do this for show
EXEC SELECT SYS_CONTEXT('USERENV','CON_NAME') into :connection_name from DUAL;
exec is just a wrapper for an anonymous block, so
exec SHOW CON_NAME into :=connection_name
is the same as
begin SHOW CON_NAME into :=connection_name end
Even with other issues fixed, show is a SQL*Plus client command, and doesn't mean anything inside a SQL or PL/SQL context.
You could do:
exec :connection_name := SYS_CONTEXT('USERENV','CON_NAME');
to avoid the context switch of selecting from dual within the PL/SQL.
Looking at the statement log in SQL Developer, show con_name is doing something similar, with a checkone bind variable it uses internally; though it also puts it through a local PL/SQL variable and trims that to 30 chars.
You could also use column ... new_value ... and query from dual, without using PL/SQL, and then use a substitution variable to refer to the value later instead of a bind variable:
column con_name new_value connection_name
select SYS_CONTEXT('USERENV','CON_NAME') as con_name from dual;
-- then later...
select '&connection_name' from dual;
Not sure how useful that would be though. Depends what you want to use it for I suppose.

age control 2 for pl/sql

i am trying to find out at what age an employee started working.
if he started under 16 he should report this 'Error when entering the date of birth' mistake. so my trigger is created but my trigger is not working
I get ever this error: ORA-01422: Exact retrieval returns more than the requested number of lines
i can't find the problem
Here is the code:
SET SERVEROUTPUT ON
ACCEPT Birthday PROMPT ' Pleas give you Date of birth: '
CREATE OR REPLACE TRIGGER T_Controll
before INSERT ON meine_Firma -- Table
FOR EACH ROW
DECLARE
V_Berufstart meine_Firma.Hiredate%TYPE; --Job begin
V_Geburtsdatum DATE; -- Date of birth
V_Alter number:=0; -- AGE
SELECT HIREDATE INTO V_Berufstart FROM meine_Firma;
BEGIN
V_Geburtsdatum:=('&Birthday');
V_Alter:= Round(MONTHS_BETWEEN(V_Berufstart,V_Geburtsdatum)-2)/12;
IF 16 > V_Alter THEN
RAISE_APPLICATION_ERROR(-20201,'Error when entering the date of birth');
END IF;
END;
/
SET SERVEROUTPUT OFF
If he under 16 then he may not work
sorry my english is not good (=
You have a much bigger issue in this script than the error you are getting. Even after correcting as #ShaunPeterson suggested it will still fail
, it WILL NOT generate an error it will just not run as you expect. The issue is you failed to understand substitution variables - the use of &name (Specifically here &Birthday.) I'll actually use &Birthday in the following but the discussion applies to ANY/ALL substitution variables.
people fail to understand why they can't use the "&" substitution
variables in their PL/SQL procedures and functions to prompt for input
at run time. This article will hopefully help clarify in your mind
what the differences are so that you can understand where and when to
use these.
Substitution Variables The clue here is in the name... "substitution". It relates to values being substituted into the code
before it is submitted to the database. These substitutions are
carried out by the interface being used
The effect of this substitution is the the line containing the substitution variable is physically rewritten by the interface replacing %Birthday. In this case if you don't enter a value or the date 2000-05-19 the statement before and after substitution is
BEFORE: V_Geburtsdatum:=('&Birthday');
AFTER: V_Geburtsdatum:=(''); OR V_Geburtsdatum:=('2000-05-19');
Either way the after is what the compiler sees; it does NOT see %Birthday at all. Moreover when run the trigger will not prompt for a value. As far as the compiler is concerned it is a hard coded value that will never change. Beyond that a trigger, or any other PLSQL script (stored or anonymous) never prompts for values, they are actually incapable of doing so as it is not part of the language. Any prompt is via your interface software not plsql.
I'm going to suggest a way to avoid the trigger altogether. Getting on soap box: Triggers are BAD, they have some usefulness for assigning auto incrementing keys (before 12c),logging, very limited auditing, etc. However, for business rules they should be the option of last resort. Ok Get off soap box.
The first thing is to make the columns meine_Firma.Hiredate and meine_Firma.Geburtsdatum NOT null (if not already). If either are NULL you cannot calculate anything with them, the result would be NULL.
Second create a new column age_at_hire (or whatever) as a virtual column then put a check constraint on it. And voila trigger no longer needed. See fiddle for demo.
So the proposed change (YES you will probably have to clean up the bad data first):
alter table meine_Firma modify
( hiredate not null
, Geburtsdatum not null
) ;
alter table meine_Firma add
( age_at_hire integer generated always as (trunc(months_between(hiredate,Geburtsdatum))) virtual
, constraint check_age_at_hire check (age_at_hire >= 16*12)
);
Anyway, I hope you get an understanding of substitution variables for the future. And learn to avoid triggers. Good luck.
The reason you are getting that specific error is that the below select will select ALL rows from meine_Firma as there is no where clause
SELECT HIREDATE INTO V_Berufstart FROM meine_Firma;
However because you are in a trigger you do not need to select anything you use the :NEW bind variable. So you can just use
V_Berufstart := :NEW.HIREDATE;
If this was an update trigger there would be both a :NEW and :OLD bind variable declared so that you can access the OLD and NEW values. As this is an Insert trigger the :OLD will just be null as there is no old values.

Call odi Mappig through PL/SQl Procedure

enter image description hereI have an anonymous block mentione below , i want to replace the execute immediate statement with the odi scenarion .
Any way of doing it with odi procedure. If i can use any odi api or odi utilities command to replace it.
i.e:
OdiStartScen "-SCEN_NAME=LD_T_RD_ACCOUNT_POC" "-SCEN_VERSION=001"
"-CONTEXT=GLOBAL" "-LOG_LEVEL=6" "-AGENT_CODE=OracleDIAgent1"
"-SYNC_MODE=1";
DECLARE
VAR VARCHAR2(2000);
VAR2 DATE;
BEGIN
BEGIN
Select XYZ INTO VAR
From DUMMY
Where ID= 2; end;
BEGIN
l_exec_sql:= 'INSERT INTO DUMMY VALUES('1')';
IF VAR LIKE 'XY%' THEN
execute immediate(l_exec_sql); --Replace it with odi scenario
ELSE
IF FUNCTION_F(VAR) THEN
execute immediate(l_exec_sql); --Replace it with odi scenario
END IF;
END IF;
END;
Regarding your anonymous block, you should rewrite it like this:
Create a new ODI package;
Create new variable named VAR (or how you like it), inside the var, put what you need, pairing with the proper logical schema;
open the newly create ODI Package, drag-and-drop the variable and choose the Refresh Variable Type (see below picture);
after drag-and-drop variable, choose it again and drag-and-drop, this time choosing the type Evaluate variable, and the write your first condition (see picture below);
then drag and drop what ODI scenario do you need;
You can "play" in many more ways with the odi package variables. For example, you can create a variable that will return YES if the first condition is meet and NO if second one is meet. Your variable will execute an sql statement and will return a value (only one row, one column) and then you will evaluate it and choose what scenario to execute.
Hope that it was useful
EDIT 1:
You can call an ODI Scenario from ODI Procedure, but the techonology should be ODI Tools, for the task that will call the scenario.
For your example you can do like this:
* inside your plsql block, where you have "--Replace it with odi scenario", place this substitution variables : ""; on the second variable evaluate, place "" etc;
* in the same procedure, make another task and write something like this:
<$
if (var.equals("call secenario 1") {
$>
OdiStartScen "-SCEN_NAME=NAMEOFSCENARIO" "-SCEN_VERSION=001"
<$
}
$>
This new task should have Techonology: ODI Tools.
You can't call the scenario in the same task that will run the plsql procedure, because the PLSQL procedure will need Technology Oracle and the calling of scenario will need ODI Tools.
EDIT 2:
To see the value in operator, go to your ODI Procedure, and please check the next option for each of your task. Save an regenerate the scenario (if you have a scenario):
EDIT 3:
Where to see the code in Operator:
Double click the session > choose the task you want to see> expand it> double click > Code

how to use a cursor within a function in PL/SQL

I have an assignment, and the course materials do not cover how to do this, and a web search has not been help regarding cursors within functions.
The assignment is to return all last names in the database, but change any according to the case statement parameters. And I am required to use a cursor. Here is my code:
create or replace function Convert_New_Name
return sys_refcursor
as
c_results sys_refcursor;
begin
open c_results for
select
case last_name
when 'King' then 'LION'
when 'Ford' then 'CAR'
when 'Miller' then 'BEER'
else last_name
end as new_name
from employees;
return c_results;
end convert_new_name;
I'm having a hard time finding anything pertinent in searches. The database has 20 rows. This code returns all 20 rows, with required changes, but it returns those 20 row 20 times, instead of once.
There was another post on here with almost the same assignment, but when I tried to post on there, it got deleted, and I got told to ask my own question.
The function code you posted is fine. The calling code should call function Convert_New_Name only once. If you plan to call it from a SQL statement, then this query should do the job:
Select Convert_New_Name() From dual;

ORA-00984 on an after update pl/sql trigger

I have been fighting with this trigger for a while now, im trying to send to the table "MOVIMIENTO" the old stock, the new one, the difference between them and what kind of operation it is, only problem it's that i get an ORA-00984 error on line 12 and a sql statement ignored on line 11, any ideas?
CREATE OR REPLACE TRIGGER TRG_MOVIMIENTO
AFTER UPDATE OF "STOCK" ON PRODUCTO
FOR EACH ROW
DECLARE
v_tmov VARCHAR2(7);
v_cant NUMBER(6);
BEGIN
v_cant:=:OLD.STOCK-:NEW.STOCK;
IF :OLD.STOCK>:NEW.STOCK THEN
v_tmov:='SALIDA';
ELSE
v_tmov:='ENTRADA';
END IF;
INSERT INTO MOVIMIENTO(N_MOV,TIPO_MOV,STOCK_NEW,STOCK_OLD,CANT_MOV)
VALUES(s_NUMEROMOV.nextval,v_tmod,:NEW.STOCK,:OLD.STOCK,v_cant);
END;
/
Is v_tmod a column on the MOVIMIENTO table. Because there is no variable with that name. That would explain the error.
Edit: OK, looking at the comments, I think I know what is going on.
The variables in the declare section are v_tmov and v_cant.
But in your INSERT statement you have made a typo and used v_tmod.
Oracle sees this is not a known variable so assumes it must be a column name. So it then reports the ORA-00984 error, without even checking to see if its a valid column name. This is because you cannot use a column here.
So the real error is v_tmod is not a defined variable

Resources