Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between EXEC_SQL, EXECUTE IMMEDIATE, DBMS_SQL and inline SQL

I've been going over some PL/SQL (In Oracle SQL Developer), and have seen several different formats of SQL being called.

For the consistency and speed of current and future code, I'd like to know which is the preferred choice.

There are four types I've seen.

1) Plain DDL:

CREATE TABLE newtable AS SELECT * FROM pSource;

2) Execute Immediate (Native Dynamic SQL):

statement := 'CREATE TABLE newtable AS SELECT * FROM ' || pSource;
EXECUTE IMMEDIATE statement;

3) EXEC_SQL:

EXEC_SQL('CREATE TABLE newtable AS SELECT * FROM ' || pSource);

4) DBMS_SQL:

cursor := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(cursor, 'CREATE TABLE newtable AS SELECT * FROM ' || pSource, DBMS_SQL.NATIVE);
numRows := DBMS_SQL.EXECUTE(cursor);

Are there any particular advantages/disadvantages/restrictions between these different ways of calling?

like image 276
Addison Avatar asked May 01 '15 05:05

Addison


People also ask

What is the difference between execute immediate and DBMS_SQL in Oracle?

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.

What does execute immediate do in SQL?

The EXECUTE IMMEDIATE statement executes a dynamic SQL statement or anonymous PL/SQL block. You can use it to issue SQL statements that cannot be represented directly in PL/SQL, or to build up statements where you do not know all the table names, WHERE clauses, and so on in advance.

Is execute immediate faster?

Execute Immediate executes much faster than Dbms_Sql in many scenarios.


1 Answers

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.

like image 173
mmmmmpie Avatar answered Sep 30 '22 17:09

mmmmmpie