Dynamically generate DDL from text file input fields for table output - pentaho-data-integration

Consider the following three files:
1.csv [contains 3 fields: a, b, c]
2.csv [contains 4 fields: d, e, f, g]
3.csv [contains 2 fields: h, i]
My assignment is to load all three files to their respective table output. So
File "*.csv" ->loads-> Table "*_csv"
I know I can process multiple files with the "Get File Names" step but how do I generate a DDL statement that creates the target table for each file? I am looking at the metadata injection step but I am not sure this fits my needs.
Any advice?
Pentaho Data Integration 7.0
Postgres RDS

You can below procedure to create the table dynamically.The only prob in this procedure is it is creating table with the same name. play with this code. I created this code in mysql. Prerequisite is you have to pass field names in concatenated form like 'col1,col2,col3'.
delimiter $$
create procedure dynamic_table (col_concat varchar(2000),out query1 varchar(1000))
begin
declare i integer ;
declare v_count int;
declare v_col varchar(100);
set i =1;
select LENGTH(col_concat) - LENGTH(REPLACE(col_concat, ',', ''))+1 into v_count;
set query1 =(select concat('create table table',convert(i,signed),' ( '));
while (i<= v_count)
do
begin
select replace(substring_index(col_concat,',',i),',','_') into v_col;
set query1 = (select concat(query1, v_col,' varchar(1000), '));
set i=i+1;
end;
end while;
select query1;
set query1= replace(query1,substring(query1,length(query1)-1,1),' )');
select query1;
end;$$
sample run : call dynamic_table ('col1,col2,col3',#query1)

Related

Deleting Records from multiple tables with the SQL Query

I have a staging table in Oracle DB where the data is loaded and table name is pc_stg_auth. It has 4 PKs. I Have to match these 4 PKs with another table called autho_activity_msc and if the PKs match then I have to delete the record from both the staging table called pc_stg_auth as well as from autho_activity_msc.
I am using below query but it is giving me a syntax error:
delete autho_activity_msc , pc_stg_auth from autho_activity_msc inner join pc_stg_auth
where autho_activity_msc.reference_number = pc_stg_auth.reference_number AND
autho_activity_msc.external_stan = pc_stg_auth.external_stan AND
autho_activity_msc.routing_code = pc_stg_auth.routing_code AND
autho_activity_msc.capture_code = pc_stg_auth.capture_code;
commit;
Below is the eror:
line 1: ORA-00933: SQL command not properly ended
please help or suggest if there is a simpler way to achieve it.
Oracle does not support that syntax.
You need to use multiple DELETE statements. You can delete the matched rows from one table and collect the matched keys into collections and then loop through the collections and delete all the rows in the second table:
DECLARE
rns SYS.ODCINUMBERLIST;
ess SYS.ODCINUMBERLIST;
rcs SYS.ODCINUMBERLIST;
ccs SYS.ODCINUMBERLIST;
BEGIN
DELETE FROM pc_stg_auth
WHERE (reference_number, external_stan, routing_code, capture_code)
IN (SELECT reference_number, external_stan, routing_code, capture_code
FROM autho_activity_msc)
RETURNING reference_number, external_stan, routing_code, capture_code
BULK COLLECT INTO rns, ess, rcs, ccs;
FORALL i IN 1 .. rns.COUNT
DELETE FROM autho_activity_msc
WHERE reference_number = rns(i)
AND external_stan = ess(i)
AND routing_code = rcs(i)
AND capture_code = ccs(i);
COMMIT;
END;
/
db<>fiddle here

alias required in select list of cursor

I m getting an error as when I compiled the below code as alias required in select list of the cursor.
Create Or Replace PROCEDURE pr_no_debit is
Cursor c_Today(From_date date, To_Date date) is
Select Today from sttm_dates where today between From_Date and To_Date;
cursor c_no_debit is
Select a.* , b.* from STTM_NO_DEBIT_customer a , STTM_FIN_CYCLE b where a.Fin_Cycle = b.Fin_Cycle ;
l_No_Debit_List STTM_NO_DEBIT_CUSTOMER%ROWTYPE;
begin
For i_indx in c_Today(l_No_Debit_List.From_Date,l_No_Debit_List.To_Date)
Loop
for j_indx in c_no_debit
loop
update sttm_cust_account set ac_stat_no_Dr='Y' where account_class=j_index.account_class;
end loop;
End Loop;
-- At the end of the period Change No_Debit to 'N'
End pr_no_debit;
Another solution could be to split the cursor into two parts, though giving alias to respective columns shall be sufficient under the case:
Cursor c_no_debit :
c_no_debit_1: Based on table STTM_NO_DEBIT_customer a
c_no_debit_2: Based on table STTM_FIN_CYCLE b
Through parameterized cursor pass value of of cursor_1 into cursor_2.
Tables STTM_NO_DEBIT_CUSTOMER and STTM_FIN_CYCLE both have a column named FIN_CYCLE, so when the PL/SQL compiler tries to construct the record j_indx from c_no_debit, it gets something like this:
( fin_cycle number
, from_date date
, to_date date
, account_class varchar2(20)
, fin_cycle number
, ...
which is invalid because a record can't have two fields with the same name.
Change c_no_debit to specify only the columns you need, for example:
cursor c_no_debit is
select a.account_class
from sttm_no_debit_customer a
join sttm_fin_cycle b on b.fin_cycle = a.fin_cycle;
(and maybe other columns - I don't have your schema and I don't know what it needs to do)

Create simple PL/SQL variable - Use Variable in WHERE clause

Thanks for looking...
I've spent hours researching this and I can't believe it's that difficult to do something in PL/SQL that is simple in TSQL.
I have a simple query that joins 2 tables:
Select DISTINCT
to_char(TO_DATE('1899123000', 'yymmddhh24')+ seg.NOM_DATE, 'mm/dd/yyyy') AS "Record Date"
, cd.CODE
, EMP.ID
, EMP.SHORT_NAME
FROM
EWFM.GEN_SEG seg join EWFM.SEG_CODE cd ON seg.SEG_CODE_SK = cd.SEG_CODE_SK
join EMP on seg.EMP_SK = EMP.EMP_SK
where NOM_DATE = vMyDate;
I use Toad Date Point and I'm querying against an Oracle Exadata source. The resulting query will be dropped into a visualization tool like QlikView or Tableau. I'd like to create a simple variable to use the the WHERE clause as you can see in the code.
In this example, NOM_DATE is an integer such as 42793 (2/27/2017) as you can see in the first row "Record Date". Nothing new here, not very exciting... Until... I tried to create a variable to make the query more dynamic.
I've tried a surprising variety of examples found here, all have failed. Such as:
declare
myDate number(8);
Begin
myDate := 42793;
--Fail ORA-06550 INTO Clause is expected
variable nomDate NUMBER
DEFINE nomDate = 42793
EXEC : nomDate := ' & nomDate'
...where NOM_DATE = ( & nomDate) ;
--ORA-00900: invalid SQL statement
and
variable nomDate NUMBER;
EXEC nomDate := 42793;
select count(DET_SEG_SK) from DET_SEG
where NOM_DATE = :nomDate;
--ORA-00900: invalid SQL statement
and several more.. hopefully you get the idea. I've spent a few hours researching stackoverflow for a correct answer but as you can see, I'm asking you. From simple declarations like "Var" to more complex " DECLARE, BEGIN, SELECT INTO...." to actually creating Functions, using cursors to iterate the output.... I still can't make a simple variable to use in a Where clause.
Please explain the error of my ways.
--Forlorn SQL Dev
Since you are using an implicit cursor, you have to select then INTO variables. Now I d not know the data types of you variables, so I have just guessed in this example below, but hopefully you get the point.
Two other things I should mention
Why are you TO_CHARing you DATE. Just use a DATE datatype. Also, I think your format mask is wrong too 1899123000 does not match yymmddhh24.
In explicit cursor expects exactly one row; no rows and you get NO_DATA_FOUND; more than one and you get TOO_MANY_ROWS
Declare
myDate number(8) := 42793;
/* These 4 variable data types are a guess */
v_record_date varchar2(8);
v_cd_code varchar2(10);
v_emp_id number(4);
v_emp_short_name varchar2(100);
BEGIN
Select DISTINCT to_char(TO_DATE('1899123000', 'yymmddhh24')
+ eg.NOM_DATE, 'mm/dd/yyyy') AS "Record Date"
, cd.CODE
, EMP.ID
, EMP.SHORT_NAME
INTO v_record_date, v_cd_code, v_emp_id, v_emp_short_name
FROM EWFM.GEN_SEG seg
join EWFM.SEG_CODE cd
ON seg.SEG_CODE_SK = cd.SEG_CODE_SK
join EMP
on seg.EMP_SK = EMP.EMP_SK
where NOM_DATE = myDate;
END;
/
VARIABLE vMyDate NUMBER;
BEGIN
:vMyDate := 42793;
END;
/
-- or
-- EXEC :vMyDate := 42793;
SELECT DISTINCT
TO_CHAR( DATE '1899-12-30' + seg.NOM_DATE, 'mm/dd/yyyy') AS "Record Date"
, cd.CODE
, EMP.ID
, EMP.SHORT_NAME
FROM EWFM.GEN_SEG seg
join EWFM.SEG_CODE cd
ON seg.SEG_CODE_SK = cd.SEG_CODE_SK
join EMP
on seg.EMP_SK = EMP.EMP_SK
WHERE NOM_DATE = :vMyDate;
You put the variables with getter and setter in a package.
Then use a view that uses the package getter
Personally I prefer to use a collection that way I can do a select * from table (packagage.func(myparam))

how to save synonyms in database ( Oracle Text )

I am using oracle text for Arabic language.
I want to save the synonyms list in a database table, so the domain index read from this table, any idea ?
I found a solution :
1- I uploaded my synonyms list to a table called words( contains all the terms and their synonyms' IDs ) and master table called synset (contains synonyms)
2- create thesaurus :
begin
ctx_thes.create_thesaurus ('MyThesaurus');
end;
3- create a stored procedure to read from my table [words] and create relationship between synonyms:
create or replace procedure CreateSynonyms is
CURSOR syn_cur is select s.name_abstract,w.root,w.word_abstract
from p words w , synset s
where w.synset_id=s.synset_id and w.root<>s.name_abstract and w.word_abstract<> s.name_abstract
order by s.synset_id;
syn_rec syn_cur%rowtype;
BEGIN
OPEN syn_cur;
LOOP
FETCH syn_cur into syn_rec;
EXIT WHEN syn_cur%notfound;
begin
ctx_thes.create_relation ('MyThesurus', syn_rec.name_abstract, 'syn', syn_rec.word_abstract);
END LOOP;
END;
4- rewrite my query to select synonyms:
select /*+ FIRST_ROWS(1)*/ sentence_id,score(1) as sc, isn
where contains(PROCESSED_TEXT,'<query>
<textquery>
search for somthing here
<progression>
<seq><rewrite>transform((TOKENS, "{", "}", ","))</rewrite></seq>
<seq><rewrite>transform((TOKENS, "syn(", ",listing)", " , "))</rewrite>/seq>
</progression>
</textquery>
<score datatype="INTEGER" algorithm="COUNT"/></query>',1)>0
Hope this will help someone

Create PL/SQL script with 2 cursors, a parameter and give results from a table?

I need to create a script that puts a key number from table A (which will be used as a parameter later), then flow that parameter or key number into a query and then dump those results into a holding record or table for later manipulation and such. Because each fetch has more than 1 row (in reality there are 6 rows per query results or per claim key) I decided to use the Bulk Collect clause. Though my initial test on a different database worked, I have not yet figured out why the real script is not working.
Here is the test script that I used:
DECLARE
--Cursors--
CURSOR prod_id is select distinct(product_id) from product order by 1 asc;
CURSOR cursorValue(p_product_id NUMBER) IS
SELECT h.product_description,o.company_short_name
FROM company o,product h
WHERE o.product_id =h.product_id
AND h.product_id =p_product_id
AND h.product_id IS NOT NULL
ORDER by 2;
--Table to store Cursor data--
TYPE indx IS TABLE OF cursorValue%ROWTYPE
INDEX BY PLS_INTEGER;
indx_tab indx;
---Variable objects---
TotalIDs PLS_INTEGER;
TotalRows PLS_INTEGER := 0 ;
BEGIN
--PARAMETER CURSOR RUNS---
FOR prod_id2 in prod_id LOOP
dbms_output.put_line('Product ID: ' || prod_id2.product_id);
TotalIDs := prod_id%ROWCOUNT;
--FLOW PARAMETER TO SECOND CURSOR--
Open cursorValue(prod_id2.product_id);
Loop
Fetch cursorValue Bulk collect into indx_tab;
---data dump into table---
--dbms_output.put_line('PROD Description: ' || indx_tab.product_description|| ' ' ||'Company Name'|| indx_tab.company_short_name);
TotalRows := TotalRows + cursorValue%ROWCOUNT;
EXIT WHEN cursorValue%NOTFOUND;
End Loop;
CLOSE cursorValue;
End Loop;
dbms_output.put_line('Product ID Total: ' || TotalIDs);
dbms_output.put_line('Description Rows: ' || TotalRows);
END;
Test Script Results:
anonymous block completed
Product ID: 1
Product ID: 2
Product ID: 3
Product ID: 4
Product ID: 5
Product ID Total: 5
Description Rows: 6
Update: Marking question as "answered" Thanks.
The first error is on line 7. On line 4 you have:
CURSOR CUR_CLAIMNUM IS
SELECT DISTINCT(CLAIM_NO)FROM R7_OPENCLAIMS;
... and that seems to be valid, so your column name is CLAIM_NO. On line 7:
CURSOR OPEN_CLAIMS (CLAIM_NUM R7_OPENCLAIMS.CLAIM_NUM%TYPE) IS
... so you've mistyped the column name as CLAIM_NUM, which doesn't exist in that table. Which is what the error message is telling you, really.
The other errors are because the cursor is invalid, becuase of that typo.
When you open the second cursor you have the same name confusion:
OPEN OPEN_CLAIMS (CUR_CLAIMNUM2.CLAIM_NUM);
... which fails because the cursor is querying CLAIMNO not CLAIMNUM; except here it's further confused by the distinct. You haven't aliased the column name so Oracle applies one, which you could refer to, but it's simpler to add your own:
CURSOR CUR_CLAIMNUM IS
SELECT DISTINCT(CLAIM_NO) AS CLAIM_NO FROM R7_OPENCLAIMS;
and then
OPEN OPEN_CLAIMS (CUR_CLAIMNUM2.CLAIM_NO);
But I'd suggest you also change the cursor name from CUR_CLAIMNUM to CUR_CLAIM_NO, both in the definition and the loop declaration. And having the cursor iterator called CUR_CLAIMNUM2 is odd as it suggests that is itself a cursor name; maybe something like ROW_CLAIM_NO would be clearer.

Resources