Oracle PL/SQL/PL SQL/Utility Package
Содержание
Debug package
<source lang="sql">
SQL> SQL> CREATE OR REPLACE PACKAGE Debug AS
2 PROCEDURE Debug(p_Description IN VARCHAR2, 3 p_Value IN VARCHAR2); 4 5 PROCEDURE Reset; 6 END Debug; 7 /
Package created. SQL> SQL> CREATE OR REPLACE PACKAGE BODY Debug AS
2 PROCEDURE Debug(p_Description IN VARCHAR2, 3 p_Value IN VARCHAR2) IS 4 BEGIN 5 DBMS_OUTPUT.PUT_LINE(p_Description || ": " || p_Value); 6 END Debug; 7 8 PROCEDURE Reset IS 9 BEGIN 10 DBMS_OUTPUT.DISABLE; 11 DBMS_OUTPUT.ENABLE(1000000); 12 END Reset; 13 BEGIN /* Package initialization code */ 14 Reset; 15 END Debug; 16 /
Package body created. SQL> SQL> SQL>
</source>
Debug package based on UTL_FILE
<source lang="sql">
CREATE OR REPLACE PACKAGE Debug AS
v_DebugDir VARCHAR2(50); v_DebugFile VARCHAR2(20); PROCEDURE Debug(p_Description IN VARCHAR2, p_Value IN VARCHAR2); PROCEDURE Reset(p_NewFile IN VARCHAR2 := v_DebugFile, p_NewDir IN VARCHAR2 := v_DebugDir) ; PROCEDURE Close;
END Debug; / CREATE OR REPLACE PACKAGE BODY Debug AS
v_DebugHandle UTL_FILE.FILE_TYPE; PROCEDURE Debug(p_Description IN VARCHAR2,p_Value IN VARCHAR2) IS BEGIN UTL_FILE.PUTF(v_DebugHandle, "%s: %s\n", p_Description, p_Value); UTL_FILE.FFLUSH(v_DebugHandle); EXCEPTION WHEN UTL_FILE.INVALID_OPERATION THEN RAISE_APPLICATION_ERROR(-20102, "Debug: Invalid Operation"); WHEN UTL_FILE.INVALID_FILEHANDLE THEN RAISE_APPLICATION_ERROR(-20103, "Debug: Invalid File Handle"); WHEN UTL_FILE.WRITE_ERROR THEN RAISE_APPLICATION_ERROR(-20104, "Debug: Write Error"); END Debug; PROCEDURE Reset(p_NewFile IN VARCHAR2 := v_DebugFile, p_NewDir IN VARCHAR2 := v_DebugDir) IS BEGIN IF UTL_FILE.IS_OPEN(v_DebugHandle) THEN UTL_FILE.FCLOSE(v_DebugHandle); END IF; v_DebugHandle := UTL_FILE.FOPEN(p_NewDir, p_NewFile, "w"); v_DebugFile := p_NewFile; v_DebugDir := p_NewDir; EXCEPTION WHEN UTL_FILE.INVALID_PATH THEN RAISE_APPLICATION_ERROR(-20100, "Reset: Invalid Path"); WHEN UTL_FILE.INVALID_MODE THEN RAISE_APPLICATION_ERROR(-20101, "Reset: Invalid Mode"); WHEN UTL_FILE.INVALID_OPERATION THEN RAISE_APPLICATION_ERROR(-20101, "Reset: Invalid Operation"); END Reset; PROCEDURE Close IS BEGIN UTL_FILE.FCLOSE(v_DebugHandle); END Close;
BEGIN
v_DebugDir := "/tmp"; v_DebugFile := "debug.out"; Reset;
END Debug; / show error
</source>
Debug package: inserts into a test table
<source lang="sql">
SQL> SQL> CREATE TABLE debug_table (
2 linecount NUMBER PRIMARY KEY, 3 debug_str VARCHAR2(200));
SQL> SQL> SQL> CREATE OR REPLACE PACKAGE Debug AS
2 PROCEDURE Debug(p_Description IN VARCHAR2, p_Value IN VARCHAR2); 3 4 PROCEDURE Reset; 5 END Debug; 6 /
Package created. SQL> SQL> CREATE OR REPLACE PACKAGE BODY Debug AS
2 v_LineCount NUMBER; 3 4 PROCEDURE Debug(p_Description IN VARCHAR2, p_Value IN VARCHAR2) IS 5 BEGIN 6 INSERT INTO debug_table (linecount, debug_str) 7 VALUES (v_LineCount, p_Description || ": " || p_Value); 8 COMMIT; 9 v_LineCount := v_LineCount + 1; 10 END Debug; 11 12 PROCEDURE Reset IS 13 BEGIN 14 v_LineCount := 1; 15 DELETE FROM debug_table; 16 END Reset; 17 18 BEGIN 19 Reset; 20 END Debug; 21 /
Package body created. SQL> SQL> drop table debug_table; Table dropped. SQL> SQL>
</source>
Debug package: uses DBMS_OUTPUT.
<source lang="sql">
SQL> SQL> CREATE TABLE debug_table (
2 linecount NUMBER PRIMARY KEY, 3 debug_str VARCHAR2(200));
Table created. SQL> SQL> SQL> CREATE OR REPLACE PACKAGE Debug AS
2 PROCEDURE Debug(p_Description IN VARCHAR2, p_Value IN VARCHAR2); 3 4 PROCEDURE Reset; 5 END Debug; 6 /
Package created. SQL> SQL> SQL> CREATE OR REPLACE PACKAGE BODY Debug AS
2 PROCEDURE Debug(p_Description IN VARCHAR2, 3 p_Value IN VARCHAR2) IS 4 BEGIN 5 DBMS_OUTPUT.PUT_LINE(p_Description || ": " || p_Value); 6 END Debug; 7 8 PROCEDURE Reset IS 9 BEGIN 10 DBMS_OUTPUT.DISABLE; 11 DBMS_OUTPUT.ENABLE(1000000); 12 END Reset; 13 14 BEGIN 15 Reset; 16 END Debug; 17 /
Package body created. SQL> SQL>
</source>
stop_watch
<source lang="sql">
SQL> SQL> CREATE OR REPLACE PACKAGE stop_watch AS
2 pv_start_time_num PLS_INTEGER; 3 pv_stop_time_num PLS_INTEGER; 4 pv_last_stop_time_num PLS_INTEGER; 5 PROCEDURE start_timer; 6 PROCEDURE stop_timer; 7 END stop_watch; 8 /
Package created. SQL> CREATE OR REPLACE PACKAGE BODY stop_watch AS
2 PROCEDURE start_timer AS 3 BEGIN 4 pv_start_time_num := DBMS_UTILITY.GET_TIME; 5 pv_last_stop_time_num := pv_start_time_num; 6 END start_timer; 7 8 PROCEDURE stop_timer AS 9 BEGIN 10 pv_stop_time_num := DBMS_UTILITY.GET_TIME; 11 DBMS_OUTPUT.PUT_LINE("Total Time Elapsed: " || 12 TO_CHAR((pv_stop_time_num - pv_start_time_num)/100, 13 "999,999.99") || " sec Interval Time: " || 14 TO_CHAR((pv_stop_time_num - pv_last_stop_time_num)/100, 15 "99,999.99") || " sec"); 16 pv_last_stop_time_num := pv_stop_time_num; 17 END stop_timer; 18 END; 19 /
Package body created. SQL> SQL> CREATE OR REPLACE PROCEDURE test_if (p_condition_num NUMBER) AS
2 lv_temp_num NUMBER := 0; 3 lv_temp_cond_num NUMBER := p_condition_num; 4 BEGIN 5 stop_watch.start_timer; 6 FOR lv_count_num IN 1..1000 LOOP 7 IF lv_temp_cond_num = 1 THEN 8 lv_temp_num := lv_temp_num + 1; 9 ELSIF lv_temp_cond_num = 2 THEN 10 lv_temp_num := lv_temp_num + 1; 11 ELSIF lv_temp_cond_num = 3 THEN 12 lv_temp_num := lv_temp_num + 1; 13 ELSIF lv_temp_cond_num = 4 THEN 14 lv_temp_num := lv_temp_num + 1; 15 ELSIF lv_temp_cond_num = 5 THEN 16 lv_temp_num := lv_temp_num + 1; 17 ELSIF lv_temp_cond_num = 6 THEN 18 lv_temp_num := lv_temp_num + 1; 19 ELSIF lv_temp_cond_num = 7 THEN 20 lv_temp_num := lv_temp_num + 1; 21 ELSE 22 lv_temp_num := lv_temp_num + 1; 23 END IF; 24 END LOOP; 25 stop_watch.stop_timer; 26 END; 27 /
Procedure created. SQL> SQL> SQL> SQL> SQL> SQL>
</source>
This object type represents a point on a Cartesian grid.
<source lang="sql">
SQL> SQL> CREATE OR REPLACE TYPE Point AS OBJECT (
2 x NUMBER, 3 y NUMBER, 4 5 MEMBER FUNCTION ToString RETURN VARCHAR2, 6 PRAGMA RESTRICT_REFERENCES(ToString, RNDS, WNDS, RNPS, WNPS), 7 8 MEMBER FUNCTION Distance(p IN Point DEFAULT Point(0,0)) 9 RETURN NUMBER, 10 PRAGMA RESTRICT_REFERENCES(Distance, RNDS, WNDS, RNPS, WNPS), 11 12 MEMBER FUNCTION Plus(p IN Point) RETURN Point, 13 PRAGMA RESTRICT_REFERENCES(Plus, RNDS, WNDS, RNPS, WNPS), 14 15 MEMBER FUNCTION Times(n IN NUMBER) RETURN Point, 16 PRAGMA RESTRICT_REFERENCES(Times, RNDS, WNDS, RNPS, WNPS) 17 ); 18 /
Type created. SQL> show errors No errors. SQL> SQL> CREATE OR REPLACE TYPE BODY Point AS
2 MEMBER FUNCTION ToString RETURN VARCHAR2 IS 3 myResult VARCHAR2(20); 4 v_xString VARCHAR2(8) := SUBSTR(TO_CHAR(x), 1, 8); 5 v_yString VARCHAR2(8) := SUBSTR(TO_CHAR(y), 1, 8); 6 BEGIN 7 myResult := "(" || v_xString || ", "; 8 myResult := myResult || v_yString || ")"; 9 RETURN myResult; 10 END ToString; 11 12 MEMBER FUNCTION Distance(p IN Point DEFAULT Point(0,0)) 13 RETURN NUMBER IS 14 BEGIN 15 RETURN SQRT(POWER(x - p.x, 2) + POWER(y - p.y, 2)); 16 END Distance; 17 18 MEMBER FUNCTION Plus(p IN Point) RETURN Point IS 19 myResult Point; 20 BEGIN 21 myResult := Point(x + p.x, y + p.y); 22 RETURN myResult; 23 END Plus; 24 25 MEMBER FUNCTION Times(n IN NUMBER) RETURN Point IS 26 myResult Point; 27 BEGIN 28 myResult := Point(x * n, y * n); 29 RETURN myResult; 30 END Times; 31 END; 32 /
Type body created. SQL> show errors No errors. SQL> SQL> set serveroutput on SQL> SQL> DECLARE
2 v_Point1 Point := Point(1, 2); 3 v_Point2 Point; 4 v_Point3 Point; 5 BEGIN 6 v_Point2 := v_Point1.Times(4); 7 v_Point3 := v_Point1.Plus(v_Point2); 8 DBMS_OUTPUT.PUT_LINE("Point 2: " || v_Point2.ToString); 9 DBMS_OUTPUT.PUT_LINE("Point 3: " || v_Point3.ToString); 10 DBMS_OUTPUT.PUT_LINE("Distance between origin and point 1: " || 11 v_Point1.Distance); 12 DBMS_OUTPUT.PUT_LINE("Distance between point 1 and point 2: " || 13 v_Point1.Distance(v_Point2)); 14 END; 15 /
Point 2: (4, 8) Point 3: (5, 10) Distance between origin and point 1: 2.23 Distance between point 1 and point 2: 6.70 PL/SQL procedure successfully completed. SQL>
</source>
time the performance enhancements of native dynamic SQL.
<source lang="sql">
SQL> SQL> set serveroutput on SQL> SQL> CREATE OR REPLACE PACKAGE Timing AS
2 PROCEDURE StartTiming; 3 PROCEDURE StopTiming; 4 PROCEDURE PrintElapsed(p_Message IN VARCHAR2); 5 END Timing; 6 /
Package created. SQL> SQL> CREATE OR REPLACE PACKAGE BODY Timing AS
2 v_StartTime NUMBER; 3 v_EndTime NUMBER; 4 5 PROCEDURE StartTiming IS 6 BEGIN 7 v_StartTime := DBMS_UTILITY.GET_TIME; 8 END StartTiming; 9 10 PROCEDURE StopTiming IS 11 BEGIN 12 v_EndTime := DBMS_UTILITY.GET_TIME; 13 END StopTiming; 14 15 PROCEDURE PrintElapsed(p_Message IN VARCHAR2) IS 16 v_Elapsed NUMBER := (v_EndTime - v_StartTime) / 100; 17 BEGIN 18 DBMS_OUTPUT.PUT_LINE( 19 "Elapsed Time for " || p_Message || " is " || 20 v_Elapsed || " seconds."); 21 END PrintElapsed; 22 END Timing; 23 /
Package body created. SQL> SQL> SQL> SQL> CREATE TABLE MyTable (
2 num_col NUMBER, 3 char_col VARCHAR2(60) 4 );
Table created. SQL> SQL> SQL> TRUNCATE TABLE MyTable; Table truncated. SQL> SQL> DECLARE
2 v_CursorID INTEGER; 3 v_Dummy NUMBER; 4 v_SQLStatement VARCHAR2(100) := "INSERT INTO MyTable (num_col) VALUES (:num)"; 5 6 c_NumRows CONSTANT NUMBER := 5000; 7 BEGIN 8 DELETE FROM MyTable; 9 COMMIT; 10 11 Timing.StartTiming; 12 v_CursorID := DBMS_SQL.OPEN_CURSOR; 13 14 FOR v_Count IN 1..c_NumRows LOOP 15 DBMS_SQL.PARSE(v_CursorID, v_SQLStatement, DBMS_SQL.NATIVE); 16 DBMS_SQL.BIND_VARIABLE(v_CursorID, ":num", v_Count); 17 v_Dummy := DBMS_SQL.EXECUTE(v_CursorID); 18 END LOOP; 19 20 DBMS_SQL.CLOSE_CURSOR(v_CursorID); 21 22 Timing.StopTiming; 23 Timing.PrintElapsed("DBMS_SQL"); 24 25 DELETE FROM MyTable; 26 COMMIT; 27 28 Timing.StartTiming; 29 FOR v_Count IN 1..c_NumRows LOOP 30 EXECUTE IMMEDIATE v_SQLStatement USING v_Count; 31 END LOOP; 32 Timing.StopTiming; 33 Timing.PrintElapsed("Native Dynamic SQL"); 34 END; 35 /
Elapsed Time for DBMS_SQL is 1.04 seconds. Elapsed Time for Native Dynamic SQL is .52 seconds. PL/SQL procedure successfully completed. SQL> SQL> SQL> drop table MyTable; Table dropped. SQL>
</source>