Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
plsql_static_dynamic_sql [2020/05/31 15:26] – andonovj | plsql_static_dynamic_sql [2020/06/04 15:41] (current) – [Differences] andonovj | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | =====Overview===== | + | ======Overview====== |
In this section we will discuss: | In this section we will discuss: | ||
* Static SQL | * Static SQL | ||
Line 6: | Line 6: | ||
So let's get going, what do you say ? | So let's get going, what do you say ? | ||
- | =====Static SQL===== | + | ======Static SQL====== |
Static SQL relies on hard coding the SQL commands inside the code. Once written, that code cannot be changed via parameters and because of that it is called static. There are use cases, when you should use Static, but mostly Native dynamic SQL is used. We will see why in a bit. But first, let's pass through the Static one. | Static SQL relies on hard coding the SQL commands inside the code. Once written, that code cannot be changed via parameters and because of that it is called static. There are use cases, when you should use Static, but mostly Native dynamic SQL is used. We will see why in a bit. But first, let's pass through the Static one. | ||
+ | |||
+ | ====Statment==== | ||
To define a static SQL, let's check the following example: | To define a static SQL, let's check the following example: | ||
Line 35: | Line 37: | ||
We will discuss both ways now: | We will discuss both ways now: | ||
- | ====Native==== | + | =====Native===== |
Let's see example of a Native Dynamic SQL | Let's see example of a Native Dynamic SQL | ||
Line 56: | Line 58: | ||
Native SQL is all about " | Native SQL is all about " | ||
- | ====DBMS_SQL==== | + | =====DBMS_SQL===== |
Something to note here in contrast with Native Dynamic SQL. But first, little history. When you invoke a procedure, usually you invoke it with the definer' | Something to note here in contrast with Native Dynamic SQL. But first, little history. When you invoke a procedure, usually you invoke it with the definer' | ||
Line 86: | Line 88: | ||
We will examine each of these executions. | We will examine each of these executions. | ||
- | ===DDL & Session Control=== | + | ====DDL & Session Control==== |
DDL statment or Data Definition language statment is a statment which create, alters or delete definitions of data. It includes the following commands: | DDL statment or Data Definition language statment is a statment which create, alters or delete definitions of data. It includes the following commands: | ||
* Create | * Create | ||
Line 119: | Line 121: | ||
In Oracle DB, DDLs are auto-commit. | In Oracle DB, DDLs are auto-commit. | ||
- | ===DML Statment=== | + | ====DML Statment==== |
DML is Data Modification Language is a language used to modify the data, it includes the following commands: | DML is Data Modification Language is a language used to modify the data, it includes the following commands: | ||
* Update | * Update | ||
Line 125: | Line 127: | ||
* Insert | * Insert | ||
- | In order to execute DML using DBMS_SQL we need to pass through the following steps from the SQL Processing Flow: | + | In order to execute DML using DBMS_SQL we need to pass through the following steps from the SQL Processing Flow APIs: |
- | * Unordered List Item | + | * Open Cursor |
+ | * Parse | ||
+ | * Bind Varialbes (Optional): Generally used to reduce the number of hard parses as Oracle Optimizer will be able to re-use the execution plan if the query is ran again. | ||
+ | * Execute | ||
+ | * Variable Value | ||
+ | * Close Cursor | ||
So let's check an example of this: | So let's check an example of this: | ||
< | < | ||
+ | CREATE OR REPLACE PROCEDURE insert_record(p_talbe_name VARCHAR2, | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | l_sql VARCHAR2(100); | ||
+ | l_cursor_id INTEGER; | ||
+ | l_return INTEGER; | ||
+ | BEGIN | ||
+ | l_sql := ' | ||
+ | p_col1_name||',' | ||
+ | p_col2_name|| | ||
+ | ') '|| | ||
+ | ' | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | END insert_record; | ||
+ | </ | ||
+ | ====Describe Unknown No. of Columns==== | ||
+ | One advantage of the DBMS_SQL over the Native Dynamic SQL is the ability to work with: | ||
+ | |||
+ | * Unknown Number of Bind Variables | ||
+ | * Unknown Number of Column | ||
+ | |||
+ | So let's see how we can work with unknown number of columns. Oracle provided couple APIs for that: | ||
+ | |||
+ | * DBMS_SQL.DESC_COLUMNS(x) | ||
+ | * DBMS_SQL.DESC_TAB | ||
+ | * DBMS_SQL.DESC_REC | ||
+ | |||
+ | X - being: ,2 or 3 | ||
+ | Let's go through each of them. | ||
+ | |||
+ | ===DESC_COLUMNS=== | ||
+ | It has the following syntax: | ||
+ | |||
+ | < | ||
+ | ( | ||
+ | c | ||
+ | col_cnt OUT INTEGER, <- Returns the count of the columns in that Cursor | ||
+ | desc_t | ||
+ | ); | ||
+ | < | ||
+ | |||
+ | ===DESC_TAB=== | ||
+ | That array which we saw above and it has the following structure: | ||
+ | |||
+ | < | ||
+ | TYPE desc_tab IS TABLE OF desc_rec(x) INDEX BY BINARY_INTEGER; | ||
</ | </ | ||
- | ===Anonymous Block=== | + | More info about this record, below: |
- | <Code:pl/sql|Example | + | |
+ | ===DESC_REC=== | ||
+ | The last collection has relation with the previous collection as follows: | ||
+ | |||
+ | <Code:bash|DBMS_SQL.DESC_REC Relation> | ||
+ | desc_tab(1) | ||
+ | desc_tab(2) | ||
+ | desc_tab(3) | ||
+ | desc_tab(4) | ||
+ | desc_tab(n) | ||
+ | </Code> | ||
+ | |||
+ | Each desk_tab points to a desc_rec collection with the following content: | ||
+ | |||
+ | < | ||
+ | TYPE desc_rec IS RECORD ( | ||
+ | col_type | ||
+ | col_max_len | ||
+ | col_name | ||
+ | col_name_len | ||
+ | col_schema_name | ||
+ | col_schema_name_len BINARY_INTEGER := 0, | ||
+ | col_precision | ||
+ | col_scale | ||
+ | col_charsetid | ||
+ | col_charsetform | ||
+ | col_null_ok | ||
+ | TYPE desc_tab IS TABLE OF desc_rec INDEX BY BINARY_INTEGER; | ||
+ | </ | ||
+ | |||
+ | With the new versions, there is slightly different provided values, you can check all the values in that collections: | ||
+ | |||
+ | Phew, gosh, that was a long walk, let's see example finally: | ||
+ | |||
+ | ===Example=== | ||
+ | < | ||
+ | CREATE OR REPLACE PROCEDURE desc_columns (p_query VARCHAR2) AUTHID DEFINER IS | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | BEGIN | ||
+ | | ||
+ | | ||
+ | | ||
+ | FOR i in 1 .. l_no_of_columns LOOP | ||
+ | l_desc_rec2 := l_desc_tab2(i) | ||
+ | DBMS_OUTPUT.PUT_LINE(' | ||
+ | DBMS_OUTPUT.PUT_LINE(' | ||
+ | END LOOP; | ||
+ | DBMS_SQL.CLOSE_CURSOR(l_cursor_id); | ||
+ | END desc_columns; | ||
+ | </ | ||
+ | |||
+ | ====Security with DBMS_SQL==== | ||
+ | As we discussed, DBMS_SQL has couple security policies to prevent SQL injection. Most of them are controller when we open a cursor as the one explained above for 11g+ | ||
+ | |||
+ | < | ||
+ | DBMS_SQL.OPEN_CURSOR(security _level IN INTEGER) | ||
+ | </ | ||
+ | |||
+ | The security level is integer and sets one of the following configurations: | ||
+ | |||
+ | * 0 - No security Check | ||
+ | * 1 - Userid / Role Parsing be the same as Binding / Executing | ||
+ | * 2 - Most Secure | ||
+ | |||
+ | The most secure level is of course recommend and include the following checks: | ||
+ | |||
+ | * Current Calling User is the same as the user with the most recent parse | ||
+ | * Enabled Roles on the Current call is the same as enabled roles on the most recent parse. | ||
+ | * Container on current call is the same as the container on the most recent parse. | ||
+ | |||
+ | If any of these aren't true, you will receive: | ||
+ | < | ||
+ | ORA-29470: The effective userid or roles on this call to DBMS_SQL are not the same as those at the time the cursor was parsed. | ||
</ | </ | ||
- | ===Select Statment=== | + | Other security feature of the DBMS_SQL is the access denied when you try to use invalid Cursor ID. In a nutshell if a session tries to execute an open cursor generated by a different session, you will receive: |
- | <Code:pl/ | + | |
+ | < | ||
+ | DBMS_SQL access denied. | ||
</ | </ | ||
=====Differences===== | =====Differences===== | ||
Line 162: | Line 299: | ||
* Used for: Dynamic Queries and Sorts (Queries which can change depending on the user's preferences) | * Used for: Dynamic Queries and Sorts (Queries which can change depending on the user's preferences) | ||
* DDL can be used, unlike Static SQL | * DDL can be used, unlike Static SQL | ||
+ | |||
+ | In general, you should use DBMS_SQL dynamic SQL, only when you don't know the number of columns or bind variables which will be used in a select, for every other occasion, use the Native Dynamic SQL. |