What is the difference between pre-compile and bind for a COBOL DB2 program.
How does syntax check differ in both the processes.
If we give the wrong column name in our code, then in which process it will fail.
It seems you need to do some study in the Db2 Knowledge Centre.
A pre-compile action creates a bindfile, containing the static SQL present in the source code (i.e the sections of code with EXEC SQL statements in your COBOL), in addition to a compilable form of the source code that contains the non-SQL logic and data (your PROCEDURE DIVISION and DATA DIVISION etc).
A bind action uses both the bindfile and the database to create a package inside the database which is the executable form of the bindfile contents. The package contains sections corresponding your your EXEC SQL blocks for static SQL.
Later, when the built (i.e. compiled and linked) application executes, and wants to use the database, this will cause sections of the package to be loaded from the database catalog (or read from cache) and executed by the database manager to deliver the required actions.
As each command (precompile, vs bind) serves a different purpose, the syntax varies , and also can vary with the Db2-server platform (Z/OS , i-series, Linux/Unix/Windows) and version.
Refer to the free Db2 Knowledge Center for your version of Db2 and your Db2-server platform (separate different documentation Knowledge Center websites exist for Db2-for-Z/OS, Db2 for i-series, Db2-for-Linux/Unix/Windows ).
Related
Is there a way to call a program from db2 interactive SQL in as400 (strsql)? this program receives an argument by reference and modify it's content. In CL, you simply call it like this:
call myprogram 12345
I need to be able to call it in interactive SQL, Is there any way or workaround to do this? like launching an OS command? for example in C you do system("your system command"). I couldn't find anything related to it.
STRSQL supports the SQL CALL statement.
The best option is to define the program as External SQL Stored procedure
--note
----- numeric-->zoned decimal
----- decimal-->packed decimal
CREATE PROCEDURE MYLIB.MYPROGRAM_SP
(IN number numeric(5,0))
LANGUAGE RPGLE
EXTERNAL NAME 'MYLIB/MYPROGRAM'
PARAMETER STYLE GENERAL;
Then you can
CALL MYLIB.MYPROGRAM_SP(12345)
Technically, every *PGM object on the IBM i is a stored procedure. You can call it without explicitly defining it as shown above. But assumptions are made about the parms in that case. It's much better to provide the DB with the interface definition.
Note that STRSQL is a 20 year old tool, it has various limitations including not supporting OUT or INOUT parameters of stored procedures.
A much better choice is to use the Run SQL Scripts component of IBM's Access Client Solutions (ACS)
Embedded SQL application for DB2LUW is developed in following steps:
db2 prep
db2 bind
Assume we have 2 DB2LUW nodes and DDL are identical for both nodes. When switching DB2LUW node, is precompilation for new node necessary? Or is it possible to start from binding by using the bind file generated when precompiled for the first node?
I mean is it possible to bind in the following way?
[for node1]
1. db2 prep
2. db2 bind
[for node2]
db2 bind by using bind file generated at step1 for node1?
Any comments are greatly appreciated!
It helps to use clearer terminology when asking for help.
If by 'node1' and 'node2' you mean different copies of the same database, possibly with different data, but the same DDL then you do not need to precompile again, you can simply bind using the previously generated bindfiles. This assumes both databases use the same platform of Db2. This is common when promoting embedded-SQL code between environments (development, various-testing, pre-production, production etc.). Any external routines need their deployables promoted appropriately. Always ensure that runstats are appropriate before you bind.
If your 'node1' and 'node2' are part of a High-Availability solution (either active:passive on failover/failback, or primary:standby after takeovers, or purescale-members), then it is the same database so you don't need to rebind. You can rebind if you want to - but not essential.
I am trying to create a trigger that sends an email based on a database event, specifically, when a record is INSERTed in a certain table, I want an email stating that fact to go to the SysAdmin.
I can successfully do the following from a SQL window in iSeries Navigator:
CL:SNDDST TYPE(*LMSG)
TOINTNET(('sysadmin#mycompany.com'))
DSTD('this is the Subject Line')
LONGMSG('This is an Email sent from iSeries box via Navigator')
...and an email gets sent. Which means that the necessary SMTP stuff is there and working.
So all I'm trying to do is encapsulate this code, perhaps with some data changes (e.g. "A record has been added to the XYZ table on whatever-the-sysdate-is"). Navigator has some tantalizing examples that call CL to do some plain-vanilla things, but no clue as to how to make it work in a trigger. I know how to write triggers that do "database stuff", but not this CL stuff. And this is iSeries DB2, so I don't have access to UTL_MAIL.
I know next to nothing about CL, DDS or other iSeries internals... I would prefer not to have to create an external Java program, but will do that as a last resort...but even then, I'm having a hard time finding straightforward examples.
thanks in advance.
First off, note that SNDDST isn't the best choice for internet mail from the IBM i. Basically, SNDDST is a relic from the SNADS networking days that IBM hacked into supporting SMTP emails. There are free alternatives, or if you're reasonably current on fixes for 7.1 then you should have the Send SMTP E-mail (SNDSMTPEMM) command available.
The Run SQL Scripts window of iNav does indeed support CL commands using the CL: prefix. But that's not the same thing as having the query engine itself understand CL.
The CL: prefix isn't going to work inside an SQL trigger.
You could however,use the QCMDEXC stored procedure to call a CL command. But I wouldn't necessarily call that the best option.
The IBM i supports using "external" stored procedures and triggers. Theoretically, you could use a CL program that invokes the SNDSMTPEMM command directly. But given you desires to include data from the table, I wouldn't recommend that approach as you'd be tied to the table structure.
Instead, create your own UTLMAILSND CL program that invokes SNDSMTPEMM. Then defined the UTLMAILSND program as an external stored procedure (you can even give it a longer SQL name of UTIL_MAIL_SEND).
Now you can call your UTIL_MAIL_SEND() procedure from your SQL trigger.
You need to try the SNDSMTPEMM command. It's like sliced bread compared to SNDDST TYPE(*LMSG) It supports HTML too which makes for a lot of fun.
Yes, I used SNDSMPTEMM (skipping the html for now...).
One big note, however: using this command in a CL program doesn't work when being called from SQL. I had to change it to a CLLE program.
So the final answer is as follows: a) an INSERT trigger on the table in question, which calls: b) an (external) PROCEDURE created in the database, which in turn calls: c) the compiled CLLE program object. Works like a charm.
p.s. I create the whole body of the email in the INSERT trigger, and pass it along, eventually to the CLLE program. This allows me to have just this one CLLE program to report on any INSERT/UPDATE/DELETE anywhere in the database.
How to run two sub programs from a main program if both are db2-cobol programs?
My main program named 'Mainpgm1', which is calling my subprograms named 'subpgm1' and 'subpgm2' which are a called programs and I preferred static call only.
Actually, I am now using a statement called package instead of a plan and one member, both in 'db2bind'(bind program) along with one dbrmlib which is having a dsn name.
The main problem is that What are the changes affected in 'db2bind' while I am binding both the db2-cobol programs.
Similarly, in the 'DB2RUN'(run program) too.
Each program (or subprogram) that contains SQL needs to be pre-processed to create a DBRM. The DBRM is then bound into
a PLAN that is accessed by a LOAD module at run time to obtain the correct DB/2 access
paths for the SQL statements it contains.
You have gone from having all of your SQL in one program to several sub-programs. The basic process
remains the same - you need a PLAN to run the program.
DBA's often suggest that if you have several sub-programs containing SQL that you
create PACKAGES for them and then bind the PACKAGES into a PLAN. What was once a one
step process is now two:
Bind DBRM into a PACKAGE
Bind PACKAGES into a PLAN
What is the big deal with PACKAGES?
Suppose you have 50 sub-programs containing SQL. If you create
a DBRM for each of them and then bind all 50 into a PLAN, as a single operation, it is going
to take a lot of resources to build the PLAN because every SQL statement in every program needs
to be analyzed and access paths created for them. This isn't so bad when all 50 sub-programs are new
or have been changed. However, if you have a relatively stable system and want to change 1 sub-program you
end up reBINDing all 50 DBRMS to create the PLAN - even though 49 of the 50 have not changed and
will end up using exactly the same access paths. This isn't a very good apporach. It is analagous to compiling
all 50 sub-programs every time you make a change to any one of them.
However, if you create a PACKAGE for each sub-program, the PACKAGE is what takes the real work to build.
It contains all the access paths for its associated DBRM. Now if you change just 1 sub-program you
only have to rebuild its PACKAGE by rebinding a single DBRM into the PACKAGE collection and then reBIND the PLAN.
However, binding a set of PACKAGES (collection) into a PLAN
is a whole lot less resource intensive than binding all the DBRM's in the system.
Once you have a PLAN containing all of the access paths used in your program, just use it. It doesn't matter
if the SQL being executed is from subprogram1 or subprogram2. As long as you have associated the PLAN
to the LOAD that is being run it should all work out.
Every installation has its own naming conventions and standards for setting up PACKAGES, COLLECTIONS and
PLANS. You should review these with your Data Base Administrator before going much further.
Here is some background information concerning program preperation in a DB/2 environment:
Developing your Application
If I have 1 COBOL DB2 program which is calling 2 other COBOL DB2 sub programs, then how many DBRMs,Packages,Plans it will create? If I am changing any one of the sub program then do I need to recompile and bind all the programs?I am really confused with DBRMs,Plans and Packages.
Regards,
Manasi
Oh my... This is a huge topic so this
answer is going to be very simplified and therefore incomplete.
The answer depends somewhat on whether you are using the DB/2 pre-compiler or co-compiler. For this
answer I will assume you are using the pre-compiler. If you are using the co-compiler the
principle is pretty much the same but the mechanics are a bit different.
The goal here is to generate:
a Load module from your COBOL source
DB/2 Plan to provide your program with access paths into the DB/2 database
Everything in between just supports the mechanics of creating an appropriate DB/2 Plan
for your program to run against.
The Mechanics
Each program and/or sub-program containing DB/2 statements needs
to be pre-processed by the DB/2 pre-compiler. The pre-compiler
creates a DBRM (Data Base Request Module). The pre-compile also alters your source program by commenting
out all the EXEC SQL...END-EXEC statements and replaces them with specific calls to the DB/2 subsystem.
You then use the regular COBOL compiler to compile the code emitted by the pre-processor to produce an object module which you then link into an executable.
The DBRM produced by the pre-compile contains a listing of the SQL statements contained
in your program plus some other information that DB/2 uses to
associate these specific SQL statements to your program. The DBRM is typically written to
a permanent dataset (usually a PDS) and then input to
the DB/2 Binder where the specific access
paths for each SQL statement in your program are compiled into a form that DB/2
can actually use. The binder does for DB/2 roughly the same function as the compiler does for COBOL.
Think of the DBRM as your source code and the Binder as the compiler.
The access path information produced when the DBRM is bound
needs to be stored somewhere so that it can be located and used
when your program calls DB/2.
Where to put the binder output? Your options are to bind it into a Package or directly into a Plan.
The shortest route is to bind a group of DBRMs directly into a Plan.
However, as with many short cuts, this may not be the
most efficient thing to do (I will touch upon the reason later on).
Most larger systems will not bind DBRMs directly into Plans, they will bind into a Package. The bound
Package is stored within the DB/2 sub-system (same way a Plan is). What then is a Package?
A Package is a bound single DBRM. A Plan, on the other hand, typically contains the
access paths for multiple DBRMs.
Now we have a set of Packages, each Package contains the SQL access paths to its respective DBRM which
was derived from a given
program. We need to construct a Plan from these. To do this, a set of Bind Cards
is created, usually by your Data Base Administrator. Bind Cards are just a sort of "source code"
to the DB/2 Binder (they are not punched cards).
The Bind Cards define which Packages form
a given Plan. These are then submitted to the Binder which assembles them into a Plan. Note:
you may also hear mention of Collections, these are just named groupings of Packages that have
been defined by your DBA.
To summarize, we have the following process:
Program -> (Pre-Compiler) -> Modified Program -> (COBOL compiler) -> Object -> (Link) -> Load Module
-> DBRM -> (DB/2 Bind) -> Package
Bind Cards -> (DB/2 Bind) -> DB/2 Plan
Package(s) ->
The two fundamental outputs here are a Load Module (your executable COBOL program) and a DB/2 Plan. The Program
and Plan come together in your JCL where you have to give the Plan name somewhere within the EXEC statement
along with the program to run.
With this brief, and highly simplified, background, lets try to answer your questions:
How may DBRMs are created?
One DBRM per program containing SQL EXEC statements
How many Packages are created?
A package is constructed from one DBRM. There is a 1:1 correspondence between Source Program and Package
How many Plans are created?
Any given Package may be included in multiple Collections and or multiple Bind Card sets. This
means that a given Package may be included in multiple Plans.
If I change a program what is affected?
If you bind your DBRM directly into a Plan, then you must rebind every Plan that uses
that DBRM. This can be a very time consuming and error prone proposition.
However, if you bind your DBRM into a Package, then you only need to rebind that Package.
Since there is a 1:1 correspondence between Program and Package, only a single bind
needs to be done. The only time the Plan needs to be rebound is when a Package or Collection
is added or removed from the Bind Card set that defines it.
The advantage of using Packages should be clear from the above and this is why most
shops do not bind DBRMs directly into Plans, but use Packages instead.