bulk compiling pl/sql procedures - oracle

i have lots of packages which needed to be compiled when i move from development to production or when we release a change request.
right now , we compile each of the packages one by one using toad or sqldbx , is there a way that i can write a batch file with sqlplus command so that i can run all my packages in one go.. like *.sql

You can execute dbms_utility.compile_schema(user,false); to compile all invalid objects in your schema at once.
You can read about that procedure here in the documentation: http://download.oracle.com/docs/cd/E11882_01/appdev.112/e16760/d_util.htm#ARPLS73226
Regards,
Rob.

Normally when we do lots of changes in a database that invalidates lots of objects, the easiest way to get them recompiled is by running sqlplus "/ as sysdba" #?/rdbms/admin/utlrp This procedure gets smarter every release and from 10g it uses the Oracle Scheduler to work in parallel. This of course only works with dba access to the database. If you lack that Rob van Wijk's answer is the way to go.

You can put all the SQLs in a text file and execute that by:
SQL > #/path/script.sql
You just need to provide path of script to be executed.

My approach would be to copy all package scripts into a directory then create a single sql script in that directory to load all packages, see example below.
-- load package specifications
##package1.pks
##package2.pks
-- load package bodies
##package1.pkb
##package2.pkb

One way of tackling this is to deploy your code in the correct order.
PL/SQL packages themselves are the API for the code in the package body, and the packages themselves are not dependent on each other. Package bodies however can be dependent on packages, so if a package is recompiled than it runs the risk of invalidating package bodies that reference it.
Unfortunately it's very common to see deployments that work in this order:
create or replace Package A ...;
create or replace Package Body A ...;
create or replace Package B ...;
create or replace Package Body B ...;
create or replace Package C ...;
create or replace Package Body C ...;
This has the side-effect that if code in Package Body A is dependent on Package B, then when Package B is (re)created it invalidates Package Body A.
The correct sequence for deployment is:
create or replace Package A ...;
create or replace Package B ...;
create or replace Package C ...;
create or replace Package Body A ...;
create or replace Package Body B ...;
create or replace Package Body C ...;
If there have not been changes in the package itself then there is no need to deploy it at all, of course.
Respecting these methods should give you much fewer invalid objects.

Package Headers first:
for i in $(ls *.hed); do sqlplus user/password #$i; done
Then package bodies:
for i in $(ls *.hed); do sqlplus user/password #$i; done

you can use dba_objects to check for invalid objects and use dynamic sql to generate compile statements, something like:
select 'alter ' || object_type || ' ' || owner || '.' || object_name || ' compile;'
from dba_objects
where status = 'INVALID'
and object_type in ('PACKAGE', 'PROCEDURE', 'FUNCTION');
you can then put that into a sql script.
You can also look into utl_recomp package

Related

Verify if a file is SQL or verify its syntax

I'm implementing DevOps with Oracle and Jenkins, I use a Gitlab repository for scripts .sql (PL/SQL and ORDS), I want to verify if a file is uploaded and trigger pipeline is indeed a SQL file and verify its syntax to avoid execute all pipeline if it is a wrong file. Exists some Oracle command or script that do this? (I find EXPLAIN PLAN FOR but it doesn't work with PL/SQL blocks and ORDS)
Thank you
script
var input = 'select * from emp';
var ParsedSql = Java.type('oracle.dbtools.parser.plsql.ParsedSql');
var parsed = new ParsedSql(input);
var root = parsed.parse();
root.printTree();
/
The other useful ParsedSql methods:
getInput()
getSrc()
getRoot()
getSyntaxError()

Oracle command works in database but not in SQLPlus

I'm currently trying to implement a bash script that runs at the end of the day that runs a simple oracle query. The command works just fine in Oracle but when inside a .sql file it does not run.
I've attempted to put all of the code on one line and adding semicolons.
Contents of batch file (with user/pass altered):
sqlplus username/password#database #set_changed.sql
Contents of set_changed.sql file:
UPDATE ris_web a
SET a.changed = 0
where exists
(
select modified_date from invn_sbs b
where b.item_sid = a.item_sid
and b.modified_date <= sysdate-1
);
COMMIT;
END;
In SQLPlus you should use a / on a separate line to terminate an SQL statement or PL/SQL block instead of using a semicolon, so change your file to
UPDATE ris_web a
SET a.changed = 0
where exists
(
select modified_date from invn_sbs b
where b.item_sid = a.item_sid
and b.modified_date <= sysdate-1
)
/
SHOW ERRORS
/
COMMIT
/
SHOW ERRORS
/
END
You might also want to have a look at this question
You have end; command at the end of the script but no BEGIN for it.
Simply replace the END; with /
The original syntax was correct. There were uncommitted changes in sqldeveloper that were causing the .sql file to never finish running. Thank you everyone for your help.

calling exist/not exist package dynamically

I have a PL/SQL package as following (A piece of code):
if(IsRegisterMode)
num_result := kwp_gep.register(var_name,var_family, bool_is_incomming);
My problem is : in some environment kwp_gep package exist and IsRegisterMode flag is true so kwp_gep.register called but in another environment kwp_gep package don't exist(not necessary) and IsRegisterMode flag is false.
With above explanation in second environment main package doesn't compile and show error : kwp_gep does not exist.
My question is: What is solution for this problem? I think exist a solution for dynamically execute kwp_gep procedures.
EDIT:
kwp_gep.register has a number as return value and bool_is_incomming and boolean.
Option 1: Conditional Compilation
You could use conditional compilation, e.g.
$IF $$isregistermode $THEN
kwp_gep.register(var_name,var_family);
$ENDIF
When you compile the package, you'd do something like this in the environments where the package exists:
ALTER SESSION SET PLSQL_CCFLAGS = 'isregistermode:true'
Option 2: Dynamic execution
if IsRegisterMode then
execute immediate 'kwp_gep.register(:var_name,:var_family)'
using var_name, var_family;
end if;
Option 3: Stub
(as per Egor's suggestion) in the environments that don't have kwp_gep.register, create a stub that never gets called, e.g.
CREATE OR REPLACE PACKAGE kwp_gep IS
PROCEDURE register (var_name in varchar2, var_family in varchar2);
END kwp_gep;
Note that it has no package body, so it will never execute without error. In your case it doesn't matter since your flag ensures it won't get called. If it does, then you know there's a problem in that environment.

PLS-00103: Encountered the symbol "CREATE"

What is the problem with this package as it is giving an error?
CREATE OR REPLACE PACKAGE PKG_SHOW_CUST_DETAILS
AS
PROCEDURE SHOW_CUST_DETAILS( myArg VARCHAR2);
END PKG_SHOW_CUST_DETAILS;
CREATE OR REPLACE PACKAGE BODY PKG_SHOW_CUST_DETAILS
AS
PROCEDURE SHOW_CUST_DETAILS(myArg VARCHAR2)
IS
BEGIN
DBMS_OUTPUT.PUT_LINE(myArg);
END SHOW_CUST_DETAILS;
END PKG_SHOW_CUST_DETAILS;
/
On compilation of the above script, I am getting the following errors:
SQL> show errors
Errors for PACKAGE PKG_SHOW_CUST_DETAILS:
LINE/COL ERROR
-------- -----------------------------------------------------------------
6/1 PLS-00103: Encountered the symbol "CREATE"
The package is very simple and I am not able to compile it. I searched earlier answers on this error message and none of them did solve my problem.
I am consistently getting this error for 2 more packages and I am stuck on this error message no matter what I do. I even tried to strip everything to the barest minimum as shown above, but the error message does not seem to go away.
BTW I am executing this on command line SQL plus session after logging into my Oracle 11G database.
YES- SET SERVEROUTPUT ON -- is executed and the error message has nothing to do with this command.
What am I missing?
At line 5 there is a / missing.
There is a good answer on the differences between ; and / here.
Basically, when running a CREATE block via script, you need to use / to let SQLPlus know when the block ends, since a PL/SQL block can contain many instances of ;.
For me / had to be in a new line.
For example
create type emp_t;/
didn't work
but
create type emp_t;
/
worked.
In my case EXECUTE IMMEDIATE ('CREATE TABLE ...') works, for example:
DECLARE
  myVar INT;
BEGIN
SELECT 2 INTO myVar FROM dual;
IF myVar > 1 THEN
   EXECUTE IMMEDIATE('Create Global Temporary Table TestTemp ( id VARCHAR2(2) ) ON COMMIT PRESERVE ROWS');
END IF;
END;
Reference to Create Table As within PL/SQL?
Run package declaration and body separately.

Update a package from SQLPLUS

I'm trying to update a package in Oracle, coming from SQL Server this has been confusing.
I have written a batch file that runs the .spec file first and the .body file second, but even running it manually does not work.
I use this syntax:
sqlplus username/password#databasename #c:\temp\myfile.spec
sqlplus username/password#databasename #c:\temp\myfile.body
When I go back to Sql Developer I can look at the stored procedures in the package and see that they have not been updated.
Why aren't my packages getting updated?
The spec and body files need to have / make SQL*Plus create/replace the object.
Without the /:
CREATE OR REPLACE PACKAGE TEST12_13 AS
PROCEDURE TEST12_13;
END;
STAGE#DB>#C:\TEST.PKS
6
With the /:
CREATE OR REPLACE PACKAGE TEST12_13 AS
PROCEDURE TEST12_13;
END;
/
STAGE#DB>#C:\TEST.PKS
Package created.
In reply to your comment about passing filename as parameter, instead of passing the filename as parameter, have SQL*Plus ask you for the filename
wrapper.sql
ACCEPT filename_var Prompt 'Enter filename'
#c:\temp\&filename_var
/
#c:\temp\&filename_var
/
Connect to SQL*Plus with
sqlplus username/password#databasename
Then run the script from the SQL*Plus prompt:
set echo on
#c:\temp\myfile.spec
You should be able to see whats going on like this, including any error messages.

Resources