Upload
jeffrey-kemp
View
852
Download
1
Embed Size (px)
Citation preview
Old Oracle Versions Top 20 Gotchas
Jeffrey Kemp
AUSOUG Perth Conference, October 2012
Poll
• Oldest Oracle database version worked with
• Past 12 months (approximately)
Database Versions & Extended Support 1
99
2
20
15
20
10
20
00
20
05
19
95
v7
v8
8i
9i
9iR2
10g
10gR2
11g
11gR2
12c
Disclaimer The following is intended to outline the general product direction way back in the distant past. It is intended for information purposes only, and may not always be perfectly syntactically correct. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions (if you’re thinking of buying 8i or 9i, you should probably get out from under that rock). The development, release, and timing of any features or functionality described for Oracle’s products remains at the sole discretion of Oracle… who cares, give us the new features now!
“Be grateful for what you have...”
vs.
#20: insert from record type
INSERT INTO mytable
VALUES rec;
#20: insert from record type
INSERT INTO mytable
VALUES rec;
INSERT INTO mytable (col1, col2, col3, …)
VALUES (rec.col1, rec.col2, rec.col3, …);
#19: temporary tables
CREATE GLOBAL TEMPORARY TABLE t...
#19: temporary tables
BEGIN
TRUNCATE TABLE ordinary_tmp;
INSERT INTO ordinary_tmp ...;
-- etc…
END;
#18: error messages
EXCEPTION
DBMS_OUTPUT.put_line(
DBMS_UTILITY.format_error_backtrace
);
RAISE;
END;
#18: error messages
EXCEPTION
DBMS_OUTPUT.put_line(
DBMS_UTILITY.format_error_backtrace
SQLERRM
);
RAISE;
END;
#17: queries on DBMS_RANDOM
SELECT DBMS_RANDOM.value FROM dual;
ORA-00600 internal error
http://www.angelfire.com/home/jasonvogel/oracle_plsql_random_number_generator.html
#16: TIMESTAMP & INTERVAL
the_exact_time TIMESTAMP := SYSTIMESTAMP;
#16: TIMESTAMP & INTERVAL
the_exact_time TIMESTAMP := SYSTIMESTAMP;
Java - timestamp.getTime() (number of milliseconds since January 1, 1970, 00:00:00 GMT)
#15: DIRECTORY objects CREATE DIRECTORY mydir AS '/usr/example';
#15: DIRECTORY objects CREATE DIRECTORY mydir AS '/usr/example'; ALTER SYSTEM SET UTL_FILE_DIR='/usr/example' SCOPE=SPFILE; - restart database
f := utl_file.fopen( '/usr/example' , 'myfile.txt' , 'rw');
#14: SQL analytic functions BEGIN FOR r IN ( SELECT RANK(a) OVER (PARTITION BY b ORDER BY c) q FROM t) LOOP ...
#14: SQL analytic functions BEGIN FOR r IN ( SELECT RANK(a) OVER (PARTITION BY b ORDER BY c) q FROM t) LOOP ... CREATE VIEW v AS SELECT RANK(a) OVER (PARTITION BY b ORDER BY c) q FROM t; BEGIN FOR r IN (SELECT q FROM t) LOOP ... (alternatively, use dynamic SQL instead)
R2 Analytic functions were added in 8iR2, but they only work in plain SQL – PL/SQL embedded SQL didn’t use the same engine.
#13: write BLOB to file l_file := UTL_FILE.fopen ('BLOBS','MyImage.gif','w', 32767); WHILE l_pos < l_blob_len LOOP DBMS_LOB.read(l_blob, l_amount, l_pos, l_buffer); UTL_FILE.put_raw(l_file, l_buffer, TRUE); l_pos := l_pos + l_amount; END LOOP; UTL_FILE.fclose(l_file);
#13: write BLOB to file l_file := UTL_FILE.fopen ('BLOBS','MyImage.gif','w', 32767); WHILE l_pos < l_blob_len LOOP DBMS_LOB.read(l_blob, l_amount, l_pos, l_buffer); UTL_FILE.put_raw(l_file, l_buffer, TRUE); l_pos := l_pos + l_amount; END LOOP; UTL_FILE.fclose(l_file);
Java - http://www.oracle-base.com/articles/8i/export-blob.php
#12: external tables CREATE TABLE t ... ORGANIZATION EXTERNAL
#12: external tables CREATE TABLE t ... ORGANIZATION EXTERNAL CREATE OR REPLACE VIEW diy$extfile AS SELECT * FROM TABLE( CAST(read_file_into_array() AS my_array_type) ); (using UTL_FILE) - http://www.oracle-base.com/articles/8i/diy-dynamic-views.php
#11: XMLTYPE
CREATE TABLE t (myxml XMLTYPE);
#11: XMLTYPE CREATE TABLE t (myxml XMLTYPE);
xmlparser.parse( v_parser , 'C:\emp.xml'); v_doc := xmlparser.getDocument (v_parser);
http://www.oracle-base.com/articles/8i/parse-xml-documents-8i.php
#10: NULL datatype conversion
SELECT null, null, null FROM dual UNION ALL SELECT 'abc', 123, DATE '2012-01-01' FROM dual;
ORA-01790: expression must have same datatype as corresponding expression ?
#10: NULL datatype conversion SELECT null, null, null FROM dual UNION ALL SELECT 'abc', 123, DATE '2012-01-01' FROM dual; SELECT null, TO_NUMBER(null), TO_DATE(null) FROM dual UNION ALL SELECT 'abc', 123, DATE '2012-01-01' FROM dual;
vs.
#9: MERGE MERGE INTO d USING (SELECT * FROM src) s ON (d.id = s.id) WHEN MATCHED THEN UPDATE d.a = s.a, d.b = s.b WHERE s.a = 'x' DELETE WHERE s.a = 'z' WHEN NOT MATCHED THEN INSERT (s.id, s.a, s.b) WHERE s.b = 'y';
WHEN MATCHED and WHEN NOT MATCHED are optional* * DELETE WHERE must be part of a WHEN MATCHED clause, however
#9: MERGE MERGE INTO d USING (SELECT * FROM src) s ON (d.id = s.id) WHEN MATCHED THEN UPDATE d.a = s.a, d.b = s.b WHERE s.a = 'x' DELETE WHERE s.a = 'z' WHEN NOT MATCHED THEN INSERT (s.id, s.a, s.b) WHERE s.b = 'y';
WHEN MATCHED and WHEN NOT MATCHED are mandatory
#9: MERGE MERGE INTO d USING (SELECT * FROM src) s ON (d.id = s.id) WHEN MATCHED THEN UPDATE d.a = s.a, d.b = s.b WHEN NOT MATCHED THEN INSERT (s.id, s.a, s.b); FOR s IN (SELECT * FROM src) LOOP UPDATE d SET d.a = s.a, d.b = s.b WHERE d.id = s.id; IF SQL%ROWCOUNT = 0 THEN INSERT INTO d VALUES (s.id, s.a, s.b); END IF; END LOOP;
#8: FORALL on sparse array
FORALL i IN INDICES OF arr INSERT INTO t (arr(i));
#8: FORALL on sparse array
FORALL i IN INDICES OF arr INSERT INTO t (arr(i));
un-sparse that array, then…
FORALL i IN 1..arr.COUNT INSERT INTO t (arr(i));
#7: UTL_MAIL
#7: UTL_SMTP
#6: string literals
v_sql := q'[SELECT q'{She said 'Hello'.}' FROM t]';
#6: string literals
v_sql := q'[SELECT q'{She said 'Hello'.}' FROM t]';
single-quotes-masquerading-as-double-quotes hell…
v_sql := 'SELECT ''She said ''''Hello''''.'' FROM t';
#5: Regular Expressions
• REGEXP_INSTR
• REGEXP_REPLACE
• REGEXP_SUBSTR
#5: Regular Expressions
• Try this homegrown solution: http://phil-sqltips.blogspot.com.au/2009/06/regexpreplace-regexplike-for-oracle-9i.html
• Or just do it old-school – INSTR, SUBSTR, LIKE, TRANSLATE, etc.
#4: PLS_INTEGER vs. BINARY_INTEGER
PLS_INTEGER = BINARY_INTEGER
#4: PLS_INTEGER vs. BINARY_INTEGER
• PLS_INTEGER uses native arithmetic = faster
• PLS_INTEGER - overflow exception
• BINARY_INTEGER overflow - no overflow exception*
* If a 9i BINARY_INTEGER operation overflows, no exception is raised if the result is being assigned to a NUMBER. In 10g, this is not true – PLS_INTEGER and BINARY_INTEGER are identical, both raise an exception on overflow.
#3: DBMS_OUTPUT
Max size: unlimited
Line size: 32KB
#3: DBMS_OUTPUT
Max size: 1 million bytes*
Line size: 255 bytes
*default = 20,000 bytes
#2, #1, #0
• no PL/SQL conditional compilation
• no Recycle Bin for dropped tables
• no flashback table*
*NOTE: in my original presentation I claimed “no flashback query” in 9i, but this is incorrect. (Thanks to Tom Kyte for the correction!)
Moral of the story?
• Use appropriate features when available
• Be professional
• Keep old Oracle documentation URLs
Images Attribution
http://4.bp.blogspot.com/-ib6RKHzuEaU/Tb4aaXaq-YI/AAAAAAAANVk/s5RPjflt4hU/s1600/cadillac-car-wreck.jpg
http://images.brisbanetimes.com.au/2012/03/08/3109605/Women%20vote.jpg
http://i47.photobucket.com/albums/f189/captjeremy/ace_ventura_pet_detective_fake_pict.jpg
http://rlv.zcache.com/vintage_business_mailman_mail_carrier_delivering_postcard-p239921576489667584envli_400.jpg
http://technology.amis.nl/2006/04/04/back-to-the-future-oracle-41-vm-appliance/
Thank you
http://jeffkemponoracle.com