SlideShare a Scribd company logo
1 of 32
Beyond Basic Datatypes SQL Objects and PL/SQL
Who am I ? Gary Myers Oracle developer since 1994  Database Consultant with SMS M&T Blogger since 2004 Now at blog.sydoracle.com Twitter at syd_oracle Guest editor at Log Buffer "Oracle" badge at Stackoverflow forums  Find me at LinkedIn…
What is PL/SQL PL/SQL is an EXTENSION to SQL PL/SQL is procedural Closely tied to the database Runs under the oracle shadow process Mostly in the PGA  BEWARE Shared Server (eg APEX)
PL/SQL Datatypes As an extension, PL/SQL recognizes all SQL datatypes (except LONG) That includes user-defined datatypes User-defined datatypes includes Oracle supplied ones such as Spatial (MDSYS) and Multimedia (ORDSYS).
PL/SQL specific datatypes Boolean, PLS_INTEGER etc Only within PL/SQL Cannot be used to ‘talk’ to SQL. Avoid as function parameters Some potential for better performance and/or memory consumption
PL/SQL Record Types CREATE PROCEDURE TEST   TYPE typ_rec is RECORD    (id  NUMBER, val VARCHAR2(20)); t_rec1 typ_rec;  t_rec2 typ_rec; BEGIN t_rec1.id  := 5; t_rec1.val := 'TEST';  t_rec2 := t_rec1; t_rec1 := null; END;
SQL Object Type CREATE TYPE typ_rec is OBJECT     (id NUMBER, val VARCHAR2(20)); / SELECT typ_rec(1,’test’) FROM DUAL;
Constructor Methods CREATE TYPE holt AS OBJECT 	      (record_type varchar2(1), record_column varchar2(10) ,   CONSTRUCTOR FUNCTION holt  ( i_record_type in varchar2 default null, i_record_column in varchar2 default null)     return self as result);
Constructor Method Body CREATE OR REPLACE TYPE body holt is   CONSTRUCTOR FUNCTION holt   (i_record_type  in varchar2 default null, i_record_column in varchar2 default null)     return self as result is 	   begin self.record_type    := i_record_type; self.record_column  :=  i_record_column;     RETURN;   end holt; end;
PL/SQL using  SQL Type declare v_holt   holt; begin v_holt := holt( i_record_type => 'a',  i_record_column => 'B'); end; /
PL/SQL Collection Types CREATE PROCEDURE TEST   TYPE typ_coll_vc10 is TABLE    OF VARCHAR2(10) INDEX BY PLS_INTEGER; tc_val typ_coll_vc10; BEGIN tc_val(1) := 'TEST'; END;
SQL Collection Types SQL Collection types cannot have member functions. They do have functionality equivalent to a default constructor though You can create an object that includes a collection
SQL collection as Table You can select from a collection using the syntax SELECT column_value from TABLE(   tab_varchar_4000( 'a','b','c'));
FREE  There's a default collection type in the database, granted to public SYS.DBMS_DEBUG_VC2COLL select * from   table(sys.dbms_debug_vc2coll             ('a','b','c'))
Functions returning collections CREATE FUNCTION gen_dates  (i_start in date, i_end in date)  RETURN tab_varchar_4000 IS v_tab tab_varchar_4000 :=                   tab_varchar_4000(); BEGIN v_tab.extend(1 + i_end - i_start ); FOR i in 0..( i_end - i_start ) LOOP v_tab(i+1) := i_start + i; END LOOP;   RETURN v_tab; END;
Pipelined functions CREATE FUNCTION gen_dates RETURNtab_varchar_4000 PIPELINED IS CURSOR c_1 is     select sysdatedt from dual      connect by level < 100; BEGIN FORi in c_1 LOOP PIPE ROW(to_char(i.dt)); END LOOP; RETURN; END;
Wouldn't it be nice…. procedure p_test is Begin dbms_output.put_line('point 1');   . . . dbms_output.put_line('point 2');   . . . End;
Does not allow DML Function p_test return tab_varchar_4000 pipelined is Begin   pipe row('point 1');   update….   pipe row('point 2'); End;
Must be at the top level Procedure process_records is  procedure debug (p_text in varchar2) is   begin     pipe row (p_text);   end; Begin  . . . End;
Warning – No Data Found TABLE() functions complete with a NO_DATA_FOUND
It gets worse Non-existent collection elements also return a no_data_found
Pipelined Functions and PL/SQL Collections A PL/SQL collection type can also be used in a pipelined function It implicitly creates three SQL level-types (starting with SYS_PLSQL_object_id) These types can be amended with ALTER TYPE (but that's not a good idea)
INDEX BY VARCHAR2 Added in 9iR2 Allows a degree of caching in PL/SQL Useful if you have an expensive calculation that you can reuse (much like the function result cache in 11g).
SQL collection operators COLLECT will aggregate up a set of data items into an on-the-fly collection select collect('test')  from dual connect by level < 10; You can CAST that collection to your own collection type, if compatible.  Beware of CHAR / VARCHAR2 incompatibilities
Like any Aggregate Function DISTINCT select collect(distinct  to_char(sysdate))  from dual connect by level < 5; GROUP BY select cast(collect(object_name) as           tab_varchar_4000) t  from user_objects group by object_type;
Collections and Sets Definition : A collection is a set if it doesn't have duplicates
SET testing select 1 a from dual  where mset('a','b','a') is a set; no rows selected select 1 a from dual  where mset('a','b') is a set;          A ----------          1
MULTISET operators Turn a collection into a set.  select mset('z','a','a','c','d','c') multiset union distinct mset()  from dual; There are also INTERSECT and EXCEPT (not MINUS)
SET comparison select 1 from dual  where 'a' member mset('a','b'); 1 select 1 from dual  where mset('a') submultisetmset('a','b'); 1 select 1 a from dual  where mset('a','c') submultisetmset('a','b'); no rows selected
Collection comparison You can compare simple collections  in PL/SQL with an equals operator declare   x1 mset := mset('a','b');   x2 mset := mset('b','a'); begin   if x1 = x2 then dbms_output.put_line('Match');   end if; end;
Multiset operators in PL/SQL declare   x1 mset := mset('a','b');   x2 mset := mset('b');   x3 mset; begin   x3 := x1 multiset except x2; dbms_output.put_line(x3.count         ||  '.'||x3(1)); end;
Final Thought For complex logic SQL*Plus embedded in shell scripts is      NOT a good idea

More Related Content

What's hot

Ddl &amp; dml commands
Ddl &amp; dml commandsDdl &amp; dml commands
Ddl &amp; dml commandsAnjaliJain167
 
5. stored procedure and functions
5. stored procedure and functions5. stored procedure and functions
5. stored procedure and functionsAmrit Kaur
 
SQL Server Learning Drive
SQL Server Learning Drive SQL Server Learning Drive
SQL Server Learning Drive TechandMate
 
MySQL Tutorial For Beginners | Relational Database Management System | MySQL ...
MySQL Tutorial For Beginners | Relational Database Management System | MySQL ...MySQL Tutorial For Beginners | Relational Database Management System | MySQL ...
MySQL Tutorial For Beginners | Relational Database Management System | MySQL ...Edureka!
 
pl/sql Procedure
pl/sql Procedurepl/sql Procedure
pl/sql ProcedurePooja Dixit
 
Oracle pl/sql control statments
Oracle pl/sql control statmentsOracle pl/sql control statments
Oracle pl/sql control statmentsTayba Bashir
 
Procedure and Functions in pl/sql
Procedure and Functions in pl/sqlProcedure and Functions in pl/sql
Procedure and Functions in pl/sqlÑirmal Tatiwal
 
introdution to SQL and SQL functions
introdution to SQL and SQL functionsintrodution to SQL and SQL functions
introdution to SQL and SQL functionsfarwa waqar
 

What's hot (20)

SQL
SQLSQL
SQL
 
Plsql lab mannual
Plsql lab mannualPlsql lab mannual
Plsql lab mannual
 
Ddl &amp; dml commands
Ddl &amp; dml commandsDdl &amp; dml commands
Ddl &amp; dml commands
 
MYSQL
MYSQLMYSQL
MYSQL
 
Chapter 4 Structured Query Language
Chapter 4 Structured Query LanguageChapter 4 Structured Query Language
Chapter 4 Structured Query Language
 
5. stored procedure and functions
5. stored procedure and functions5. stored procedure and functions
5. stored procedure and functions
 
SQL Server Learning Drive
SQL Server Learning Drive SQL Server Learning Drive
SQL Server Learning Drive
 
SQL
SQLSQL
SQL
 
MySQL Tutorial For Beginners | Relational Database Management System | MySQL ...
MySQL Tutorial For Beginners | Relational Database Management System | MySQL ...MySQL Tutorial For Beginners | Relational Database Management System | MySQL ...
MySQL Tutorial For Beginners | Relational Database Management System | MySQL ...
 
SQL commands
SQL commandsSQL commands
SQL commands
 
pl/sql Procedure
pl/sql Procedurepl/sql Procedure
pl/sql Procedure
 
12 SQL
12 SQL12 SQL
12 SQL
 
SQL
SQLSQL
SQL
 
Introduction to-sql
Introduction to-sqlIntroduction to-sql
Introduction to-sql
 
Oracle pl/sql control statments
Oracle pl/sql control statmentsOracle pl/sql control statments
Oracle pl/sql control statments
 
Procedure and Functions in pl/sql
Procedure and Functions in pl/sqlProcedure and Functions in pl/sql
Procedure and Functions in pl/sql
 
SQL(DDL & DML)
SQL(DDL & DML)SQL(DDL & DML)
SQL(DDL & DML)
 
Sql Constraints
Sql ConstraintsSql Constraints
Sql Constraints
 
PL/SQL TRIGGERS
PL/SQL TRIGGERSPL/SQL TRIGGERS
PL/SQL TRIGGERS
 
introdution to SQL and SQL functions
introdution to SQL and SQL functionsintrodution to SQL and SQL functions
introdution to SQL and SQL functions
 

Viewers also liked

Oracle basic queries
Oracle basic queriesOracle basic queries
Oracle basic queriesPRAKHAR JHA
 
Basic MySQL Troubleshooting for Oracle Database Administrators
Basic MySQL Troubleshooting for Oracle Database AdministratorsBasic MySQL Troubleshooting for Oracle Database Administrators
Basic MySQL Troubleshooting for Oracle Database AdministratorsSveta Smirnova
 
Oracle Database Management Basic 1
Oracle Database Management Basic 1Oracle Database Management Basic 1
Oracle Database Management Basic 1Chien Chung Shen
 
Oracle architecture with details-yogiji creations
Oracle architecture with details-yogiji creationsOracle architecture with details-yogiji creations
Oracle architecture with details-yogiji creationsYogiji Creations
 
Introduction to Oracle Database
Introduction to Oracle DatabaseIntroduction to Oracle Database
Introduction to Oracle Databasepuja_dhar
 
Oracle Basics and Architecture
Oracle Basics and ArchitectureOracle Basics and Architecture
Oracle Basics and ArchitectureSidney Chen
 
Sql queries interview questions
Sql queries interview questionsSql queries interview questions
Sql queries interview questionsPyadav010186
 
Best Practices - PHP and the Oracle Database
Best Practices - PHP and the Oracle DatabaseBest Practices - PHP and the Oracle Database
Best Practices - PHP and the Oracle DatabaseChristopher Jones
 
Oracle Database Overview
Oracle Database OverviewOracle Database Overview
Oracle Database Overviewhonglee71
 
Basic oracle for developer&beginner
Basic oracle for developer&beginnerBasic oracle for developer&beginner
Basic oracle for developer&beginnermaclean liu
 
Oracle architecture ppt
Oracle architecture pptOracle architecture ppt
Oracle architecture pptDeepak Shetty
 

Viewers also liked (15)

Oracle basic queries
Oracle basic queriesOracle basic queries
Oracle basic queries
 
Basic Oracle Usage v1
Basic Oracle Usage v1Basic Oracle Usage v1
Basic Oracle Usage v1
 
Basic MySQL Troubleshooting for Oracle Database Administrators
Basic MySQL Troubleshooting for Oracle Database AdministratorsBasic MySQL Troubleshooting for Oracle Database Administrators
Basic MySQL Troubleshooting for Oracle Database Administrators
 
Basic of Oracle Application
Basic of Oracle ApplicationBasic of Oracle Application
Basic of Oracle Application
 
Oracle Database Management Basic 1
Oracle Database Management Basic 1Oracle Database Management Basic 1
Oracle Database Management Basic 1
 
Oracle architecture with details-yogiji creations
Oracle architecture with details-yogiji creationsOracle architecture with details-yogiji creations
Oracle architecture with details-yogiji creations
 
Introduction to Oracle Database
Introduction to Oracle DatabaseIntroduction to Oracle Database
Introduction to Oracle Database
 
Oracle Essentials Oracle Database 11g
Oracle Essentials   Oracle Database 11gOracle Essentials   Oracle Database 11g
Oracle Essentials Oracle Database 11g
 
Oracle Basics and Architecture
Oracle Basics and ArchitectureOracle Basics and Architecture
Oracle Basics and Architecture
 
Sql queries interview questions
Sql queries interview questionsSql queries interview questions
Sql queries interview questions
 
Oracle: Basic SQL
Oracle: Basic SQLOracle: Basic SQL
Oracle: Basic SQL
 
Best Practices - PHP and the Oracle Database
Best Practices - PHP and the Oracle DatabaseBest Practices - PHP and the Oracle Database
Best Practices - PHP and the Oracle Database
 
Oracle Database Overview
Oracle Database OverviewOracle Database Overview
Oracle Database Overview
 
Basic oracle for developer&beginner
Basic oracle for developer&beginnerBasic oracle for developer&beginner
Basic oracle for developer&beginner
 
Oracle architecture ppt
Oracle architecture pptOracle architecture ppt
Oracle architecture ppt
 

Similar to Beyond Basic Datatypes: SQL Objects and PL/SQL

Oracle - Program with PL/SQL - Lession 09
Oracle - Program with PL/SQL - Lession 09Oracle - Program with PL/SQL - Lession 09
Oracle - Program with PL/SQL - Lession 09Thuan Nguyen
 
Oracle Objects And Transactions
Oracle Objects And TransactionsOracle Objects And Transactions
Oracle Objects And Transactionstepsum
 
PLSQLmy Updated (1).pptx
PLSQLmy Updated (1).pptxPLSQLmy Updated (1).pptx
PLSQLmy Updated (1).pptxvamsiyadav39
 
Weird Plsql
Weird PlsqlWeird Plsql
Weird Plsqlwebanddb
 
Plsql coding conventions
Plsql coding conventionsPlsql coding conventions
Plsql coding conventionsFang Yu
 
Exploring collections with example
Exploring collections with exampleExploring collections with example
Exploring collections with examplepranav kumar verma
 
L9 l10 server side programming
L9 l10  server side programmingL9 l10  server side programming
L9 l10 server side programmingRushdi Shams
 
Porting Applications From Oracle To PostgreSQL
Porting Applications From Oracle To PostgreSQLPorting Applications From Oracle To PostgreSQL
Porting Applications From Oracle To PostgreSQLPeter Eisentraut
 
Mysqlppt
MysqlpptMysqlppt
MysqlpptReka
 
PL/SQL Fundamentals I
PL/SQL Fundamentals IPL/SQL Fundamentals I
PL/SQL Fundamentals INick Buytaert
 
DAC training-batch -2020(PLSQL)
DAC training-batch -2020(PLSQL)DAC training-batch -2020(PLSQL)
DAC training-batch -2020(PLSQL)RajKumarSingh213
 
Domain Specific Languages In Scala Duse3
Domain Specific Languages In Scala Duse3Domain Specific Languages In Scala Duse3
Domain Specific Languages In Scala Duse3Peter Maas
 
Tony jambu (obscure) tools of the trade for tuning oracle sq ls
Tony jambu   (obscure) tools of the trade for tuning oracle sq lsTony jambu   (obscure) tools of the trade for tuning oracle sq ls
Tony jambu (obscure) tools of the trade for tuning oracle sq lsInSync Conference
 
Cursors, triggers, procedures
Cursors, triggers, proceduresCursors, triggers, procedures
Cursors, triggers, proceduresVaibhav Kathuria
 

Similar to Beyond Basic Datatypes: SQL Objects and PL/SQL (20)

plsql.ppt
plsql.pptplsql.ppt
plsql.ppt
 
Oracle - Program with PL/SQL - Lession 09
Oracle - Program with PL/SQL - Lession 09Oracle - Program with PL/SQL - Lession 09
Oracle - Program with PL/SQL - Lession 09
 
Oracle Objects And Transactions
Oracle Objects And TransactionsOracle Objects And Transactions
Oracle Objects And Transactions
 
PLSQLmy Updated (1).pptx
PLSQLmy Updated (1).pptxPLSQLmy Updated (1).pptx
PLSQLmy Updated (1).pptx
 
Weird Plsql
Weird PlsqlWeird Plsql
Weird Plsql
 
SQL- Introduction to PL/SQL
SQL- Introduction to  PL/SQLSQL- Introduction to  PL/SQL
SQL- Introduction to PL/SQL
 
Plsql coding conventions
Plsql coding conventionsPlsql coding conventions
Plsql coding conventions
 
PL_SQL - II.pptx
PL_SQL - II.pptxPL_SQL - II.pptx
PL_SQL - II.pptx
 
Plsql
PlsqlPlsql
Plsql
 
Exploring collections with example
Exploring collections with exampleExploring collections with example
Exploring collections with example
 
L9 l10 server side programming
L9 l10  server side programmingL9 l10  server side programming
L9 l10 server side programming
 
Porting Applications From Oracle To PostgreSQL
Porting Applications From Oracle To PostgreSQLPorting Applications From Oracle To PostgreSQL
Porting Applications From Oracle To PostgreSQL
 
PLSQL
PLSQLPLSQL
PLSQL
 
Plsql
PlsqlPlsql
Plsql
 
Mysqlppt
MysqlpptMysqlppt
Mysqlppt
 
PL/SQL Fundamentals I
PL/SQL Fundamentals IPL/SQL Fundamentals I
PL/SQL Fundamentals I
 
DAC training-batch -2020(PLSQL)
DAC training-batch -2020(PLSQL)DAC training-batch -2020(PLSQL)
DAC training-batch -2020(PLSQL)
 
Domain Specific Languages In Scala Duse3
Domain Specific Languages In Scala Duse3Domain Specific Languages In Scala Duse3
Domain Specific Languages In Scala Duse3
 
Tony jambu (obscure) tools of the trade for tuning oracle sq ls
Tony jambu   (obscure) tools of the trade for tuning oracle sq lsTony jambu   (obscure) tools of the trade for tuning oracle sq ls
Tony jambu (obscure) tools of the trade for tuning oracle sq ls
 
Cursors, triggers, procedures
Cursors, triggers, proceduresCursors, triggers, procedures
Cursors, triggers, procedures
 

Beyond Basic Datatypes: SQL Objects and PL/SQL

  • 1. Beyond Basic Datatypes SQL Objects and PL/SQL
  • 2. Who am I ? Gary Myers Oracle developer since 1994 Database Consultant with SMS M&T Blogger since 2004 Now at blog.sydoracle.com Twitter at syd_oracle Guest editor at Log Buffer "Oracle" badge at Stackoverflow forums Find me at LinkedIn…
  • 3. What is PL/SQL PL/SQL is an EXTENSION to SQL PL/SQL is procedural Closely tied to the database Runs under the oracle shadow process Mostly in the PGA BEWARE Shared Server (eg APEX)
  • 4. PL/SQL Datatypes As an extension, PL/SQL recognizes all SQL datatypes (except LONG) That includes user-defined datatypes User-defined datatypes includes Oracle supplied ones such as Spatial (MDSYS) and Multimedia (ORDSYS).
  • 5. PL/SQL specific datatypes Boolean, PLS_INTEGER etc Only within PL/SQL Cannot be used to ‘talk’ to SQL. Avoid as function parameters Some potential for better performance and/or memory consumption
  • 6. PL/SQL Record Types CREATE PROCEDURE TEST TYPE typ_rec is RECORD (id NUMBER, val VARCHAR2(20)); t_rec1 typ_rec; t_rec2 typ_rec; BEGIN t_rec1.id := 5; t_rec1.val := 'TEST'; t_rec2 := t_rec1; t_rec1 := null; END;
  • 7. SQL Object Type CREATE TYPE typ_rec is OBJECT (id NUMBER, val VARCHAR2(20)); / SELECT typ_rec(1,’test’) FROM DUAL;
  • 8. Constructor Methods CREATE TYPE holt AS OBJECT (record_type varchar2(1), record_column varchar2(10) , CONSTRUCTOR FUNCTION holt ( i_record_type in varchar2 default null, i_record_column in varchar2 default null) return self as result);
  • 9. Constructor Method Body CREATE OR REPLACE TYPE body holt is CONSTRUCTOR FUNCTION holt (i_record_type in varchar2 default null, i_record_column in varchar2 default null) return self as result is begin self.record_type := i_record_type; self.record_column := i_record_column; RETURN; end holt; end;
  • 10. PL/SQL using SQL Type declare v_holt holt; begin v_holt := holt( i_record_type => 'a', i_record_column => 'B'); end; /
  • 11. PL/SQL Collection Types CREATE PROCEDURE TEST TYPE typ_coll_vc10 is TABLE OF VARCHAR2(10) INDEX BY PLS_INTEGER; tc_val typ_coll_vc10; BEGIN tc_val(1) := 'TEST'; END;
  • 12. SQL Collection Types SQL Collection types cannot have member functions. They do have functionality equivalent to a default constructor though You can create an object that includes a collection
  • 13. SQL collection as Table You can select from a collection using the syntax SELECT column_value from TABLE( tab_varchar_4000( 'a','b','c'));
  • 14. FREE There's a default collection type in the database, granted to public SYS.DBMS_DEBUG_VC2COLL select * from table(sys.dbms_debug_vc2coll ('a','b','c'))
  • 15. Functions returning collections CREATE FUNCTION gen_dates (i_start in date, i_end in date) RETURN tab_varchar_4000 IS v_tab tab_varchar_4000 := tab_varchar_4000(); BEGIN v_tab.extend(1 + i_end - i_start ); FOR i in 0..( i_end - i_start ) LOOP v_tab(i+1) := i_start + i; END LOOP; RETURN v_tab; END;
  • 16. Pipelined functions CREATE FUNCTION gen_dates RETURNtab_varchar_4000 PIPELINED IS CURSOR c_1 is select sysdatedt from dual connect by level < 100; BEGIN FORi in c_1 LOOP PIPE ROW(to_char(i.dt)); END LOOP; RETURN; END;
  • 17. Wouldn't it be nice…. procedure p_test is Begin dbms_output.put_line('point 1'); . . . dbms_output.put_line('point 2'); . . . End;
  • 18. Does not allow DML Function p_test return tab_varchar_4000 pipelined is Begin pipe row('point 1'); update…. pipe row('point 2'); End;
  • 19. Must be at the top level Procedure process_records is procedure debug (p_text in varchar2) is begin pipe row (p_text); end; Begin . . . End;
  • 20. Warning – No Data Found TABLE() functions complete with a NO_DATA_FOUND
  • 21. It gets worse Non-existent collection elements also return a no_data_found
  • 22. Pipelined Functions and PL/SQL Collections A PL/SQL collection type can also be used in a pipelined function It implicitly creates three SQL level-types (starting with SYS_PLSQL_object_id) These types can be amended with ALTER TYPE (but that's not a good idea)
  • 23. INDEX BY VARCHAR2 Added in 9iR2 Allows a degree of caching in PL/SQL Useful if you have an expensive calculation that you can reuse (much like the function result cache in 11g).
  • 24. SQL collection operators COLLECT will aggregate up a set of data items into an on-the-fly collection select collect('test') from dual connect by level < 10; You can CAST that collection to your own collection type, if compatible. Beware of CHAR / VARCHAR2 incompatibilities
  • 25. Like any Aggregate Function DISTINCT select collect(distinct to_char(sysdate)) from dual connect by level < 5; GROUP BY select cast(collect(object_name) as tab_varchar_4000) t from user_objects group by object_type;
  • 26. Collections and Sets Definition : A collection is a set if it doesn't have duplicates
  • 27. SET testing select 1 a from dual where mset('a','b','a') is a set; no rows selected select 1 a from dual where mset('a','b') is a set; A ---------- 1
  • 28. MULTISET operators Turn a collection into a set. select mset('z','a','a','c','d','c') multiset union distinct mset() from dual; There are also INTERSECT and EXCEPT (not MINUS)
  • 29. SET comparison select 1 from dual where 'a' member mset('a','b'); 1 select 1 from dual where mset('a') submultisetmset('a','b'); 1 select 1 a from dual where mset('a','c') submultisetmset('a','b'); no rows selected
  • 30. Collection comparison You can compare simple collections in PL/SQL with an equals operator declare x1 mset := mset('a','b'); x2 mset := mset('b','a'); begin if x1 = x2 then dbms_output.put_line('Match'); end if; end;
  • 31. Multiset operators in PL/SQL declare x1 mset := mset('a','b'); x2 mset := mset('b'); x3 mset; begin x3 := x1 multiset except x2; dbms_output.put_line(x3.count || '.'||x3(1)); end;
  • 32. Final Thought For complex logic SQL*Plus embedded in shell scripts is NOT a good idea

Editor's Notes

  1. Did a bit of COBOL and IDMS-XThen Ingres for a couple of yearsFound Oracle around the Forms 3 Era, used a lot of Pro*CobolCame to Australia about 12 years ago from England.Forms work in Perth and Adelaide.Arrived in Sydney in ‘99Contracted with the Office of State Revenue, P&amp;O Nedlloyd, MBF Health Insurance…Consultant with DWS for a year, contracted for a bit more.Been consulting with SMS for about 18 monthsCurrently at SiCorp on a very small data warehouse.
  2. SQL is very good at set-based operations.When the task isn’t set based, it is worth considering a procedural approach.Processing of large data volumes are more likely to be amenable to set-based solutions. Because PL/SQL runs in the database, and as the same process performing SQL operations, there is a smaller detrimental impact from context switching than you may get from a client language containing SQL (e.g. Perl, Python )In Shared Server, session persistent data is stored in the UGA which is in the SGA, but data that is only required for the duration of the call may still be in the PGA.
  3. By not requiring a translation between the SQL types and PL/SQL types, any impedance is reduced.
  4. PL/SQL has its own particular datatypes that are geared towards PROCESSING of data, as opposed to STORAGE. Mostly they are beneficial in terms of performance and/or memory consumption.Unless you do heavy processing in PL/SQL, the benefits are likely to be smallPlus they cannot be used in embedded SQL statements, and have to be converted to a standard datatype.
  5. You can have type declarations in PL/SQL which are local to the code block.If declared in a package specification, they can be used more widely, but (generally) only within PL/SQL.You can assign variables of the same type to each other. You can assign NULL to a record type.Comparison isn&apos;t as simple (and don&apos;t forget NULLs in record items when you do comparisons).Sometimes worth creating comparison functions.
  6. An SQL Object type has attributes (a cross between variables and columns) and optionally member functions/proceduresThese can be used in SQL and PL/SQL
  7. Objects come with a default constructor method, where you can create an INSTANCE of the object by stating the object name then, in brackets, values for every one of the attributes. You can create your own constructor functions too. They MUST have the same name as the type, but can differ in their parameters. They can have different numbers of parameters, parameter names, datatypes and default values.I like constructors that have parameters that default to null, so I don&apos;t have to supply them all
  8. To implement the method, you need a BODY, in the same way as a package body. Unlike packages, a type body cannot contain functions not declared in the TYPE specification. [But you can declare private functions / procedures in the declaration part of the member functions.CREATE OR REPLACE TYPE body holt is CONSTRUCTOR FUNCTION holt ( i_record_type in varchar2 default null,i_record_column in varchar2 default null) return self as result isv_number number; procedure p_test is beginv_number := 1; end; beginself.record_type := i_record_type;self.record_column := i_record_column; RETURN; end holt;end;
  9. You can use user-defined types as easily as the built-in types.
  10. A collection type, in PL/SQL, can be of an ARRAY or TABLE. I find tables more useful as I don’t need to consider size when I declare them. A collection is of a single data type. However that datatype may be a simple SQL datatype [such as NUMBER or VARCHAR2(n)], a user-defined SQL datatype (such as a Spatial co-ordinate)) a PL/SQL type such as PLS_INTEGER or a user-defined PL/SQL record type. You can even define collections of collections, though that would get complicated.
  11. So you can have a collection like CREATE TYPE tab_varchar_4000 IS TABLE OF VARCHAR2(4000);CREATE TYPE strings_coll IS OBJECT (coll tab_varchar_4000);
  12. You are limited to a default constructor if you use the type directly.
  13. There&apos;s no public synonym for it, so you need to use the SYS schema declaration
  14. You need to initialize the collection.Then extend it to the size necessary.Load up the rows and return it.You can then just select from itselect * from table(gen_dates(sysdate, sysdate+10));
  15. Pipelined functions don&apos;t need to assemble the whole dataset into memory before returning it.You MUST have the RETURN at the end, and it returns nothing.
  16. You&apos;ve probably seen code like this. Lots of debug statements to report on what the code is doing.Or rather what the code has done, as dbms_output doesn&apos;t get reported until the end.Can we use PIPE ROW to report on debugging during processing ?
  17. You don&apos;t want to try wrapping it all up in autonomous transactions and ugly stuff like that
  18. You&apos;ve probably seen code like this. Lots of debug statements to report on what the code is doing.Or rather what the code has done, as dbms_output doesn&apos;t get reported until the end.Can we use PIPE ROW to report on debugging during processing ?The PIPE ROW has to be in the top level (ie can&apos;t be delegated to a called subroutine).create function process_records return tab_varchar_4000 pipelined isv_str varchar2(10); procedure put (p_text in varchar2) is begin pipe row (p_text); end;begin for i in 1 .. 10 loop select id into v_str from recs where id = i; put (&apos;update &apos;||i); end loop; return;end;/PLS-00629: PIPE statement cannot be used in non-pipelined functions
  19. Warning - NO_DATA_FOUND is a PL/SQL exceptionIt is NOT an SQL error.When you select from a function returning a table, if the PL/SQL encounters an unhandled NO_DATA_FOUND exception, it acts like a RETURN. The function ends, and as far as the SQL is concerned, it completed successfully.create function gen_nums return tab_varchar_4000 pipelinedis cursor c_1 is select rownumrn from dual connect by level &lt; 10;v_num number;begin for i in c_1 loop select 1 into v_num from dual where i.rn &lt; 3; pipe row (i.rn); end loop; return;end;/select * from table(gen_nums);Only returns 2 rows.ALWAYS use a NO_DATA_FOUND exception handler and raise it as a different error.drop function gen_nums;create function gen_nums return tab_varchar_4000 pipelinedis cursor c_1 is select rownumrn from dual connect by level &lt; 10;v_num number;begin for i in c_1 loop select 1 into v_num from dual where i.rn &lt; 3; pipe row (i.rn); end loop; return;exception when no_data_found thenraise_application_error(-20001,&apos;NDF&apos;,false);end;/select * from table(gen_nums);
  20. drop function gen_char;create function gen_char return tab_varchar_4000 pipelinedis type tab_val is table of varchar2(10) index by pls_integer;t_valtab_val;begint_val(1) := &apos;test 1&apos;;t_val(10) := &apos;test 10&apos;; pipe row (t_val(10)); pipe row (t_val(5)); pipe row (t_val(1)); return;--exception-- when no_data_found then-- raise_application_error(-20001,&apos;NDF&apos;,false);end;/select * from table(gen_char);
  21. create or replace package test_pipe_pkg is type rec_pipe is record (id number, val varchar2(20)); type tab_pipe is table of rec_pipe; function ret_pipe return tab_pipe pipelined;end;/create or replace package body test_pipe_pkg is function ret_pipe return tab_pipe pipelined isv_recrec_pipe; begin v_rec.id := 1; v_rec.val := &apos;test&apos;; pipe row (v_rec); return; end;end;/select * from table(test_pipe_pkg.ret_pipe);select type_name from user_types where type_name like &apos;SYS_PLSQL%&apos;;alter type &quot;GARY&quot;.&quot;SYS_PLSQL_13672_9_1&quot; add attribute gid number;
  22. create table t_sub_postcodes (postcode varchar2(4), suburb_name varchar2(20));insert into t_sub_postcodes values (&apos;2000&apos;,&apos;Sydney&apos;);insert into t_sub_postcodes values (&apos;3000&apos;,&apos;Melbourne&apos;);create or replace procedure demo_cache is type tab_postcode is table of varchar2(4) index by varchar2(40);t_postcodetab_postcode; cursor c_1 is select decode(mod(rownum,2),1,&apos;Sydney&apos;,&apos;Melbourne&apos;) sub from dual connect by level &lt;10; function get_postcode (i_suburb in varchar2) return varchar2 isv_postcode varchar2(4); begin if t_postcode.exists (i_suburb) then return t_postcode(i_suburb); elsedbms_output.put_line(&apos;Fetching&apos;); select postcode into v_postcode from t_sub_postcodes where suburb_name = i_suburb;t_postcode(i_suburb) := v_postcode; return t_postcode(i_suburb); end if; end;begin for c_rec in c_1 loopdbms_output.put_line(get_postcode(c_rec.sub)); end loop; end;/show errors procedure demo_cacheexec demo_cache;
  23. create table test (val varchar2(10));insert into test select sysdate+level from dual connect by level &lt; 10;select cast(collect(val) as tab_varchar_4000) a from test;
  24. create type mset is table of varchar2(4000);/create type mset_mset is table of mset;/
  25. create type mset is table of varchar2(4000);/create type mset_mset is table of mset;/
  26. First one checks if an ELEMENT is in the setSecond/third ones check if a set is contained within a set
  27. set serveroutput on declare x1 tab_varchar_4000; x2 tab_varchar_4000;begin select cast(collect(to_char(sysdate)) as tab_varchar_4000) into x1 from dual connect by level &lt; 10; -- select cast(collect(to_char(sysdate)) as tab_varchar_4000) into x2 from dual connect by level &lt; 5; -- if x1 = x2 thendbms_output.put_line(&apos;Match&apos;); --elsif x1 &lt; x2 then -- dbms_output.put_line(&apos;Less&apos;); elsedbms_output.put_line(&apos;No Match&apos;); end if;end;./
  28. Also works with locally defined collectionsdeclare TYPE lset is table of varchar2(30); x1 lset := lset(&apos;a&apos;,&apos;b&apos;); x2 lset := lset(&apos;b&apos;); x3 lset;begin x3 := x1 multiset except x2;dbms_output.put_line(x3.count||&apos;.&apos;||x3(1));end;But not complex ones (SQL or PL/SQL)declare TYPE lrc is record (id number, val varchar2(10)); TYPE lset is table of lrc; x1 lset; x2 lset; x3 lset; function x (p_id in number, p_val in varchar2) return lrc isv_xlrc; begin v_x.id := p_id; v_x.val := p_val; return v_x; end;begin x1 := lset(x(1,&apos;a&apos;), x(2,&apos;b&apos;)); x2 := lset(x(2,&apos;b&apos;)); x3 := x1 multiset except x2;dbms_output.put_line(x3.count);end;
  29. SQL*Plus is a poor tool for procedural logic (loops and conditional flows)Embedding calls to sqlplus in a shell script is not a good idea.You generally won’t have a persistent connection, so will be continually logging on and off the database. You can’t maintain transactionsThere is poor error/exception handling as you can really only return a generic error/warning to the shell script.Use Perl (which gets installed with the databases, except XE) or Python or….PL/SQL