Wednesday, October 9, 2013

DB2 for z/OS: Something You Might Not Know About Character String Literal Values

Here's something I imagine a lot of you (or programs written by you) do all the time: issue DB2 for z/OS-accessing SQL statements that contain character string literal values. Below is a query that I issued from Data Studio earlier today, targeting a table that I'd created on one of our test DB2 subsystems:

SELECT PRODUCT_ID, UNIT_SALES
  FROM PRODUCT_SALES
  WHERE PRODUCT_ID = 'A12345';


Now, a question for you: is that character string literal value, 'A12345', fixed-length or varying-length? Considering this from your point of view, you might answer, "Fixed length." After all, it's six characters, right? No more, no less. And if you look at it again a few minutes from now, it'll still be six characters. Guess what? From DB2's point of view, the value 'A12345' in the above statement is a varying-length character string. I'm not revealing any state secrets here -- check the DB2 10 for z/OS SQL Reference and you'll see, in the first sentence of the section on character string constants, the following:

"A character string constant specifies a varying-length character string."

Of course, even a seasoned mainframe DB2 professional is not likely to have committed the entire SQL Reference to memory, and in fact plenty of people are unaware of this little nugget of information. That's generally not a big deal, because it almost never matters. Why does it hardly ever matter? Because fixed-length and varying-length character strings are compatible for purposes of assignment and comparison in a DB2 for z/OS system. Take the previously referenced SELECT statement. The 'A12345' character string constant is, as noted, treated by DB2 as a varying-length value. The PRODUCT_ID column of my PRODUCT_SALES table is defined as CHAR(6) -- a fixed-length character column. Does that matter? No -- the query runs just fine. What if you have a stored procedure with an input parameter defined as CHAR(10), and you call the stored procedure with a 10-character (or shorter) literal value provided for that input parameter? Does that matter? No -- the CALL will work just fine. Same goes for a user-defined function invocation.

Alright, so I said that the fact that DB2 treats a character string constant as a varying-length value almost never matters. "Almost never" is not the same thing as "never." So, when does it matter? I'm aware of one case, which was recently brought to my attention by a DB2 for z/OS DBA who I've known for years. This individual was trying to create a column mask in a DB2 10 for z/OS new-function mode environment. His CREATE MASK statement looked something like this (I'm using table and column names other than the real ones):

CREATE MASK ABC.COL2_MASK
 ON ABC.MY_TABLE
 FOR COLUMN COL2 RETURN
   CASE
    WHEN (1 = 1)
     THEN '999999'
    ELSE '000000'
   END
   ENABLE;


When he issued that SQL statement, it failed with a -20474 SQL code, reason code 33, indicating that "The data type of the return expression is not the same as the  data type of the column on which the column mask is defined." This didn't make sense to my DBA friend, because COL2 was defined as CHAR(6), and he'd provided 6-character literal values in the RETURN clause of the CREATE MASK statement. In this situation, the problem was related to the fact that the character string literals in the SQL statement were treated as varying-length values by DB2. Why did that matter? Because, per the DB2 10 SQL Reference, one of the rules of column mask creation is as follows:

"The result data type, null attribute, data length, subtype, encoding scheme, and CCSID of the CASE expression must be identical to those attributes of the column that is specified by column-name."

Fixed-length character strings and varying-length character strings are two different DB2 data types. Thus, the -20474 error, with reason code 33. When the DBA changed the statement as shown below, it worked:

CREATE MASK ABC.COL2_MASK
 ON ABC.MY_TABLE
 FOR COLUMN COL2 RETURN
   CASE
    WHEN (1 = 1)

     THEN CAST('999999' AS CHAR(6))
    ELSE CAST('000000' AS CHAR(6))
   END
   ENABLE;


The statement also worked when coded as follows, because the CHAR scalar function returns a fixed-length character string representation of the argument (this from the DB2 10 SQL Reference, with emphasis added by me):

CREATE MASK ABC.COL2_MASK
 ON ABC.MY_TABLE
 FOR COLUMN COL2 RETURN
   CASE
    WHEN (1 = 1)

     THEN CHAR('999999')
    ELSE CHAR('000000')
   END
   ENABLE;



Recap time. 1) Character string literals in SQL statements are treated by DB2 for z/OS as varying-length values. 2) That almost never matters. 3) It matters when you want to create a mask for a fixed-length character column.

5 comments:

  1. Hi Robert,
    I have a small doubt.
    I could not see any Indexspaces entries in the catalog table SYSCOPY.
    When I queried the syscopy with OTYPE=I , I am able to find the directory Indexspace entries only, Please help me on this.
    Thanks

    ReplyDelete
    Replies
    1. By default, DB2 for z/OS indexes are created with COPY NO. In such cases, they are rebuilt -- not recovered -- when the underlying table space is recovered. It is very common for SYSCOPY to contain very few rows pertaining to indexes. If a lot of indexes in a DB2 for z/OS subsystem are defined with COPY YES, and they are regularly backed up, you will see a lot of index-related rows in SYSCOPY.

      Robert

      Delete
    2. Thanks a Lot Robert...

      But my question is not only related to Image copy.
      Whether DB2 tracks for any utility that ran on an "Indexspace into SYSCOPY" ? . Since we need to know when the last reorg(or any other utility) was done on particular Indexspace.

      Delete
    3. Use the SYSIBM.SYSINDEXSPACESTATS catalog table for that purpose. Check the values in columns such as REORGLASTTIME.This and other columns of the table are described in the DB2 for z/OS SQL Reference (http://publib.boulder.ibm.com/infocenter/dzichelp/v2r2/topic/com.ibm.db2z10.doc.sqlref/src/tpc/db2z_sysibmsysindexspacestatstable.htm).

      Robert

      Delete
    4. Thanks Robert ...

      Delete