Static SQL On DB2 For zOS Packages, Collections (Part2) English
Static SQL On DB2 For zOS Packages, Collections (Part2) English
(Part2)
(0:00 - 0:15)
For now, think of it just like a place to put the package. A collection in DB2 is kind of like
your load library where your actual load modules live. It's just when you compile it, you've
got to put it somewhere.
(0:16 - 0:21)
So a collection is an object in DB2. It literally is a collection of packages. It's just a place to
put the package.
(0:24 - 0:51)
The member name is the actual name of the programmer module that I'm binding. So I'm
going to take a program, or a DBRM called lotsa-sq1, and bind it and put it in a collection
called themis-cl, in this case. The DBRM library, so this program called lotsa-sq1, the DBRM
is going to be searched for in this DBRM library up top here.
(0:51 - 1:06)
And again, you could have multiple libraries concatenated. Typically, this one, you'll only
have one. So take a package called lotsa-sq1, bind it to a collection called themis-cl, on DB2
subsystem DB1a.
(1:07 - 1:18)
That's what this is going to end up looking like. Now, there's a bunch of other bind options.
I'm going to point out some of the more important ones here.
(1:19 - 1:43)
The qualifier says, what set of tables are we going to use? So on DB2 system DB1a, we may
actually have several different copies of the same tables. This is particularly true in test
environments. We may have one copy for unit testing, and one copy for integration testing,
and another copy for quality assurance.
(1:45 - 2:09)
You've got how many different levels of tests do you have? And some of those share, in the
shops I've been in anyway, some of those share the same DB2 subsystems. So the qualifier
on the bind says, any unqualified table references in the program will be qualified by Themis
82. Now, you can hard code qualifiers in your code, and that'll override this.
(2:10 - 2:24)
But the common practice here is to leave your table references in the program unqualified.
So in other words, I don't say select from themis82.emp, I say select from emp. It's a short
table name.
(2:25 - 2:48)
And then at bind time, DB2 resolves those references. And that means that I can bind it
against my unit test tables today, and then take the same DBRM and bind it against my
integration test tomorrow, and user acceptance test the next day, or whatever. I don't have
to decide which particular set of tables I want to go at until I do the bind.
(2:50 - 3:05)
So that's a qualifier, and that's one that you'll see used in almost every bind card that gets
written. Another one that's sort of interesting is the owner of the package. That has to do
with authorizations.
(3:06 - 3:27)
So one of the great things about static SQL is that we have a lot of control over
authorization. The people running this program, so a user comes along and subs a batch job
that runs this program, that person does not need to be authorized to do all the SQL in the
program. What they need is authorization to execute this package.
(3:29 - 3:50)
This owner ID here, this is the credentials that are going to be used to actually validate the
SQL in that package. So this owner needs quite a bit of authority. The owner needs, and that
is also tied to this other bind option called validate bind, which is usually what we want.
(3:51 - 4:03)
Validate run says, don't do all that checking until runtime. But the owner needs to be
authorized to bind a package. And the owner needs to be authorized to put the package in
the collection we're talking about here.
(4:04 - 4:28)
And the owner needs to be authorized to do all the SQL that's in the package. So the owner
on a bind has to be a fairly authorized individual. And it can be a person's user ID who's
submitting the bind, or it can be a secondary auth ID that whoever is actually submitting the
bind is attached to.
(4:28 - 4:43)
So in other words, your DBAs may grant authority not to you individually, but to a group
that you're in. If they grant it to a group, then you have to stick that group ID in this owner.
Now, you see a bunch of other bind options there that we're probably not going to talk
about today.
(4:44 - 4:55)
But I'm giving you the link here. Don't try and type that into your browser. But if you
download the slides from the website that I showed you a moment ago, you can click the
hyperlink.
(4:56 - 5:10)
If you were not here for the beginning and don't know the link I'm talking about, I'll put it on
the screen again at the end. It's themisinc.com slash webinars. You can download these
slides and then get to the hyperlinks inside it.
(5:11 - 5:20)
So lots of bind options. The documentation tells you about what they all are and what they
do. Basically controlling the behavior of this package when we run it.
(5:23 - 5:34)
Now, versioning. So we said a collection is a place to put a package. So if you look at my
query here, I'm just going out to the DB2 catalog to a place called sysibm syspackage.
(5:36 - 5:52)
And I'm saying I want to see all of the packages in a collection called themiscl, where the
package name is lotsa-sq1. And you actually see five of them here, which is really
interesting. You can't do this in a load library.
(5:52 - 6:00)
I said a collection is a little bit like a load library. Well, this is actually a little bit more flexible
than a load library. A load library can only have one copy of a program at a time.
(6:01 - 6:18)
But a collection actually can contain multiple versions. Now, remember, this goes all the
way back to the precompile, where I said version auto. That is what made these DBRMs bind
actually separate copies of this package or separate versions of this package every time I ran
the compile.
(6:19 - 6:36)
You see that version ID. If you use version auto in the precompiler, it just takes the
precompile timestamp and makes that the version ID. So you can tell a little bit of
something about when this thing was compiled by looking at its version.
(6:37 - 6:50)
And then you see the bind time. So a lot of people wonder, well, what's the difference? Why
would I have a different bind time than a version ID? And in most of mine, you can see
they're pretty close. You see, like, let's take this third one.
(6:51 - 7:12)
It was, the version is November 6, a few days ago, at 308.36. 308.36. I think that's actually
UTC or Greenwich Mean Time. So it standardizes the clock. You actually see the bind time.
(7:12 - 7:26)
The bind time is represented in local time. So me here in North America, I'm a few hours
behind UTC. So actually, it's a different day, right? The version is the 6th.
(7:26 - 7:30)
It actually was bound before it was versioned. That's interesting. And that's because of the
UTC thing.
(7:32 - 7:45)
You see that first copy there, though, that was versioned on the 6th wasn't actually bound
till the 7th. Well, that can be for a few reasons. Number one, I could take that DBRM and
bind it again.
(7:46 - 8:25)
Or I could do a rebind, which we're going to talk about a little bit later. So you see, I've got
multiple versions of this package. Now, when I run the program from the load library, what
is it going to do? Which one of these am I running? Well, that's going to be determined by
this consistency token that we talked about a little bit earlier.
(8:26 - 8:51)
So the consistency token is another thing that's in this package that we're seeing here. And
you see in my query, I've actually used the hex function in SQL to kind of unpack it, show it
to me as something I can read, rather than just on printable characters. And you see that
consistency token is different for each of these versions.
(8:51 - 9:11)
That is the thing that was generated by the precompile. That's going to be used to match up
which one of these I'm going to run. So in other words, if I run a load module that has a
consistency token of this whole thing ending in 931, well then, which version of this package
am I running? I'm running the middle one there, the third one.
(9:12 - 9:28)
If I send in a different load module and run it with a load module that contains the
consistency token ending in DE4, then I'm going to be running that last one. This is pretty
cool, actually. Versioning allows you to be really flexible with change control.
(9:28 - 9:40)
Number one, it means that I can roll this thing out before I'm ready to actually run it. I can
do the bind whenever I want. It also means that I can fall back pretty easily.
(9:41 - 10:14)
So in other words, and I know this never happens at any of your shops, but where I've
worked in the past, we've put new code into production and then found out that we didn't
really want it there and had to back it out. If you've made a backup of your load library from
before the deploy, all you got to do is substitute that load library with the old load module
in it. If your packages are versioned, the old one is still there, and it'll just start running that
one when you send in the old load library.
(10:15 - 10:35)
So versioning is a change control technique. That means I can stage code before I'm ready to
run it, and it means I can fall back pretty easily without recompiling. If you're not using
versioning, then you're going to have to either recompile the old source code or go find the
old DBRM and bind it again.
(10:37 - 10:52)
So this simplifies your change control quite a bit if you use versioning. I'd say probably half
the shops that I visit now still don't use versioning. It requires just a little bit more planning
and knowledge of what's going on inside here.
(10:54 - 11:27)
And it also requires you to do a little bit of your own cleanup, because DB2 never purges out
old versions automatically. So in other words, if this program is 20 years old and it's been
compiled 100 times in that course of that 20 years, you could have a lot of versions of it out
there. So in the shops I've been in that use versioning, we typically wrote some homegrown
thing to identify maybe we keep the last three or four or five versions of a program.
(11:28 - 11:42)
You probably need to keep more in test than you do in production, because people are
compiling all day every day in test. But in production, if you keep the last few, you're
probably good. But you are on your own to clean up old versions.
(11:42 - 11:54)
So that is one downside of versioning. It requires a little bit more planning and cleanup on
your part. But it also provides you a ton of flexibility with the way you handle change
control.
(11:58 - 12:13)
All right, so let's kind of talk about these other pieces of terminology that I've been dancing
around a little bit. So location is just simply a DB2 system, right? Within a DB2 system, in my
case, the location was DB1A. That's the DB2 I was connecting.
(12:16 - 12:37)
A collection, again, when I do a bind of a package, a collection is simply a place where the
package is going to live. It's a home for the package. A package is just one single, you know,
the DB2 executable stuff for a single COBOL module is a package.
(12:38 - 12:52)
A plan, well, we're going to, and we just talked about versioning. A plan is going to be the
thing that we need to reference at runtime. Now, we haven't talked about plans yet.
(12:52 - 13:16)
So let me back up in just a little tiny bit of history. You can't even do this anymore. But in the
old, old days, and we're talking about late 80s, early 90s, your only option when you were
going to run an application, when you run an application, when you actually, you know, run
a program, and I'll skip forward a few slides and show you what that looks like.
(13:17 - 13:26)
OK. When I run a program here, so here I'm running my program called lotsa-sq1, I give it a
plan. I don't tell it where the package is.
(13:27 - 13:54)
Specifically, I give it a plan. In the old days, that plan was one big, giant module inside DB2
that contained all of the SQL for everything I might call. So not just for this module, but if my
COBOL program called lotsa-sq1 makes a call to another module, my plan would need to
contain them both directly.
(13:56 - 14:25)
And another way of saying that is, if you had an application that was made up of 50 modules
and you recompiled program 27, the bind would have to bring in all 50 DBRMs, meaning the
one that changed plus the 49 that didn't. And we'd have to bind it all again together. So a
plan is not a modular way of doing things, but it is still what I point at at runtime.
(14:26 - 14:41)
Now these days, and beginning in version 10, that environment went away. And they said,
we have to start using packages. Packages are just a more modular way of dealing with
programs.
(14:41 - 14:54)
In other words, I bind a single program into a package. I still need a plan, though. What a
plan looks like today, you can see down here, we've got an example of a bind plan.
(14:55 - 15:26)
This is something that a DBA probably does once and then leaves alone. I'm saying I've got a
plan here called plan Z. And a plan today, rather than including DBRMs directly, will include
a package list, PK list. And what I'm saying here is that the plan called plan Z contains all of
the packages that are in collection X. Now I'm doing this with a wild card in that first
example, collection X dot everything, which is the way I like to do it.
(15:26 - 15:41)
We could get more granular than that, though. In this second example, I'm saying plan Z
only contains these three packages. So there may be other packages in a collection called
collection X, but this plan only looks at these three.
(15:44 - 15:55)
A plan could also contain stuff from more than one collection. So here I've got a more
sophisticated plan list or package list. I'm binding my plan.
(15:55 - 16:31)
It's still called plan Z. The package list is all of the packages in collection one and all of the
packages in collection two that begin with the letter P. You can think of a plan at runtime as
a step lib, sort of, for the packages. In other words, a step lib in your JCL, when you're
looking for load modules, you say look here first, then look there, then look the third place,
then look the fourth place. It's going to search each of those libraries in your step lib until it
finds the program that you're looking to run.
(16:32 - 16:48)
A plan in DB2 terms now with a package list does exactly the same thing. When I run a
program and I point it at plan Z, it's going to search for the package that I'm looking for in
collection one first. It'll look for all the packages in collection one.
(16:48 - 17:09)
If it doesn't find it there, it's going to look in collection two, but only the things that start
with P. And if it doesn't find it there, I'm going to get a minus 805. But it's just a search order
when looking for packages. So you can think of a plan as just directing traffic.
(17:09 - 17:26)
The plan doesn't contain actual executable code anymore. It just contains lists of places to
look for that actual executable code. So here I've got an example of an output of a bind
package on the left.
(17:27 - 17:41)
And on the right, you have the output of a bind plan that includes a package list. So this
particular plan says all of the packages in a collection called themis-cl. So a package is one
module.
(17:42 - 18:03)
A collection is a grouping of packages. And a plan is a search list, essentially a package list.
What collections do I look in at runtime to find my program? Now, as a practical matter,
most of the plans that I see are bound with collection.asterisk, meaning all of the packages
in this collection.
(18:04 - 18:21)
And by the way, it's not just the packages that are in that collection when I bind the plan,
but all of them that are there now and will ever be there. All right. We talked about the
qualifier a little bit.
(18:21 - 18:46)
If I say select from employee in my program, which employee table? You know, tables have
two-part names within a subsystem. Which employee table am I talking about there? Well,
it depends on how I bind the package. If I bind the package with a qualifier of test, then I'm
going to be selecting from test.employee. If I bind the package with a qualifier of prod, then
I'll be selecting from prod.employee. This is very good.
(18:46 - 19:02)
It's very good to leave your SQL unqualified in applications. It means that I don't have to
change the code when I go from my unit test to user acceptance test, quality assurance, to
production. All I'm doing is changing the qualifier on the bind and binding it in a new place.
(19:08 - 19:19)
Debugging. And when I teach this in a class environment, we actually spend a little bit of
time in workshop looking at this. But the output messages from the bind are not necessarily
the most friendly.
(19:21 - 19:33)
So when we get an error on the bind, all you're going to see is that thing at the bottom. And
don't let this message right here fool you. Using ODYED authority.
(19:33 - 19:44)
Sometimes people see that as, well, that's my error. That message actually comes out in
every bind. It's just letting you know, hey, that was the owner ID that you put on the bind.
(19:44 - 19:53)
This is the person's authority that I'm using. That is not the real error here. The real error is
an SQL code minus 206.
(19:54 - 20:16)
And if you look that one up in the book, or use QuickRef, a lot of you have QuickRef,
probably. But if you look that one up in the book, you're going to see a message something
like, column not found. Have a nice day, right? So if this program has 50 SQL statements in
it, well, how do I know which one? It gives you a statement number here.
(20:17 - 20:27)
Statement number 99. And remember how I said it assigns that statement number based on
the line number in the precompile listing where that statement occurred. So this is how I
match up.
(20:27 - 20:49)
I got a minus 206 at statement 99. You got to go back to your precompile listing, and you'll
see the actual statement. And it gives you a little bit of an idea of what is the problem,
right? What did it not like? And if you look at this, I think you see probably the problem, or
some of you notice the problem, that ws department is a COBOL host variable.
(20:50 - 21:04)
I forgot to put a colon in front of it in this case. Because I didn't put a colon in front of it, the
bind process treated it as if it were a column on the table. And because that column is not
found, I get the minus 206.
(21:06 - 21:17)
You see also the precompiler up at the top flagged that as a warning. And you probably got
a condition code 4 out of the precompile, meaning, yeah, this doesn't look quite right, but
whatever. The bind will figure it out.
(21:18 - 21:27)
So the bind is what actually gave you the hard error, and the bind actually fails. So this is
kind of important to know. You need a bunch of pieces to put together.
(21:28 - 21:47)
You need to know what the SQL code means, either quick ref it or look it up in the book.
And the statement number, go back to the precompiler to find out where the problem
actually was. One quick word on bind versus rebind, the bind process takes in a DBRM and
produces a package.
(21:49 - 22:05)
Rebind is another command in DB2, not so much used by developers, but I think it's
important to understand the distinction. A rebind does not take in a new DBRM. A rebind
just takes in the statements that are already in the package and rethinks them.
(22:07 - 22:15)
So when do I bind? Well, I bind when I have a new DBRM. We've compiled the program
again. I got a new DBRM, and now I want to bind it.
(22:15 - 22:31)
Or I'm pushing the program up to production or next level of test. We move the load
module over there, I'm going to have to move the DBRM and bind it. Rebind I will do when
the code didn't change, but I just want DB2 to rethink the statements.
(22:32 - 22:51)
So if we add an index or something, or we run run stats, or the DBA makes some change to
the environment, they drop and recreate a table that invalidates the package. Rebind just
says the code didn't change, the SQL didn't change, the consistency token didn't change. I
just want DB2 to rethink this package.
(22:52 - 23:03)
So rebind and bind are not the same. It's important to understand, at least have some idea
of what the difference is. When I recompile a program, I have to bind, not rebind.
(23:03 - 23:15)
And that's a little bit funky in the messaging. When I run the program, we looked at this
already. Here I'm using the TSO monitor to run the program.
(23:15 - 23:20)
This is one way of running a program in batch. There are other ways. This way is really
common, though.
(23:21 - 23:39)
I'm running the program called lotssq1, and I don't tell it where the package is directly. I tell
it what plan I want to use. And remember, the plan then will search its package list until it
finds a program with that name and a consistency token that is the same as the one in that
program.
(23:40 - 23:47)
Remember, I had multiple versions. I'm not specifying a version ID here. It'll run whichever
one matches this load module.
(23:53 - 24:11)
One quick word about negative 805, and then I'm going to be done. Minus 805 is every
developer's favorite SQL code, I think. It means that when I ran the load module, DB2 was
not able to find the appropriate package.
(24:17 - 24:31)
So when I get to the first SQL call in my program, the package list in my plan, Themis PL, will
be searched for a matching package. Consistency token is used to find the match. If I don't
find it, I get a minus 805.
(24:32 - 24:48)
And this tells you, here's the program I was trying to run, and this is the consistency token I
was looking for, and it spans the line. 1A3354FOX13ECHOFOXCHARLIE029. That is the
consistency token it was looking for.
(24:49 - 25:12)
If you want to figure out why it wasn't finding that, you can go out to the DB2 catalog and
look for a package with that consistency token and see if it's there. So it's kind enough to tell
you, this is the consistency token that was in the load module, and I wasn't finding a
package with that same token. And on this last slide here, I've given you some common
reasons why you get the minus 805.
(25:12 - 25:18)
Your compile worked, but the bind failed. Didn't get a package. So I have a load module, but
no package.
(25:18 - 25:32)
If you try and run the load module, it's not going to find it. A bind succeeded, but you put
the package in a collection that's not in your plan. So the bind could work, but if I put it in
the wrong place, then DB2 is not going to find it.
(25:33 - 26:04)
Did I bind to the wrong DB2 subsystem? Am I running with the wrong plan? Am I running
with the wrong load library that maybe has an old copy of the program that isn't matching
up to any current package in my package list? If versioning is not used, then somebody else
ran a bind and overlaid your package. So if you're versioning, somebody else running a bind
in your collection is not going to hurt you, because it doesn't overlay. We just add another
version.
(26:06 - 26:20)
If versioning is not being used, then every time we bind, we're overlaying the same copy of
the package. This is particularly problematic in test environments where we're trying to
share a collection with other people. You really need versioning in that case.
(26:20 - 26:35)
Otherwise, you're not going to be able to play nice with others. So these are just some
common reasons why you get that minus 805. Just keep in mind, it's just going through the
package list in the plan and looking for a matching package.
(26:35 - 26:48)
It has to match the package name and the consistency token in order to be a match. So
that's what I got. I got my email address up on the board as we wrap up here.
(26:48 - 27:02)
If you have any questions or comments, feel free to email me. bsimpson at themisinc.com. I
also would direct you to our website. That is www.themisinc.com slash webinars.
(27:03 - 27:24)
If you would like to download the slides from this presentation, look at the other webinars
that we've done. And then, as I said earlier, within a day or so, we will also have the replay
of this webinar out there. So if you found it helpful, or if you have friends that might benefit
from seeing this, you can direct them.
(27:25 - 27:37)
Again, www.themisinc.com slash webinars is the address. So thanks for spending part of
your day with me. Again, please feel free to contact me if you have any questions or
comments.
(27:38 - 27:40)
And enjoy the rest of your day.