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.
Related
I am using Inno Download Plugin to download a bunch of files for my installation. These files are listed in "files.json".
FileList := TStringList.Create;
FileList.LoadFromFile(ExpandConstant('{tmp}\files.json'));
for i := 0 to FileList.Count-1 do
begin
fileName := ExtractFileName(FileList[i]);
StringChangeEx(FileList[i], '\', '/',True);
//Add each file to download queque
idpAddFile("www.myapiaddress.com/files/" + FileList[i], ExpandConstant('{tmp}\install\') + fileName );
Log(FileList[i]);
end;
What gives me a headache is the line StringChangeEx(FileList[i], '\', '/',True). As soon as I put that in, the idp.iss stops compiling, giving me the error: Variable expected on
procedure idpAddFile(url, filename: String); external 'idpAddFile#files:idp.dll cdecl';
Installer compiles normal, if I remove StringChangeEx from my script entirely. It does not help to place it in a different location...
Any idea, what might cause this problem?
The StringChangeEx function needs a string variable in the first argument (it's declared as var). You are giving it a string value only.
Your code would work, were FileList a string array. But it's not, it's a class with an array-like string default property. Using a property value is an equivalent of using a function/method return value. A property is just syntactic sugar for getter and setter methods.
You will have to copy the value to a string variable and back.
S := FileList[i];
StringChangeEx(S, '\', '/',True);
FileList[i] := S;
Though you actually do not need to copy it back in your case.
Regarding the reason why the error refers to idp.iss file: There seems to be a bug in Inno Setup that makes it report the error as if it had occurred on the very first line of the Pascal Script code (what in your case is the very first real code in the included idp.iss). I've posted a bug report. It was fixed already.
There are certain cases with my application installer where I'd want to the user to restart their device. Ideally, I'd pass an arg i.e.
Setup.exe /RESTART=yes
And withing the setup script evaluate:
AlwaysRestart={param:RESTART|no}
Unfortunatley, that is not valid:
Error on ... Setup.iss: Value of [Setup] section directive "AlwaysRestart" is invalid.
Compile aborted.
Running InnoSetup 5.6.1
I figured out that I am able to pass an argument and use it in the NeedsRestart event function. This will prompt the user to restart the system at the end of a successful installation if I pass /restart=1 as an argument.
[Code]
function NeedRestart(): Boolean;
begin
Result := ExpandConstant('{param:restart|0}') = '1';
end;
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.
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
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.