Oracle 19, PL/SQL i samotné SQL
Mrtvé linky prosím hlašte - ty o kterých vím a jde to nahrazuji pomocí Wayback Machine :)
SELECT SYS_GUID() AS guid FROM dual; -- např. 01EA3F6DD60D45EAA7AEAC3AC0B93347 DECLARE lGUID VARCHAR2(32) := SYS_GUID(); ...
utl_url.escape(url => 'nějaký text', url_charset => 'UTF-8'); -- n%C4%9Bjak%C3%BD%20text utl_url.unescape('n%C4%9Bjak%C3%BD%20text', 'UTF-8'); -- nějaký text
DECLARE lText VARCHAR2(255); lBase64Coded VARCHAR2(255); BEGIN lBase64Coded := utl_encode.text_encode(buf => 'nějaký text', encoding => utl_encode.base64); dbms_output.put_line(lBase64Coded); -- buxqYWv9IHRleHQ= lText := utl_encode.text_decode(buf => lBase64Coded, encoding => utl_encode.base64); dbms_output.put_line(lText); -- nějaký text END;
WITH)over…)CONNECT BY'nejlepší' řešení - je nejjednodušší a proti rek. CTE je zjevně mnohem rychlejší. Má ale i zásadní záludnosti (viz např. zahlušení výjimek)-- rekurzivní CTE musí obsahovat seznam sloupců WITH cisla(cislo) AS ( -- počáteční krok SELECT 1 AS cislo FROM dual UNION ALL -- vždy musí být all -- rekurzivní krok SELECT c.cislo + 1 FROM cisla c WHERE c.cislo < 15 ) SELECT * FROM cisla;
SELECT RTRIM(XMLAGG(XMLELEMENT(e, t.ke_spojeni, ', ').EXTRACT('//text()') ORDER BY t.sloupec_trideni).GetClobVal(), ', ') FROM tabulka t
XMLAGG(xml_element ORDER BY podle_čeho_třídit)XMLELEMENT(název_elementu, hodnoty_elementu) vytvoří XMLTYPE sloučeninu hodnoty na řádku (t.ke_spojeni) a ', '.extract('//text()') - extrahuje obsah elementu (výsledek je stále XMLTYPE).GetClobVal() - převede extrahovaný text z XML do clobuRTRIM() - ořízne zprava o poslední ', 'sys.dba_tab_privsGRANTEE = komu je právo udělenoGRANTOR = kdo právo udělovalTABLE_NAME = samotný název objektu (klidně i package), neobsahuje název schematuPRIVILEGE = oprávnění (SELECT, INSERT, EXECUTE, není zde ALL :)SELECT * FROM dba_tab_privs WHERE table_name = 'API_PRIKAZY_LOG';
SELECT * FROM all_constraints ac WHERE ac.owner = 'TEST' AND ac.constraint_name = 'TABULKA_CHECK';
dummysekvence.CURRVAL v SQL dotazu, může Oracle vyhodit chybu ORA-08002: sequence MySequence.CURRVAL is not yet defined in this sessionCURRVAL se v aktuální session musí alespoň jednou použít NEXTVAL-- aktuální hodnota sekvence TEST.TABULKA_SQ SELECT last_number-1 AS curr_val FROM DBA_SEQUENCES WHERE sequence_name = 'TABULKA_SQ';
ora_hash - je omezený na 4000 zn.dbms_crypto.Hash:-- vstupem je CLOB a typ hashe (3 = SHA256) -- výstupem je RAW, ten lze zkonvertovat např. do varcharu v hexa tvaru SELECT s.src_data, RAWTOHEX(dbms_crypto.Hash(src => s.src_data, typ => 3)) FROM test.sankce s;
dbms_crypto.Hash může mít problémy se znaky s codebase nad 127 (řešení je potřeba ověřit)CREATE TABLE test.tmp_tab_merge ( id NUMBER, text VARCHAR2(255), CONSTRAINT pk_tmp_tab_merge PRIMARY KEY (id) USING INDEX ); INSERT INTO test.tmp_tab_merge SELECT 1 AS id, 'ahoj' AS text FROM dual UNION ALL SELECT 2 AS id, 'nazdar' AS text FROM dual UNION ALL SELECT 3 AS id, 'čau' AS text FROM dual; COMMIT;
merge INTO test.tmp_tab_merge l USING ( SELECT 1 AS id, 'hoja' AS text FROM dual UNION ALL SELECT 15 AS id, 'aloha' AS text FROM dual ) n ON (l.id = n.id) WHEN matched THEN UPDATE SET l.text = n.text WHEN NOT matched THEN INSERT (id, text) VALUES (n.id, n.text);
case when (z.a is null and z.b is null) or (z.a = z.b) then 0 else 1 end as rozdilcase when nvl(z.a, -99999) = nvl(z.b, -99999) then 0 else 1 end as rozdildecode(z.a, z.b, 0, 1) as rozdilSELECT z.a, z.b, DECODE(z.a, z.b, 0, 1) AS rozdil FROM ( SELECT 1 AS A, 1 AS B FROM dual UNION ALL SELECT 1 AS A, 2 AS B FROM dual UNION ALL SELECT 2 AS A, 1 AS B FROM dual UNION ALL SELECT 2 AS A, NULL AS B FROM dual UNION ALL SELECT NULL AS A, 2 AS B FROM dual UNION ALL SELECT NULL AS A, NULL AS B FROM dual ) z;
default on null … (stejně tak jde používat např. sysdate pro automatické plnění sloupce s datem)test.import_sq)CREATE TABLE test.soubory ( import_id INTEGER DEFAULT ON NULL test.import_sq.NEXTVAL PRIMARY KEY, datum_cas DATE DEFAULT ON NULL SYSDATE, nazev_souboru VARCHAR2(255), obsah clob );
INSERT INTO test.soubory(nazev_souboru, obsah) VALUES('test.txt', 'tohle je pokus s automatickým ID a časem zápisu'); COMMIT;
SELECT ROWNUM AS RANK, a.* FROM (SELECT v.sid, sess.USERNAME, sess.Serial#, program, v.VALUE / (100 * 60) CPUMins FROM v$statname s, v$sesstat v, v$session sess WHERE s.name = 'CPU used by this session' AND sess.sid = v.sid AND v.statistic# = s.statistic# AND v.VALUE > 0 ORDER BY v.VALUE DESC) a WHERE ROWNUM < 11;
SELECT sql_id, executions, ROUND(cpu_time / 1000000, 2) AS cpu_sec, ROUND(cpu_time / executions / 1000000, 4) AS cpu_per_exec, sql_text FROM v$sql WHERE cpu_time > 0 ORDER BY cpu_time DESC FETCH FIRST 10 ROWS ONLY;
SELECT O.OBJECT_NAME, S.SID, S.SERIAL#, P.SPID, S.PROGRAM, S.USERNAME, S.MACHINE, S.PORT, S.LOGON_TIME, SQ.SQL_FULLTEXT FROM V$LOCKED_OBJECT L, DBA_OBJECTS O, V$SESSION S, V$PROCESS P, V$SQL SQ WHERE L.OBJECT_ID = O.OBJECT_ID AND L.SESSION_ID = S.SID AND S.PADDR = P.ADDR AND S.SQL_ADDRESS = SQ.ADDRESS;
ahoj /*nazdar*/ čau /*aloha*/ hoja, pak odstranění zakomentovaných částí obvykle najde první výskyt /* a pak poslední */. Tím přijdeme o text mezi komentáři (čau)/\*(.*)\*//\* = /*(.*) = skupina (závorky) jakýchkoli znaků (tečka) v množství 0 a víc (hvězdička)\*/ = */*? a znamená množství 0 a víc tak, aby byl výsledek co nejmenšíDECLARE lText VARCHAR2(255) := 'ahoj /*nazdar*/ čau /*aloha*/ hoja'; BEGIN lText := REGEXP_REPLACE(lText, '/\*(.*?)\*/', '', 1, 0, 'n'); -- odstranění /**/ lText := REGEXP_REPLACE(lText, '--(.*)'); -- odstranění -- dbms_output.put_line(lText); -- výsledek: ahoj čau hoja END;
@echo off sqlplus -s -l USER/pass@yourdb @yoursql.sql>your_log.LOG
EXEC test.test_jobs_start_pk.nastartuj_procesy; EXIT;
TABLE_OWNER je prázdnýtest.tabulka, pak tento sloupec ignoruji a použiju pouze jméno tabulky (bez schematu)-- podle SCN SELECT r.* FROM test.tabulka AS OF scn 4527718937 r; -- podle času SELECT * FROM test.tabulka AS OF TIMESTAMP TO_TIMESTAMP('30.5.2023 11:17:42', 'DD.MM.YYYY HH24:MI:SS') r;
SELECT s.sid, s.serial#, s.audsid, s.username, s.osuser, s.client_identifier, s.sql_trace, s.action, p.spid, p.tracefile FROM v$session s, v$process p WHERE s.paddr = p.addr AND s.username IS NOT NULL;
itool.string_pole_typ, itool.num_pole_typ a další table of typy…SELECT CASE WHEN 123 MEMBER OF itool.num_pole_typ(1, 2, 3, 123) THEN 'ano' ELSE 'ne' END AS je_clenem FROM dual;
DECLARE TYPE t_tab IS TABLE OF VARCHAR2(255); lTab t_tab := t_tab(); BEGIN lTab.extend; lTab(lTab.LAST) := 'ahoj'; IF 'ahoj' member OF lTab THEN :je_v_tab := 'ano'; ELSE :je_v_tab := 'ne'; END IF; END;
-- dotaz na sessions držící vybranou globální temp tabulku GTT_OWNER.GTT_NAME SELECT * FROM gv$lock WHERE id1 = ( SELECT object_id FROM dba_objects WHERE owner = UPPER('GTT_OWNER') AND object_name = UPPER('GTT_NAME') );
to_char() atp.Toto funguje:
DECLARE x clob; BEGIN FOR i IN 1 .. 8000 LOOP x := x || i; END LOOP; dbms_output.put_line( LENGTH( x ) ); END;
Toto již nefunguje:
DECLARE x clob; BEGIN FOR i IN 1 .. 9000 -- vede na více než 32767 znaků LOOP x := x || i; END LOOP; dbms_output.put_line( LENGTH( x ) ); END;
A toto opět funguje:
DECLARE x clob; BEGIN FOR i IN 1 .. 9000 LOOP x := x || TO_CHAR(i); -- explicitní konverze je ok END LOOP; dbms_output.put_line( LENGTH( x ) ); END;