i want to pass a whole sql query as a lexical parameter to a stored procedure and then execute it. Any suggestions how to do that?
you may try this:
create or replace procedure my_proc(pstring IN varchar2)
is
begin
if length(pstring)>0 then
EXECUTE IMMEDIATE pstring;
end if;
end my_proc;
here is the official oracle documentation on dynamic plsql : http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14261/dynamic.htm#CHDGJEGD
Not sure what you mean by "lexical" parameter but you can pass the SQL query in as a VARCHAR2 then execute it using EXECUTE IMMEDIATE.
What you are trying to do is almost certainly the wrong way to go.
Execute Immediate is to be used with caution because it can a) impose a security risk and b) cause negative effects on performance when many distinct SQL statements are run that way.
However, see here how to insert records using execute immediate. Note that it's essential to use bind variables.
If you want to run a query (as opposed to a DML [insert, update, delete] or a PL/SQL block of code), you can do something like this:
function get_dataset (p_sql_query in varchar2) return sys_refcursor
as
l_returnvalue sys_refcursor;
begin
open l_returnvalue for p_sql_query;
return l_returnvalue;
end get_dataset;
The return value is a "weakly typed" REF CURSOR.
The calling program (whether it is Java, .NET, PL/SQL, whatever) must then process the function result and close the cursor.
Related
I need to execute a script (Informix code) in a .sql file for migration purposes. The thing is, I want to load it from a function to be able to use the exception, therefore being able to do a rollback in case of an error.
So, this is the code (still experimenting):
DROP FUNCTION IF EXISTS "informix".SCRIPT_MIGRATION();
CREATE FUNCTION "informix".SCRIPT_MIGRATION()
RETURNS BOOLEAN as RESULT;
DEFINE lv_execute lvarchar(32739);
DEFINE li_errnum, li_eisam INT;
DEFINE lv_errtxt CHAR(200);
ON EXCEPTION SET li_errnum, li_eisam, lv_errtxt
ROLLBACK;
CALL regista_log('script_migration', get_session_user(), li_errnum, lv_errtxt);
RETURN 'f';
END EXCEPTION;
CALL set_isolation_level();
BEGIN;
LET lv_execute = 'LOAD FROM ''C:\Users\Admin\Desktop\ConstaWeb_Stuff\test.sql'' DELIMITER ''+'' INSERT INTO SCRIPT_MIGRATION_TEMP_TABLE;';
DROP TABLE IF EXISTS SCRIPT_MIGRATION_TEMP_TABLE;
CREATE TABLE SCRIPT_MIGRATION_TEMP_TABLE(
STRING_TO_EXECUTE LVARCHAR(31739)
);
EXECUTE IMMEDIATE lv_execute;
COMMIT;
RETURN 't';
END FUNCTION;
CALL SCRIPT_MIGRATION();
That's because we apparently can't execute the load command inside functions. So I'm trying to execute it. But I'm not getting it right, apparently...
The objective here is to execute the script (not a shell command script! it's an Informix script, like creates, loads, unloads, drops...) on a file. I'm open to other ways of doing this.
I'm relatively new to Informix so I'm sure there is still a lot I don't know about it.
As already noted, the LOAD command is not a command recognized by the Informix server. Client products emulate an SQL statement by recognizing the syntax and reading the file and executing appropriate SQL statements. Changing the way you (try to) execute it in a function executing in the server will not help.
Using a shell script instead may help.
If you're migrating an existing Informix database to a new location (machine, version of Informix), then using DB-export and DB-Import may be a good way to go.
The DB-Access command is the 'standard' way to execute scripts from a shell script. You'd need to ensure you set the DBACCNOIGN environment variable to 1. That will then stop if there's an error during the LOAD and rollback the transaction. There's also the DB-Load command, but it will be harder to rollback DDL statements since it does not handle those.
Alternatively, you might find my SQLCMD* program useful — though it too isn't perfect. However, unlike DB-Access, it allows you to control which statements can generate errors that are ignored and which are not (continue [on|off|push|pop]; before and after as appropriate).
With careful packaging, you can use it to create your migration, assuming the DB-Export and DB-Import won't do the job for you automatically.
* You may have to subscribe to the IIUG to get at this. The registration is not onerous, and neither is the email load.
I am engaged at the moment in some serious PL/SQL programming. The format for creating procedures is
[CREATE [OR REPLACE]]
PROCEDURE procedure_name[(parameter[, parameter]...)]
[AUTHID {DEFINER | CURRENT_USER}] {IS | AS}
[PRAGMA AUTONOMOUS_TRANSACTION;]
[local declarations]
BEGIN
executable statements
[EXCEPTION
exception handlers]
END [name];
and I place executable statements under BEGIN. Why am I not allowed to place a CREATE TABLE statement as an executable statement within a procedure?
Because CREATE TABLE is a DDL statement, and you may not execute DDL statements from PL/SQL (at least not directly).
If (and that's a big if) you really need to do that, you can either use the DBMS_SQL package or EXECUTE IMMEDIATE (easier):
create or replace procedure do_it as
begin
execute immediate 'CREATE TABLE foo(pk number not null)';
end;
But this is usually not necessary. People coming from a SQL Server background often are trained to create lots of temporary tables from their stored procedures - in Oracle, you'd normally use a Global Temporary Table for that.
As you can see in the image bellow, my SQL Stored Procedures, somehow, my SQL Server opens Procedures like Unicode SPs.
That was not the case before, and I have no idea how this apeared now.
I have around 5.000 stored procedures so there is no chance I can edit it manualy.
My SPs starts from ALTER PROCEDURE , everything before that is somehow added.
Your SP's will still work just fine. This is just the way SQL Server Management Studio scripts the objects when you want to generate ALTER- or CREATE-statements.
To change this behavior, go to Tools > Options > SQL Server Object Explorer > Scripting
Set the option "Include IF NOT EXISTS clause" to "False".
(In other versions of SQL Server Management Studio the option might be called something like "Check for object existence")
As previously answered, changing the scripting option "Include IF NOT EXISTS clause" to false solves the problem. To add context, if this value is true, it has to be scripted by putting the entire Alter Procedure statement in an #statement variable, because the conditional logic associated with the check for existence requires the ALTER PROCEDURE statement be inside a BEGIN/END block, which is not allowed. So Microsoft's workaround is to put the entire ALTER PROCEDURE statement in the #statement variable, which is executed conditionally inside a BEGIN/END block.
How could we know which WLM job has picked my DB2 stored procedure call invoked. I see some set of jobs are running with DB2XWLM* where DB2X is database region. But how to check which particular job had taken my stored procedure call.
Hope I made clear, please let me know if something is not clear. Appreciate your interest.
By giving few 'unique display statements' in the Stored procedure and by making the display statements on , we can check which WLMjob has picked the Stored procedure.
Typically a stored procedure is assigned to a region when it's created.
If you are able to see the DDL for the CREATE PROCEDURE statement (perhaps through DB2 admin tool), there should be a line like:
WLM ENVIRONMENT DB2SP3
DB2SP3 would be the environment your stored procedure lives in. I'm not sure that it always works this way, but it's worth checking.
Go to the job output where you can see display statements of your SP. That JCL has WLM specified. Just search for WLM word and you can find it.
I realize this is an old post but here is the answer for future reference:
select schema ,owner ,name ,WLM_ENVIRONMENT
from SYSIBM.SYSROUTINES
where schema = 'yourschemaname'
and name = 'yourSPname'
WLM_environment is the column you are looking for.
(db2v11)
I would like to test a DB2 stored procedure running on an AS400 system.
I have the IBM System i Access for Windows installed and can run SQL commands against the DB2 database.
My question is: What is the syntax to execute a stored procedure that takes in a parameter and returns a result as an output parameter and print the value to the screen?
Just to clarify: I am not asking how to call the proc in code. I want to execute the proc and see the results in the gui tool (which is similar to SQL Enterprise Manager).
use the keyword call and pass in the parameters.
call myStoredProc(parm1, parm2, ?);
for more details see here http://www.ibm.com/developerworks/data/library/techarticle/dm-0503melnyk/. The interesting part is Figure 5. Using the Command Editor to call an SQL procedure
What you want is possible. I have done it myself many times. Unfortunaly, I'm not at the office right now so it must be from the top of my head.
Start System i Access
Go to your iSeries icons and log on to the one where your stored procedure lives
Go to the databases icons and connect to the correct one (you've one local and probably one or more remotes)
Only then, you will see the option "run SQL script" at the bottom of your screen
Start that option and you will see a SQL editor (editor on top, viewer/messages at the bottom)
Remember that you are already connected to the correct iSeries but your JDBC request will get the *LIBL of the userprofile of your connection. Therefore you must know the schema (iseries library) of your stored procedure
Enter "call YOURSCHEMA.YOURSTOREDPROCEDURE(?,?);" and use the menu or shortcut to run that statement. Notice that - depending on your JDBC settings (see menu) - the correct syntax may be "/" instead of ".". Also, notice that you can replace the first question mark with a value.
On an additional note,
In iAccess, under every schema you will see icons for the tables, views and so on. Also an icon for stored procedures is available. You will see your SP there. Use the options to see the definition and so. This information includes detailed information about the parameters
If you want to check that on your iSeries, use the system catalog (this can be done from the SQL editor too) with "select * from qsys2.sysprocedures where procedure_name (sorry, not sure about the name of this column right now) = 'YOURSTOREDPROCEDURE';"
VERY IMPORTANT: I was never able to test the SP with the SQL editor (STRSQL) on the iSeries itself. Only the iAccess SQL editor did work correctly.
You should be able to run your SP like this:
DECLARE
usr_in YOUR_TABLE.YOUR_COLM%TYPE; --Gets the correct type by looking at column type
app_in YOUR_TABLE.YOUR_OTHER_COLM%TYPE;
BEGIN
usr_in:='some value';
app_in:='another_value';
YOUR_SP_NAME(usr_in, app_in);
END;
Or you can use EXECUTE, but it can't be dynamically prepared (not run in Java) and I think there's some other disadvantages.
EXECUTE myStoredProc(parm1, parm2, ?);