1) You can't execute straight DDL inside of a PL/SQL block.
BEGIN
CREATE TABLE TEST AS (
SELECT * FROM FND_USER
);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
/
Yields:
PLS-00103: Encountered the symbol "CREATE" when expecting one of the following:
2) EXECUTE IMMEDIATE
(and its sister DBMS_SQL
) are used to execute SQL inside of a PL/SQL block. These differ from "regular" SQL in that they actually use a completely different SQL engine (in PL/SQL's case it runs in the oracle
process) to compute. This is why so many of us preach "if you can do it in SQL don't do it in PL/SQL".
Even these two options differ between how. EXECUTE IMMEDIATE
is quick and easy but kind of dumb. DBMS_SQL
is a little more complex but gives the developer a lot more control.
For instance this example that essentially describes the columns of a table:
declare
c number;
d number;
col_cnt integer;
f boolean;
rec_tab dbms_sql.desc_tab;
col_num number;
procedure print_rec(rec in dbms_sql.desc_rec) is
begin
dbms_output.new_line;
dbms_output.put_line('col_type = '
|| rec.col_type);
dbms_output.put_line('col_maxlen = '
|| rec.col_max_len);
dbms_output.put_line('col_name = '
|| rec.col_name);
dbms_output.put_line('col_name_len = '
|| rec.col_name_len);
dbms_output.put_line('col_schema_name = '
|| rec.col_schema_name);
dbms_output.put_line('col_schema_name_len = '
|| rec.col_schema_name_len);
dbms_output.put_line('col_precision = '
|| rec.col_precision);
dbms_output.put_line('col_scale = '
|| rec.col_scale);
dbms_output.put('col_null_ok = ');
if (rec.col_null_ok) then
dbms_output.put_line('true');
else
dbms_output.put_line('false');
end if;
end;
begin
c := dbms_sql.open_cursor;
dbms_sql.parse(c, 'select * from fnd_user', dbms_sql.native);
d := dbms_sql.execute(c);
dbms_sql.describe_columns(c, col_cnt, rec_tab);
/*
* Following loop could simply be for j in 1..col_cnt loop.
* Here we are simply illustrating some of the PL/SQL table
* features.
*/
col_num := rec_tab.first;
if (col_num is not null) then
loop
print_rec(rec_tab(col_num));
col_num := rec_tab.next(col_num);
exit when (col_num is null);
end loop;
end if;
dbms_sql.close_cursor(c);
end;
/
Source
Since DBMS_SQL
allows us to open and manipulate the cursor in which the PL/SQL block is operating inside of the result would be very difficult to reproduce in an EXECUTE IMMEDIATE
block (difficulty level: no selecting from ALL_TAB_COLS
this is just meant to be informative:).
3)EXEC_SQL
is a forms specific version of the above DBMS_SQL
. Use it wisely. :)
Here is a great breakdown of the above and here is Tom Kyte breaking it down like only he can.
CURSOR cur IS SELECT table_name FROM cols
and thisSELECT table_name FROM cols INTO types
. I assumed that this meant that any SQL could be done like this. – Spratt