Com mai m’enrecordo exactament els diferents tiups de joins amb sql standard… pujo aquesta imatge aclaridora.
a veure si hi poso l’equivalent amb oracle (+)
Es tracta que a partir d’un dia concret, es comenti una linea d’un cron, i aquest ja no es torni a executar mes.
El contingut del crontab es com segueix:
[bi@server1 test_cron]$ crontab -l
#al minut 15 cada 6 hores
15 */6 * * * /home/bi/test_cron/list_files.sh ; /home/bi/test_cron/desactivacron.sh > /home/bi/test_cron/cron.log
He fet el següent bash que ho modifica:
——————— desactivacron.sh —————–
#!/bin/sh
#
# Copia i modifica el crontab
#
#Creem un arxiu temporal
tmpfile=$(mktemp)
today=$(date +%Y%m%d)
cond=$(date -d 2017-05-01 +”%Y%m%d”)
#echo “$today > $cond ?”
#Recuperem el crontab actual
crontab -l > $tmpfile
#Si avui es mes gran que la data $cond
if [ $today -gt $cond ]
then
#Si hem passat de la data, es comenta el cron i ja no s’executarà mes…
sed -i ‘s/^15/#15/’ $tmpfile
else
#Si encara no hem passat la data, es descomenta el cron (en cas que el tingues comentat)
sed -i ‘s/^#15/15/’ $tmpfile
fi
crontab $tmpfile
#El·liminem l’arxiu temporal
rm $tmpfile
———————
Si fem
[bi@server1 test_cron]$ ./desactivacron.sh
El cron queda comentat o no segons si s’ha arribat a la data estipulada.
Aquest sh a la vegada l’executo
Es poden crear funcions que simulen taules, i que a diferencia de les table functions on calia preomplir tots els resultats abans, aquí en els pipelined, es pot anar omplint al vol.
Com a exemple, una funció que ens torna les taules de multiplicar, no es gaire bon exemple, pero es senzil…
Un millor exemple seria per temes de BI, un que ens generes dates, o simplement nombres.
Cal crear dos tipus d’objecte, un que es de camps, com per exemple columnes, o com alguns diuen un record.
L’altre es un “array” de l’anterior, o com en diuen alguns una collection.
–DROP TYPE BI_INT.TY_RMULT;
CREATE OR REPLACE TYPE TY_RMult
AS OBJECT
(
A INT,
B INT,
R INT
)
/
–DROP TYPE BI_INT.TY_TMult;
CREATE OR REPLACE TYPE TY_TMult
AS TABLE OF TY_RMult
/
Aquests dos tipus no es poden crear dintre de una package, sino que son generals, son a nivell de base de dades o esquema. (igual que una package)
Creem la package:
CREATE OR REPLACE PACKAGE JMS_TEST
AS
FUNCTION fTMult (pTau PLS_INTEGER) RETURN TY_TMult PIPELINED;
END JMS_TEST;
/
Creem el body…
CREATE OR REPLACE PACKAGE BODY JMS_TEST
AS
FUNCTION fTMult (pTau PLS_INTEGER) RETURN TY_TMult PIPELINED IS
BEGIN
DBMS_OUTPUT.ENABLE;
FOR i in 1 .. pTau LOOP
FOR j in 1 .. 10 LOOP
PIPE ROW (TY_RMult(i,j,i*j));
END LOOP;
if mod(i,100) =0 then
dbms_output.put_line(i);
end if;
END LOOP;
RETURN;
END fTMult;
END JMS_TEST;
/
Ara quan executem :
select * from TABLE (JMS_TEST.fTMult(300));
Ens surten les taules de multiplicar…
A | B | R |
---|---|---|
1
|
1
|
1
|
1
|
2
|
2
|
1
|
3
|
3
|
1
|
4
|
4
|
1
|
5
|
5
|
1
|
6
|
6
|
1
|
7
|
7
|
1
|
8
|
8
|
A mida que anem consultant, s’executen els bucles i al passar per 100, 200 i 300 hi ha un put line a dbms_output.
Així veiem que realment es una funció pipelined. !!!
Cron que executa Bash i taula externa
Es tracta de programar un cron executi una instrucció en un bash (llista de arxius “ls”) que llegeix els noms dels arxius que hi ha en un directori i generi un arxiu amb aquest contingut.
Finalment, es pot legir l’arxiu amb utl_file o com en l’exemple creem una taula externa, que ens facilita l’accés.
Comencem per el bash:
[bi@servidor1 test_cron]$ cat list_files.sh
#!/bin/sh
#
# Generate a comma separated ls -l for the directory in which the external table’s
# location file resides
#
ls -l –time-style=long-iso /data/int/test | /usr/bin/awk ‘BEGIN {OFS = “,”;} {print $1, $2, $3, $4, $5, $6″ “$7, $8}’ > /data/int/test/ls_files.txt
—
Creem taula a oracle
DROP TABLE BI_INT.LS_DIR_EXT;
CREATE TABLE BI_INT.LS_DIR_EXT
(
permisos VARCHAR(15),
tipus VARCHAR(1),
usuari VARCHAR(15),
grup VARCHAR(15),
mida VARCHAR(8),
data VARCHAR(20),
nom VARCHAR(100)
)
ORGANIZATION EXTERNAL
(
TYPE ORACLE_LOADER
DEFAULT DIRECTORY DIR_CIEN_INT
ACCESS PARAMETERS
(
RECORDS DELIMITED BY NEWLINE
SKIP 1
NOBADFILE
NOLOGFILE
FIELDS TERMINATED BY ‘,’
)
LOCATION (DIR_CIEN_INT:’ls_files.txt’)
)
REJECT LIMIT UNLIMITED
NOPARALLEL
NOMONITORING;
Ens connectem amb putty o Terminal SSH Secure Shell Client
Per veure els crons:
[bi@servidor test_cron]$ crontab –l
*/30 * * * * /home/bi/test_cron/list_files.sh > /home/bi/test_cron/cron.log
#Comentari: S’executa cada 30 minuts
—-
Així, finalment si fem:
select * from BI_INT.LS_DIR_EXT
veurem:
PERMISOS | TIPUS | USUARI | GRUP | MIDA | DATA | NOM |
---|---|---|---|---|---|---|
-rw-r–r– | 1 | bi | prd | 28493 | 2016-03-31 16:11 | 280796079_3350699_160101_160115_160125_121326.xml.tar.gz |
-rw-r–r– | 1 | bi | prd | 54981 | 2016-03-31 16:15 | 410592062_8403368_160101_160115_160125_183950.xml.tar.gz |
-rw-r–r– | 1 | bi | prd | 0 | 2017-04-18 06:15 | ls_files.txt |
-rw-r–r– | 1 | bi | prd | 23 | 2017-04-04 15:44 | taula.txt |
—–
Per editar el cron:
crontab -e
S’obra en “Vi”
(Esc)
i – Insertar davant cursor
a – afegir darrera cursor
:w – escriu
:x – escriu i surt
———-
Si es tenen els permisos adequats, es pot arribar a fer que la propia consulta de la taula externa executi al vol un .sh que regeneri l’arxiu o troni directament el resultat, evitant així la necessitat de fer el cron.
Hi ha diverses maneres de intercomunicar el pslql amb el bash.
Llegir i escriure un txt a linux desde PLSQL.
Es pot utilitzar el paquet utl.file per llegir i escriure arxius a linux.
declare
fArchivo UTL_FILE.file_type;
pLinea varchar2(1000);
begin
— Escriure i crear
fArchivo := Utl_File.fopen(‘DIR_ORACLE’, ‘test.txt’, ‘w’, 32767);
pLinea:=’Es un test!! ‘||to_char(sysdate,’HH24:MI:SS’);
Utl_File.put_line(fArchivo,pLinea);
Utl_File.fclose(fArchivo);
— Llegir
pLinea:=null;
fArchivo := Utl_File.fopen(‘DIR_ORACLE’, ‘test.txt’, ‘r’, 32767);
Utl_File.get_line(fArchivo,pLinea);
Utl_File.fclose(fArchivo);
— Elimino arxiu
Utl_File.fremove(‘DIR_ORACLE’,’test.txt’);
dbms_output.put_line(pLinea);
end;
———–
Es un test!! 10/04/17
Es un test!! 09:21:16
Es un test!! 09:21:46
——–
Per fer això, cal tindre permisos d’escriptura i creació d’arxius al directori de Linux.
També cal haver definit un DIRECTORY a Oracle amb permisos d’escriptura i lectura.
select * from all_directories;
OWNER DIRECTORY_NAME DIRECTORY_PATH
SYS DIR_ORACLE /data/intercanvi/dir_oracle
Amb això creem estructures tabulars al vol… que es podem consumir com qualsevol taula…
El “problema” d’això es que tot va a memoria, i no torna resultats fins que ho te tot…
CREATE TYPE t_tf_row AS OBJECT (
id NUMBER,
description VARCHAR2(50)
);
CREATE TYPE t_tf_tab IS TABLE OF t_tf_row;
CREATE OR REPLACE FUNCTION get_tab_tf (p_rows IN NUMBER) RETURN t_tf_tab AS
l_tab t_tf_tab := t_tf_tab();
BEGIN
FOR i IN 1 .. p_rows LOOP
l_tab.extend;
l_tab(l_tab.last) := t_tf_row(i, ‘Description for ‘ || i);
END LOOP;
RETURN l_tab;
END;
select t.*, d.* from table(get_tab_tf(5)) t, dual d;
ID | DESCRIPTION | DUMMY |
---|---|---|
1
|
Description for 1 | X |
2
|
Description for 2 | X |
3
|
Description for 3 | X |
4
|
Description for 4 | X |
5
|
Description for 5 | X |
CREATE TABLE BI_INT.jerarquia
(
ID INTEGER,
REF_ID INTEGER,
NOM VARCHAR2(50)
);
ALTER TABLE BI_INT.jerarquia ADD (
PRIMARY KEY
(ID));
insert into jerarquia values (1,null,’Avi’);
insert into jerarquia values (2,1,’Pare1′);
insert into jerarquia values (3,1,’Pare2′);
insert into jerarquia values (4,2,’Fill1′);
insert into jerarquia values (5,2,’Fill3′);
insert into jerarquia values (6,3,’Fill2′);
insert into jerarquia values (7,3,’Fill4′);
insert into jerarquia values (8,4,’Net1′);
insert into jerarquia values (9,7,’Net2′);
commit;
select * from jerarquia;
SELECT nom, id, ref_id, LEVEL, SYS_CONNECT_BY_PATH(nom, ‘/’) as Arbre
FROM jerarquia
–where level < 3
START WITH id = 1
CONNECT BY PRIOR id = ref_id
ORDER SIBLINGS BY nom;
——
NOM | ID | REF_ID | LEVEL | ARBRE |
---|---|---|---|---|
Avi |
1
|
1
|
/Avi | |
Pare1 |
2
|
1
|
2
|
/Avi/Pare1 |
Fill1 |
4
|
2
|
3
|
/Avi/Pare1/Fill1 |
Net1 |
8
|
4
|
4
|
/Avi/Pare1/Fill1/Net1 |
Fill3 |
5
|
2
|
3
|
/Avi/Pare1/Fill3 |
Pare2 |
3
|
1
|
2
|
/Avi/Pare2 |
Fill2 |
6
|
3
|
3
|
/Avi/Pare2/Fill2 |
Fill4 |
7
|
3
|
3
|
/Avi/Pare2/Fill4 |
Net2 |
9
|
7
|
4
|
/Avi/Pare2/Fill4/Net2 |