Package got invalidated in oracle 11g [duplicate] - sql

I am using oracle 10g and toad 11.5. I am trying to call an api from an anonymous block.
If I recompile the api after adding dbms_output.put_line and then try to execute the anonymous block, it shows error as:
"ORA-06508: PL/SQL: could not find program unit being called".
However if I end current session and open a new session, then the anonymous block will execute with out the error.
Due to this issue, i am made to reconnect the session everytime i make a change to API.
Can anyone help if this issue can be resolved by making any configurations in toad or database level.

I suspect you're only reporting the last error in a stack like this:
ORA-04068: existing state of packages has been discarded
ORA-04061: existing state of package body "schema.package" has been invalidated
ORA-04065: not executed, altered or dropped package body "schema.package"
ORA-06508: PL/SQL: could not find program unit being called: "schema.package"
If so, that's because your package is stateful:
The values of the variables, constants, and cursors that a package
declares (in either its specification or body) comprise its package
state. If a PL/SQL package declares at least one variable, constant,
or cursor, then the package is stateful; otherwise, it is stateless.
When you recompile the state is lost:
If the body of an instantiated, stateful package is recompiled (either
explicitly, with the "ALTER PACKAGE Statement", or implicitly), the
next invocation of a subprogram in the package causes Oracle Database
to discard the existing package state and raise the exception
ORA-04068.
After PL/SQL raises the exception, a reference to the package causes
Oracle Database to re-instantiate the package, which re-initializes
it...
You can't avoid this if your package has state. I think it's fairly rare to really need a package to be stateful though, so you should revisit anything you have declared in the package, but outside a function or procedure, to see if it's really needed at that level. Since you're on 10g though, that includes constants, not just variables and cursors.
But the last paragraph from the quoted documentation means that the next time you reference the package in the same session, you won't get the error and it will work as normal (until you recompile again).

seems like opening a new session is the key.
see this answer.
and here is an awesome explanation about this error

Based on previous answers. I resolved my issue by removing global variable at package level to procedure, since there was no impact in my case.
Original script was
create or replace PACKAGE BODY APPLICATION_VALIDATION AS
V_ERROR_NAME varchar2(200) := '';
PROCEDURE APP_ERROR_X47_VALIDATION ( PROCESS_ID IN VARCHAR2 ) AS BEGIN
------ rules for validation... END APP_ERROR_X47_VALIDATION ;
/* Some more code
*/
END APPLICATION_VALIDATION; /
Rewritten the same without global variable V_ERROR_NAME and moved to procedure under package level as
Modified Code
create or replace PACKAGE BODY APPLICATION_VALIDATION AS
PROCEDURE APP_ERROR_X47_VALIDATION ( PROCESS_ID IN VARCHAR2 ) AS
**V_ERROR_NAME varchar2(200) := '';**
BEGIN
------ rules for validation... END APP_ERROR_X47_VALIDATION ;
/* Some more code
*/
END APPLICATION_VALIDATION; /

I recompiled the package specification, even though the change was only in the package body. This resolved my issue

Related

What does $$ (double dollar) mean in Oracle SQL?

This Create package query executes in a SQLPlus util cli without error -
create or replace package PACKAGE2 as
$if $$install_ad_zd_sys $then
procedure LOG( X_MODULE varchar2, X_LEVEL varchar2, X_MESSAGE varchar2);
function LITERAL(X_VALUE varchar2) return varchar2;
else procedure LOG_VER;
$end
end;
/
Just want to know what does double dollar mean here?
Is it a sqlplus specific keyword?
I tried running this whole block as part of jdbc but it gives error 'Invalid column index'. So, I am suspecting the sign is specific to sqlplus, but not able to find the meaning of it.
This is how I am executing the above sql in java jdbc
plSqlstatement = connection.prepareCall(sqlBuffer.toString());
//sqlBuffer contains the whole create package block
//like sqlBuffer.append("CREATE OR REPLACE
//PACKAGE ....").append("/n").append(..next Line) and so on.
It's an inquiry directive:
An inquiry directive provides information about the compilation environment.
An inquiry directive typically appears in the boolean_static_expression of a selection directive, ...
... which is how you are using it, as it's within the $if conditional compilation directive.
You would need to assign a value, which you don't seem to be doing in either execution. But it will compile anyway, through SQL*Plus or JDBC (as in this db<>fiddle).
If you are getting an error from your JDBC call then you need to look at how you are running it - particularly if you are making get/set calls for arguments, as the error message suggests - since there are no arguments to set or retrieve.

PHP function written in 5.5 throws error when upgraded to 7.0

here is the function that worked prior to upgrading to 7.0
function set_session_vars() {
$nb_args=func_num_args();
$arg_list=func_get_args();
for($i=0;$i<$nb_args;$i++) {
global $$arg_list[$i];
$_SESSION[$arg_list[$i]] = $$arg_list[$i];
}
}
now it causer error that says:
Parse error: syntax error, unexpected '[', expecting ',' or ';' in /home/mvyc1956/public_html/members/includes/functions.php on line 322
I believe its related to non backward compatable changes to GLOBAL and the use of $$ and arrays, but my PHP is not good enough to figure it out.
Is there someone who is familiar with why this line :
global $$arg_list[$i];
which is line 322 that is being reported as the cause of the error, would be failing now, and what would you recommend I change the code to in order to have it work with PHP 7?
I did some googling and found this page but again, im not understanding what needs to be changed.
thanks
says syntax error so some of the code in the function is no longer valid, but it would take a php 7 expert to see it.
UPDATE
I removed the word GLOBAL from the above code and the app "seems" to be now working fine so I will now ask:
Does anyone know specifically, why Global was the non compatibility issue? and is my fix of simply removing it a solid one or will is there a better practice or will this removal come back to haunt me?
Backward incompatible changes:
global only accepts simple variables
Variable variables can no longer be used with the global keyword. The curly brace syntax can be used to emulate the previous behaviour if required:
// Valid in PHP 5 only.
global $$foo->bar;
// Valid in PHP 5 and 7.
global ${$foo->bar};
So in your case it should become:
global ${$arg_list[$i]};
The global keyword tells PHP to access a global variable (per launch of the script) instead of a local variable (per function). For example,
global $foo;
means that future uses of the variable $foo in that function refer to the global variable with that name, rather than a variable within the function itself.
What this is trying to do is look up a variable by arbitrary name in the global namespace. That's entirely the wrong way to do things. Instead, you should have a global array and use keys in the array. In fact, $$ is arguably a bad idea in general.
But that's neither here nor there. The problem is that the parsing rules changed in PHP 7.0 in a non-backwards-compatible way (because they're using a more traditional parser now, and thus had to make their associativity rules self-consistent).
More details here:
http://php.net/manual/en/migration70.incompatible.php#migration70.incompatible.variable-handling.indirect
To make a long story short, you need to rewrite that as:
global ${$arg_list[$i]};
and then your code will work correctly on both PHP 7 and PHP 5.
Incidentally, the function only appears to work without the global keyword. In fact, it is always getting empty values for those variables.

how to store sql query result in a variable and messegeBox

I have a simple sql query in my Execute sql task in ssis package,
SELECT MAX(binindex)
FROM dbo.myTable
I need to store this maximum index into a variable and then pass it to Script Task and display it,
I already declared a package variable, the package compiles, however it shows -1 every time, I don't know what I'm doing wrong, any help will be appreciated!
public void Main(){
//TODO: Add your code here
Dts.TaskResult = (int)ScriptResults.Success;
MessageBox.Show(Dts.Variables["User::BININDEX"].Value.ToString());
}
The good news, is that you are doing everything correctly as far as I can see. I recreated your package and I get the expected value from my query.
I can also induce your situation - the correct value is returned from my query but my package produces an "incorrect result."
The problem, I hope, is that you have two BININDEX variables defined at different scopes. My original assumption was the Package scoped one contained a value of -1 and you had a variable scoped to the "Execute SQL Task" with the same name. The default behaviour is a variable is created scoped to the object that currently has focus. This changes in the 2012 release of SQL Server by the way.
As your picture shows a design-time value of 123 for the package scoped variable, the possibility also exists that you have a variable defined on the Script Task with the same name of BININDEX. The local variable would override the globally scoped variable
Click on your Script Task and hopefully you'll see a BININDEX defined there like the above. Otherwise, I think the problem is somewhere in your package, you have conflicting BININDEX variables. You can try slogging through the Package Explorer looking for an instance where you have two variables with the same name listed.
I need to leave but if none of that is the case, add a PostExecute breakpoint on the Execute SQL Task and look at your Locals window (not Variables as that only reflects Design-time values). Expand Variables and you should be able to see the value of BININDEX. Is it correct there?

Declaring global exception in PL/SQL package

I have some procedures/functions in the package which catch the -2291 exception when a FOREIGN KEY constraint is violated.
I removed the exception from the different procedures and declared it in the package body like so:
e_ouder_niet_gevonden EXCEPTION;
PRAGMA EXCEPTION_INIT(e_ouder_niet_gevonden,-2291);
Now when I use one of the procedures in the package there is no problem. What I would like to achieve, however, is that ANY procedure/function can use that exception. How would I go about doing this?
SOLUTION:
Instead of putting the exception in the package body, you need to put in the package specification. If you then want to use the exception in a procedure outside of the package you can put this in the EXCEPTION block:
WHEN packagename.exception_name THEN
This works without problems.

Correct error-handling practices for the data-layer

What are good things to check for, with respect to error-handling, when you are dealing with the data-access-layer? For example, let's assume I have this function..
Public Function UserExists(ByVal userName As String) As DataTable
Dim dt As Object = Nothing
Dim arSqlParameters(0) As SqlParameter
arSqlParameters(0) = New SqlParameter("#UserName", SqlDbType.NVarChar, 50)
arSqlParameters(0).value = userName
dt = ABC.APP.DAL.DALHelper.ExecuteDatatable(ConnectionString, CommandType.StoredProcedure, "dbo.aspnet_sprGetUserByUsername", arSqlParameters)
Return dt
End Function
This seems like very lazy and unsafe coding. How would you go about ensuring that your code elegantly handles anything unexpected in a situation like this?
I'm new to vb.net and the app that I'm working on has no error handling, so I figured this would be the best place to look for advice. Thanks in advance :)
Not sure why you're not declaring dt as a datatable - what is the motiviation for "dim dt as object = nothing"?
Really the only line that can reasonably fail is the "dt=ABC.APP.DAL...." call.
In that line, you could have a few errors:
The stored procedure or parameter
names are wrong. This should be
caught at design-time (not by a
built-in checking mechanism, but the
first time that you try to run the
code)
An error occurs in the stored
procedure. Sprocs use deferred name
resolution, which can lead to runtime
errors if (for instance) objects
don't exist at the time that the
sproc is called. Again, this is most
likely to rear it's head in testing.
A deadlock. In this case, you should
catch and resubmit the batch.
Here's an intro and set of links
on handling SQL errors in application
code.
A parameter that is passed is
invalid (too long, wrong datatype,
etc). This should be checked
before you call the sproc.
This might be of use to you...
.NET Framework Developer's Guide - Design Guidelines for Exceptions
Opinions are likely to vary wildly on a topic like this, but here's my take. Only try to deal with the exceptions that you relate to this area. That's a vague statement, but what I mean is, did the user pass a string with more chars than the column in the db. Or did they violate some other business rule.
I would not catch errors here that imply the database is down. Down this far in the code, You catch errors that you can deal with, and your app needs it's database. Declare a more global exception handler that logs the problem, notifies someone, whatever... and present the user with a "graceful" exit.
I don't see any value in catching in each method a problem with the database. You're just repeating code for a scenario that could bomb any part of your datalayer. That being said, if you choose to catch db errors (or other general errors) in this method, at least set the innerexception to the caught exception if you throw a new exception. Or better, log what you want and then just "throw", not "throw ex". It will keep the original stack trace.
Again, you will get a lot of varying thoughts on this, and there is no clear right and wrong, just preferences.
looking inside Open Source ORM solutions' code (Subsonic, nHibernate) will help you.
By my limited knowledge I think error related to connections, connection timeouts etc. should be passed as such because DAL cannot do much about it. Error related to the validations (like field lengths, datatypes) etc should be returned with appropriate details. You may provide validation methods (Subsonic contains it) that validate the field values and returns the appropriate error details.
I've put a lot of thought into this as well. A lot depends on the particular database, so depending on if you are using SQL2000 or SQL2005+ you will either be doing return codes, RAISERROR or TRY-CATCH in the stored procedure.
RAISERROR is preferably to return codes, because developers using the stored procedure get more information. Optimally you'd pick numbers 50000 and up and register the corresponding messages, but this is a lot of work just to communicate what can be communicated in the text of the RAISERROR call
The return code is uninterperatable without reading the source code of the stored procedure. a return value of 0 might be success, failure, 0 rows affected, the just generated primary key, or that no return code was set depending on the whims of the stored procedure writer that day. Also, ADO.NET returns row count from ExecuteNonQuery, so some developers will find it hard to quickly discover the return code.
Ad hoc solutions are also bad, eg.
IF ##Error>0
SELECT 'Something bad happened'
If you have the option of using CLR stored procedures, then C# style error handling comes into play.
So add RAISERROR to your stored procedures, then catch SqlException, report to the user anything that really is a user data entry Validation, log anything that is a developer abusing the API, and maybe attempt a re-try for connection or execution timeouts.
IF #Foo =42
BEGIN
RAISERROR ( 'Paramater #foo can''t be 42',
16, -- Severity = Misc. User Error.
1 -- State. == ad hoc way of finding line of code that raised error
) ;
RETURN -1; --Just because some developers are looking for this by habit
END