IBM i (AS400) Calling SQL Stored Procedure from STRSQL - sql

I’m newbie to create DB2 for IBM i (AS400) Stored procedure. I'm seeking an answer for what’s wrong with my calling stored procedure from STRSQL.
Any ‘IN’ parameter stored procedures are callable, but ‘OUT’ parameter stored procedures are not.
create procedure egg(out pcount# INT)
language sql
set option dbgview=*source, USRPRF=*USER
begin
set pcount# = 5;
end
I call this,
call egg(?)
Then this error shows up.
SQL0418
Message . . . . : Use of parameter marker not valid.
I want to see the pcount# result, '5', in the line.
Any help would be appreciated.

What you are trying to do will work, but only if you use iNav's Run SQL Scripts query tool..
[ Thu Mar 26 08:50:52 EDT 2015 ] Run Selected
> call egg(?)
Return Code = 0
Output Parameter #1 = 5
Statement ran successfully (0 ms)
Another option if you're on a recent (7.1+) release, is the use of global variables..
create or replace variable myout int default(0)
call egg(myout)
select myout from sysibm.sysdummy1
Note that even in the scenario of using a global variable, iNav's Run SQL Scripts is a better choice as it has a tab you can open to create, update, delete global variables directly.

Related

Executing SQL Script causes error in procedure called by trigger

I'm also new to DevOps, but let me see if I can explain my situation, also if anyone has any advice on doing post deployment scripts and can share their experiences I will be most grateful.
I use SQL Source control from Redgate, Git and Azure DevOps. I have managed to get the build and deployment working perfectly. Additionally we would like to make some data changes so we have additional (Data Change) scripts we wish to run. Linking these tables as static data is not an option as we would end up having most tables linked and end up with extremely timeous build and deploy times.
The script inserts data to a table, thereby triggering the insert trigger which calls a procedure to write to an audit table. The actual error from the deployment log is:
Task : DbUp Migration
2021-01-25T12:52:17.2629353Z Description : Runs SQL Server change scripts, and only those which have not been run already.
2021-01-25T12:52:17.2629405Z Version : 2.1.4
2021-01-25T12:52:17.2629671Z Author : Johan Classon
2021-01-25T12:52:17.2629721Z Help : [More Information](https://github.com/johanclasson/vso-agent-tasks)
2021-01-25T12:52:17.2629775Z ==============================================================================
2021-01-25T12:52:19.6610608Z Beginning database upgrade
2021-01-25T12:52:19.6689401Z Checking whether journal table exists..
2021-01-25T12:52:19.6728756Z Journal table does not exist
2021-01-25T12:52:19.7775348Z Executing Database Server script '001 - EX27605 - rdl.sql'
2021-01-25T12:52:19.7908913Z Checking whether journal table exists..
2021-01-25T12:52:19.7929056Z Creating the [dbo].[_SchemaVersions] table
2021-01-25T12:52:19.8077238Z The [dbo].[_SchemaVersions] table has been created
2021-01-25T12:52:20.2264323Z ifExists - rdl_Rule_Definition_Lookup - rdl_Code = "9900226e"
2021-01-25T12:52:20.2277308Z insert - rdl_Rule_Definition_Lookup - rdl_Code = "9900226e"
2021-01-25T12:52:20.2805780Z SQL exception has occured in script: '001 - EX27605 - rdl.sql'
2021-01-25T12:52:20.2942912Z ##[error]Script block number: 0; Block line 74; Message: Trig_After_Ins_Upd_Del_rdl_Rule_Definition_Lookup
2021-01-25T12:52:20.4528752Z ##[error]System.Data.SqlClient.SqlException (0x80131904): p_dte_Audit_Backend: (Line: 108) [dte_admin]
So the 1st error refers to line 74 of the trigger, if I read this correctly which is a commit on a procedure call to write to the audit table, line 108 of my procedure sets the userID:
DECLARE #user VARCHAR(40)
SET #user =
CASE
WHEN suser_sname() = 'NT SERVICE\SQLAgent$'+##servicename THEN 'dte_admin'
WHEN suser_sname() = 'NT SERVICE\SQLSERVERAGENT' THEN 'dte_admin'
ELSE suser_sname()
END
--###############
select #udt_Audit = udt_Audit
from udt_User_Detail (nolock)
where udt_User_Id = #user--suser_sname()
--select #udt_Audit = udt_Audit from udt_User_Detail
--where udt_User_Id = suser_sname()
if ##rowcount = 0
begin
declare #udt_User_Id varchar(30)
set #udt_User_Id = suser_sname()
The last line being line 108.
Important to note that dte_admin is a login on the SQL Server, it is a sysadmin account and mapped to the database, the dte_admin user is also a user at database level and exists as a user in my user table udt_user_detail.
During the build and deployment I am using variables and they are set to dte_admin username and password.
My question is then, why does this fail with this user?
Deployment Pipeline result

Initialize / activate SQL prior to GET DIAGNOSTICS

I have two service programs: mySrvPgm and myErr
mySrvPgm has a procedure which contains:
/free
...
exec sql INSERT INTO TABLE VALUES(:RECORD_FMT);
if sqlError() = *ON;
//handle error
endif;
...
/end-free
myErr has a procedure sqlError:
/free
exec sql GET DIAGNOSTICS CONDITION 1
:state = RETURNED_SQLSTATE;
...
/end-free
Background info: I am using XMLSERVICE to call the given procedure in mySrvPgm from PHP. I am not using a persistent connection. myErr is bound-by-reference via a binding directory used by mySrvPgm. Its activation is set to *IMMED, its activation group is set to *CALLER.
The problem: Assume there is an error on the INSERT statement in mySvrPgm. The first time sqlError() is called it will return SQLSTATE 00000 despite the error. All subsequent calls to sqlError() return the expected SQLSTATE.
A workaround: I added a procedure to myErr called initSQL:
/free
exec sql SET SCHEMA MYLIB;
/end-free
If I call initSQL() before the INSERT statement in mySrvPgm, sqlError() functions correctly. It doesn't have to be SET SCHEMA, it can be another GET DIAGNOSTICS statement. However, if it does not contain an executable SQL statement it does not help.
The question: I believe the myErr service program is activating properly and has the correct scope, but I am wondering if there is something more I need to do to activate the SQL part of it. Is there some way to set it up so SQL auto-initializes when the service program is activated, or do I have to execute an unneeded SQL statement in order to get it started?
There is some more background information available here.
Thank you for reading.
What version an release of the OS? Are you upto date on PTFs?
Honestly, seems to me that it's possibly a bug. Or the manual(s) need clarification.. I'd open a PMR.

Oracle PL/SQL debug procedure - using $$plsql_line

I'm looking to create a procedure that helps with debugging specific variables, and for the sake of re-usability I'd like to store it in it's own procedure and pass in the specific variable when needed such as
debugz(var_x);
and the debug procedure would do the following -
PROCEDURE debugz (var_x VARCHAR2(1000))
AS
BEGIN
DBMS_OUTPUT.put_line ('Variable value: '|| var_x || ' | Line number: ' || $$plsql_line ||' | Unit: '|| $$plsql_unit);
END;
The problem is, I want the PL/SQL line number and PL/SQL unit to be based off of where the procedure call originates, i.e. the line/unit of "debugz(var_x);". Is there anyway for debugz to output that line number without passing in additional information?
Check out DBMS_UTILITY.FORMAT_CALL_STACK
You may need/want to parse the output depending on your exact requirements, but may be a good place to start.
Oracle 10g onwards.
Also note DBMS_UTILITY.FORMAT_ERROR_BACKTRACE and DBMS_UTILITY.FORMAT_ERROR_STACK for error handling.
There is a very good debugging package unit called debugf which provides good functionality
The debug file contains information such as session id,date and time,packages being called and the line number of each debug message and the debug message itself
Example usage is given below
This is used to intialize the debug, the first parameter 'ALL' meaning all modules(can be function,procedure or package etc) and SYSTEM meaning the schema i want to debug
debug.init(p_modules => 'ALL',p_file =>'C:\debugf123\temp\test.txt',p_user =>'SYSTEM',p_show_date => 'YES',p_date_format =>'DD/MM/YYYY HH24:MI:SS',p_name_len => 30,p_show_sesid => 'YES');
This one works like printf in C and the maximum you can give is 10 parameters where v_word1 is a parameter
debug.f('the first is %s',v_word1);
This is same as debug.f but here you can give more than 10 parameters
debug.fa('the third is %s and %s',debug.argv(v_word1,v_amount));
The source code for this package is available at
http://gerardnico.com/wiki/database/oracle/debugf
OWA_UTIL.WHO_CALLED_ME(
owner OUT VARCHAR2,
name OUT VARCHAR2,
lineno OUT NUMBER,
caller_t OUT VARCHAR2);
Have you tried remote debugging? Here's how you can do it in SQL Developer:
1) Reference:
http://sueharper.blogspot.ca/2006/07/remote-debugging-with-sql-developer_13.html
2) User privileges:
grant EXECUTE on DBMS_DEBUG_JDWP to USERXX;
grant DEBUG CONNECT SESSION to USERXX;
grant DEBUG ANY PROCEDURE to USERXX;
3) Set Remote Debug on USERXX connection in SQL Developer:
Port: 80 (use 4000 if not blocked by firewall)
Local Address: IP address of your local machine
4) Compile code (package, procedure or function) in USERXX in SQL Developer for debug
5) Set breakpoints in code
6) On the remote (this could be your application invoking the PLSQL code):
before invoking the PLSQL code run/include the following:
DBMS_DEBUG_JDWP.CONNECT_TCP( 'IP address in 3', port in 3 ) when this is run SQL developer will switch to debug mode.
7) Run application or invoke procedure from remote as USERXX
8) SQL developer stops at first breakpoint, step into, view/change values and etc.

SQL Server Agent 2005 job runs but no output

Essentially I have a job which runs in BIDS and as as a stand lone package and while it runs under the SQL Server Agent it doesn't complete properly (no error messages though).
The job steps are:
1) Delete all rows from table;
2) Use For each loop to fill up table from Excel spreasheets;
3) Clean up table.
I've tried this MS page (steps 1 & 2), didn't see any need to start changing from Server side security.
Also SQLServerCentral.com for this page, no resolution.
How can I get error logging or a fix?
Note I've reposted this from Server Fault as it's one of those questions that's not pure admin or programming.
I have logged in as the proxy account I'm running this under, and the job runs stand alone but complains that the Excel tables are empty?
Here's how I managed tracking "returned state" from an SSIS package called via a SQL Agent job. If we're lucky, some of this may apply to your system.
Job calls a stored procedure
Procedure builds a DTEXEC call (with a dozen or more parameters)
Procedure calls xp_cmdshell, with the call as a parameter (#Command)
SSIS package runs
"local" SSIS variable is initialized to 1
If an error is raised, SSIS "flow" passes to a step that sets that local variable to 0
In a final step, use Expressions to set SSIS property "ForceExecutionResult" to that local variable (1 = Success, 0 = Failure)
Full form of the SSIS call stores the returned value like so:
EXECUTE #ReturnValue = master.dbo.xp_cmdshell #Command
...and then it gets messy, as you can get a host of values returned from SSIS . I logged actions and activity in a DB table while going through the SSIS steps and consult that to try to work things out (which is where #Description below comes from). Here's the relevant code and comments:
-- Evaluate the DTEXEC return code
SET #Message = case
when #ReturnValue = 1 and #Description <> 'SSIS Package' then 'SSIS Package execution was stopped or interrupted before it completed'
when #ReturnValue in (0,1) then '' -- Package success or failure is logged within the package
when #ReturnValue = 3 then 'DTEXEC exit code 3, package interrupted'
when #ReturnValue in (4,5,6) then 'DTEXEC exit code ' + cast(#Returnvalue as varchar(10)) + ', package could not be run'
else 'DTEXEC exit code ' + isnull(cast(#Returnvalue as varchar(10)), '<NULL>') + ' is an unknown and unanticipated value'
end
-- Oddball case: if cmd.exe process is killed, return value is 1, but process will continue anyway
-- and could finish 100% succesfully... and #ReturnValue will equal 1. If you can figure out how,
-- write a check for this in here.
That last references the "what if, while SSIS is running, some admin joker kills the CMD session (from, say, taskmanager) because the process is running too long" situation. We've never had it happen--that I know of--but they were uber-paranoid when I was writing this so I had to look into it...
Why not use logging built into SSIS? We send our logs toa database table and then parse them out to another table in amore user friendly format and can see every step of everypackage that was run. And every error.
I did fix this eventually, thanks for the suggestions.
Basically I logged into Windows with the proxy user account I was running and started to see errors like:
"The For each file enumerator is empty"
I copied the project files across and started testing, it turned out that I'd still left a file path (N:/) in the properties of the For Each loop box, although I'd changed the connection properties. Easier once you've got error conditions to work with. I also had to recreate the variable mapping.
No wonder people just recreate the whole package.
Now fixed and working!

What does "%%DatabaseEx" do in TSQL?

I was looking at the source of sys.sp_dbcmptlevel in SQL Server 2005.
In the source, there is this line I do not understand how it works.
EXEC %%DatabaseEx(Name = #dbname).SetCompatibility(Level = #input_cmptlevel)
It doesn't appear that DatabaseEx is a stored procedure.
-- does not return any result
select *
from sys.procedures
where [name] like '%DatabaseEx%'
So my questions are
What is DatabaseEx and what does it do?
What is %% before DatabaseEx?
I think the best answer here is that it's not documented, and not supported, so don't rely on it. While it's interesting to know how SQL Server works internally, anything you do with that knowledge has the potential to break in a future hotfix, service pack or release.
Interesting find.
System SP's also refer to %%Object, %%Relation, %%ColumnEx, %%LinkedServer, %%Owner, %%CurrentDatabase(), %%ErrorMessage, %%Module, %%DatabaseRef, %%LocalLogin, %%Alias, %%ServerConfiguration, %%IndexOrStats, %%ScalarType (etc)
My interpretation is that the %%() retrieves some kind of (COM?) object based on filter criteria, followed by a method call.
-- Note: database #dbname may not exist anymore
-- Change compatibility level
-- If invoke gets error, exception will abort this proc.
EXEC %%DatabaseEx(Name = #dbname).SetCompatibility(Level = #input_cmptlevel)
it looks like a way to refer to a variable database as an object and make config changes