顯示具有 SQL 標籤的文章。 顯示所有文章
顯示具有 SQL 標籤的文章。 顯示所有文章

星期五, 11月 10, 2023

Auditting IPs accessing IBMi via port 446

    Port 446 is the DRDA port, QRWTLSTN is the job that is listening on that port, so a couple of ways I can think of:

  • 1) exit program

  • 2) look thru history log :  DSPLOG msgid(CPI3E34) job(QRWT*)

    CPI3E34    DDM job xxxx servicing user yyy on mm/dd/yy at hh:mm:ss (This can be suppressed with QRWOPTIONS)

    Distributed relational database messages

    QRWOPTIONS data area

  • 3) History of connections to IBM i
    https://www.ibm.com/support/pages/node/6212238

  • https://community.ibm.com/community/user/power/discussion/auditting-ips-accessing-ibmi-via-port-446
  •   -- category:Robert Berendt 
      select * 
      FROM TABLE (QSYS2.HISTORY_LOG_INFO(START_TIME => CURRENT DATE - 2 days
            )) AS X
      Where message_id='CPI3E34'
       and from_job_name like 'QRWT%'
      ORDER BY ORDINAL_POSITION desc;
      
    
      -- category: bryandietz
      --  find DRDA and ODBC like connections
      -- description: history log-find user from QZDASOINIT-QRWTSRVR
      SELECT Message_Timestamp
             ,From_User
             ,From_Job
             ,Message_Id
             ,MESSAGE_TEXT
          FROM TABLE(Qsys2.History_Log_Info(
          Start_Time => current_timestamp - 1 day,   -- pick your time frame
          End_Time =>  current_timestamp
          )) i
          WHERE  Message_Id in ('CPIAD09','CPI3E34')
           --  AND        MESSAGE_TEXT LIKE '%YOUR_USER%'  -- if needing to "audit" for a single user
      ;
    
    
    
      -- find ip from message_tokens
      -- category: Robert Berendt
      select trim(substring(message_tokens, 75, 15)) as IP_address, x.* 
      FROM TABLE (QSYS2.HISTORY_LOG_INFO(START_TIME => CURRENT DATE - 2 days
                    )) AS X
      Where message_id='CPI3E34'
        and from_job_name like 'QRWT%'
      ORDER BY ORDINAL_POSITION desc;
    
    
      -- find IP
      -- category: bryandietz
      --  find DRDA and ODBC like connections
      -- description: history log-find user from QZDASOINIT-QRWTSRVR
      SELECT Message_Timestamp
             ,From_User
             ,From_Job
             ,Message_Id
             ,MESSAGE_TEXT
             ,TRIM(SUBSTR(Message_Text,(LOCATE_IN_STRING(Message_Text, 'client', 1)+7),   -- start of IP
                                (LOCATE_IN_STRING(Message_Text, ' connected', 1) -
                                (LOCATE_IN_STRING(Message_Text, 'client ', 1)+7)           -- end of IP address
                                ))) AS IP_addr
          FROM TABLE(Qsys2.History_Log_Info(
          Start_Time => current_timestamp - 1 day,   -- pick your time frame
          End_Time =>  current_timestamp
          )) i
          WHERE  Message_Id in ('CPIAD09','CPI3E34')
           --  AND        MESSAGE_TEXT LIKE '%YOUR_USER%'  -- if needing to "audit" for a single user
      ;
      
    
      
      
      

星期四, 11月 09, 2023

2013-07-01 要如何於 SQL 中取用 UUID?(SQL UDF GENSYSUUID)


要如何於 SQL 中取用 UUID?(SQL UDF GENSYSUUID)

AS400 DB2 SQL 並不支援直接取用 UUID,而是須透過呼叫系統函式 _GENUUID 來產生,
下述 SQL UDF GENSYSUUID,產生 UUID (16 bytes)的 16 進位字串(32 bytes),提供直接於 SQL 中直接取用 UUID。



File  : QRPGLESRC

Member: GENSYSUUID

Type  : RPGLE

Usage : CRTBNDRPG GENSYSUUID


     **
     **  Program . . : GENSYSUUID
     **  Description : Generate UUID(16 bytes) to HexString(32 bytes)
     **  Author  . . : Vengoal Chang
     **  Published . : AS400ePaper
     **  Date  . . . : June 26, 2013
     **
     **
     **
     **  Programmer's notes:
     **
     ** CREATE FUNCTION QGPL.GENSYSUUID ( )
     **  RETURNS CHAR(32)
     **  LANGUAGE RPGLE
     **  SPECIFIC QGPL.GENSYSUUID
     **  NOT DETERMINISTIC
     **  NO SQL
     **  CALLED ON NULL INPUT
     **  EXTERNAL NAME 'QGPL/GENSYSUUID'
     **  PARAMETER STYLE SQL ;
     **
     ** Run STRSQL:
     ** Select GENSYSUUID ( )  from sysIBM.sysdummy1
     **
     ** CREATE TABLE QGPL/LICENSE (
     **            KEYUUID CHAR (32 ) NOT NULL,
     **            CUSTNAME VARCHAR (32 ) NOT NULL WITH DEFAULT,
     **            PRODUCT  VARCHAR (32 ) NOT NULL WITH DEFAULT  )
     **
     ** CREATE TRIGGER QGPL.LICENSE_BI BEFORE INSERT ON QGPL.LICENSE
     **         REFERENCING NEW N FOR EACH ROW MODE DB2ROW
     **         SET N.KETUUID = QGPL.GENSYSUUID();
     **
     ** INSERT INTO license(custname, product) VALUES('Oracle', 'DB2')
     ** select * from qgpl/license
     **
     **
     H Option( *NoSrcStmt ) DftActGrp( *No )
     H Debug
     **
      *
      * MI builtin to create a hex dump of a spot in memory
      *
     D hexdump         PR                  EXTPROC('cvthc')
     D  output                       32A
     D  input                        16A
     D  output_len                   10I 0 value

     D HexUUID         S             32A

     D UUID_template   Ds
     D  UtBytPrv                     10u 0 Inz( %Size( UUID_template ))
     D  UtBytAvl                     10u 0
     D                                8a   Inz( *Allx'00' )
     D  UUID                         16a
     **
     D GenUuid         PR                  ExtProc('_GENUUID')
     D UUID_template                   *   Value

     D pRtnUUID        S             32
     D pRtnUUIDIn      S              5I 0
     D sqlstate        S              5A
     d functname       S            517A   VARYING
     d specname        S            128A   VARYING
     d errormsg        S             70A   VARYING
     **
     C     *Entry        Plist
     C                   Parm                    pRtnUUID
     C                   Parm                    pRtnUUIDIn
     C                   Parm                    sqlstate
     C                   Parm                    functname
     C                   Parm                    specname
     C                   Parm                    errormsg

     C                   Callp     GenUuid( %Addr( UUID_template ))

     C                   Callp     HexDump( HexUUID :
     C                                      UUID    :
     C                                      %size(HexUUID)
     C                                    )

     C                   Eval      pRtnUUID = HexUUID
     C*                  dump
     **
     C                   Return





參考資訊:

Generate Universal Unique Identifier (GENUUID)



星期三, 11月 08, 2023

2012-05-22 如何於 CLP 中執行 SQL 指令 ? IBM new command RUNSQL from V6R1, V7R1


如何於 CLP 中執行 SQL 指令 ? IBM 於 V6R1, V7R1 提供 PTF 安裝新 RUNSQL 的 command

IBM 終於提供於 CL 中執行 SQL 指令,RUNSQL,於此之前已有許多使用者自行開發的類似指令也稱為 RUNSQL(使用 google AS400 RUNSQL),
若你有安裝其他版本時,使用時要注意,是使用到哪一個版本,可使用 WRKOBJ OBJ(*ALL/RUNSQL) TYPE(*CMD) 
找出所有 RUNSQL,其中系統提供的是 QSYS/RUNSQL,若與你現有程式有衝突時,你可視需要決定要繼續使用原自有版本,還是使用系統提供的版本。

系統提供的 RUNSQL 可以接受參數 SQL 指令長度達到 5000,遠大於現有其他使用者自製的 RUNSQL 或 RUNSQLSTM 的 SQL 參數長度,所以建議使用系統提供的 RUNSQL。


V6R1 PTF SI46477 APAR SE51168:
http://www-912.ibm.com/n_dir/NAS4APAR.NSF/c79815e083182fec862564c00079d117/017071ddebbcb95f862579b200424d1f?OpenDocument

V7R1 PTF SI46219 APAR SE51276:
http://www-912.ibm.com/n_dir/NAS4APAR.NSF/c79815e083182fec862564c00079d117/cad15fd4018943b1862579ba00424874?OpenDocument


File  : QCLSRC

Member: RUNSQLTST

Type  : CLP

Usage : CRTCLPGM yourlib/RUNSQLTST

        CALL RUNSQLTST '800000'
        此範例是將 QIWS/QCUSTCDT 客戶編號大於 800000 客戶資料,排序複製到 QTEMP,並將之客戶編號輸出到螢幕。
OS    : V6R1以上

Pgm          (&SELECT)

     Dcl        &SELECT     *CHAR 6
     Dcl        &CUSNUMC    *CHAR 6
     Dcl        &SQLSTM     *CHAR 5000

     Dclf       QCUSTCDT

/*-- Global error monitoring:  --------------------------------------*/
     MonMsg     CPF0000     *N         GoTo Error

     ChgVar     &CUSNUMC    &SELECT

     ChgVar     &SqlStm     'drop table qtemp/cust'

     RunSql     Sql(&SqlStm) Commit(*None)
     MonMsg     SQL0204

     ChgVar     &SqlStm                                             +
                 (                                                  +
                  'Create table qtemp/cust as (' *CAT               +
                  'select * from qiws/qcustcdt where cusnum <' *CAT +
                  &cusnumc *BCAT                                    +
                  'order by cusnum' *cat                            +
                  ') with data'                                     +
                 )
     RunSql     Sql(&SqlStm) Commit(*None)

     OvrDbf     File(QCUSTCDT) ToFile(Qtemp/Cust) LvlChk(*NO)

Read:
     Rcvf
     MonMsg     CPF0864 *N GOTO EOF

     ChgVar     &CUSNUMC &CUSNUM
     SndPgmMsg  Msg('READ CUSNUM=' *CAT &CUSNUMC)

     Goto Read

Eof:

 Return:
     Return

/*-- Error processor ------------------------------------------------*/
Error:
     Call      QMHMOVPM    ( '    '                   +
                             '*DIAG'                  +
                             x'00000001'              +
                             '*PGMBDY   '             +
                             x'00000001'              +
                             x'0000000800000000'      +
                           )

     Call      QMHRSNEM    ( '    '                   +
                             x'0000000800000000'      +
                           )
 EndPgm:
     EndPgm







2008-06-27 如何取得 SQL Job 所執行的最後一個 SQL statement?(Command RTVSQLINF with API QUSRJOBI Format JOBI0900)


如何取得 SQL Job 所執行的最後一個 SQL statement?(Command RTVSQLINF with API QUSRJOBI Format JOBI0900)

現在有許多程式會透過 ODBC,JDBC 方式連線至 AS/400 查詢或更新資料,而其所連線至 AS/400 的 Job 名稱為
QZDASOINIT,而當有程式當掉時,需要得知該 Job 所執行的最後一個 SQL statement為何,用以除錯及快數解決
錯誤時使用。所以我們需要透過 API QUSRJOBI Format JOBI0900 來擷取 Job 的最後一個 SQL statement。



File  : QRPGLESRC
Member: RTVSQLINF
Type  : RPGLE
Usage : CRTBNDRPG PGM(RTVSQLINF) TGTRLS(V5R1M0)
OS Version: V5R1

     **
     **  Program . . : RTVSQLINF
     **  Description : Retrieve Job last SQL statement
     **  Author  . . : Vengoal Chang
     **
     **  Date    . . : 2008/06/25
     **
     **  Compile and setup instructions:
     **    CrtRpgMod   Module( RTVSQLINF )
     **                DbgView( *LIST )
     **
     **    CrtPgm      Pgm( RTVSQLINF )
     **                Module( RTVSQLINF )
     **                ActGrp( *NEW )
     **
     **
     **-- Control specification:  --------------------------------------------**
     H DEBUG  OPTION(*SRCSTMT:*NODEBUGIO) DFTACTGRP(*NO) ACTGRP(*CALLER)

     FQSYSPRT   O    F  132        Printer UsrOpn
      *
     D RtvSQLInf       PR
     D  JobName                      10a   CONST
     D  UserName                     10a   CONST
     D  JobNumber                     6a   CONST
      *
     D RtvSQLInf       PI
     D  ParmJobName                  10a   CONST
     D  ParmUserName                 10a   CONST
     D  ParmJobNumber                 6a   CONST
      *
     D RtvJobSQL       PR                  EXTPGM('QUSRJOBI')
     D  RcvVar                    65535a   Options( *VarSize)
     D  RcvVarLen                    10i 0 Const
     D  FmtName                       8a   Const
     D  QualJobName                  26a   Const
     D  InternalJobID                16a   Const
     D  ErrorCode                          like(APIErr)
     D  ResetPfrStat                  1a   Const
      *
     D JOBI0900        DS         65535    Qualified
     D  NbrBytesRtn                  10i 0
     D  NbrBytesAvl                  10i 0
     D  JobName                      10a
     D  UsrName                      10a
     D  JobNbr                        6a
     D  InternalJobID                16a
     D  JobSts                       10a
     D  JobType                       1a
     D  JobSubType                    1a
     D  SvrMode                       1a
     D  rsvd                          1a
     D  OfsOpnCrs                    10i 0
     D  SizOpnCrs                    10i 0
     D  NbrOpnCrs                    10i 0
     D  OfsCurCrs                    10i 0
     D  LenCurCrs                    10i 0
     D  StsCurCrs                    10i 0
     D  CCSIDCurCrs                  10i 0
     D  RDBname                      18a
     D  SQLObj                       10a
     D  SQLLib                       10a
     D  SQLObjType                   10a
     D  rsvd2                         4a
     D  CumNbrFullOpn                20i 0
     D  CumNbrPsedOpn                20i 0
     D  OfsCurSQL                    10i 0
     D  LenCurSQL                    10i 0
      *
     D CursorInfo      DS                  Qualified
     D   ObjName                     10a
     D   ObjLib                      10a
     D   ObjType                     10a
     D   SQLCurName                  18a
     D   SQLStmtname                 18a
      *
     D APIErr          DS                  Qualified
     D  ErrSize                      10i 0 inz(%size(APIErr))
     D  ErrLen                       10i 0 inz(0)
     D  ErrID                         7a
     D  rsvd                          1a
     D  ErrData                     256a
      *
     D QualJobName     DS            26    Qualified
     D  JobName                      10a
     D  UserName                     10a
     D  JobNumber                     6a
      *
     D RcvSize         S             10  0 INZ(262140)
      *
     D i               S              5  0
     D StartPos        S              5  0
      *
     D SQLStmt         S          65535a   Varying
      *
     D SQLLineDS       DS
     D SQLLine                      100a   Dim(50)
     D SQLLineOut      S            100a
     D idx             S              5  0
     D totline         S              5  0
      *
     D HandleErr       PR
      *
      /Free
              QualJobName.JobName = ParmJobName ;
              QualJobName.UserName = ParmUserName ;
              QualJobName.JobNumber = ParmJobNumber ;

              RtvJobSQL( JOBI0900 :
        //          %Size(JOBI0900) :
                    RcvSize :
                    'JOBI0900' :
                    QualJobName :
                    *blanks :
                    APIErr :
                    '0' ) ;

          If APIErr.ErrLEN <> 0 ;

           HandleErr() ;

          else ;

           If JOBI0900.NBROPNCRS <> 0 ;

            StartPos = %dec(JOBI0900.OFSOPNCRS) + 1 ;

            for i = 1 to %dec(JOBI0900.NBROPNCRS) ;
               CursorInfo = %subst(JOBI0900 : StartPos) ;
               //dsply CursorInfo.SQLStmtname;
               StartPos = StartPos + %size(CursorInfo) ;
            endfor ;

           else ;

            CursorInfo.SQLCurName = '*NONE' ;

           endIf ;

           if JOBI0900.LENCURCRS > 0 ;
            SQLStmt = %subst(JOBI0900:%dec(JOBI0900.OFSCURCRS)+1:
                                    %dec(JOBI0900.LENCURCRS)) ;
            Open Qsysprt;
            SQLLineDS = SQLStmt;
            totline = %div(%len(%trim(SQLLineDS)) : %len(SQLLineOut));

            Except Title;
            if (%len(%trim(SQLLineDS)) > (totline * %len(SQLLineOut)));
              totline += 1;
            endif;
            For idx = 1 to totline;
              SQLLineOut = SQLLine(idx);
              Except detail;
            EndFor;
            Close Qsysprt;
            //Dump;

           endIf;

          endIf ;

              *inLR = *on ;
              return ;

      /End-Free
      *
     OQSYSPRT   E            Title          1
     O                                           12 'Jobname   '
     O                                           23 'User      '
     O                                           30 'Jobnbr'
     OQSYSPRT   E            Title          1
     O                       ParmJobName         12
     O                       ParmUserName        23
     O                       ParmJobNumber       30
     O                                           46 'SQL statement:'
     OQSYSPRT   E            detail         1
     O                       SQLLineOut         110
      *
     P HandleErr       B
     D HandleErr       PI
      *
      /Free

      /End-Free
      *
     P HandleErr       E



File  : QCMDSRC
Member: RTVSQLINF
Type  : RPGLE
Usage : CRTCMD CMD(RTVSQLINF) PGM(RTVSQLINF)

/*  ===============================================================  */
/*  = Command....... RtvSqlInf                                    =  */
/*  = CPP........... RtvSqlInf                                    =  */
/*  = Description... Retrieve Job last current SQL statement      =  */
/*  =                                                             =  */
/*  = CrtCmd      Cmd( RtvSqlInf )                                =  */
/*  =             Pgm( RtvSqlInf )                                =  */
/*  =             SrcFile( YourSourceFile )                       =  */
/*  ===============================================================  */
/*  = Date  : 2008/06/25                                          =  */
/*  = Author: Vengoal Chang                                       =  */
/*  ===============================================================  */
             CMD        PROMPT('Retrieve Job last SQL stmt')

             PARM       KWD(JOBNAME) TYPE(*NAME) MIN(1) PROMPT('Job +
                          name')

             PARM       KWD(JOBUSER) TYPE(*NAME) MIN(1) PROMPT('Job +
                          user')

             PARM       KWD(JOBNBR) TYPE(*CHAR) LEN(6) +
                          RANGE('000000' '999999') MIN(1) +
                          FULL(*YES) EXPR(*YES) PROMPT('Job number')


File  : QCLSRC
Member: RTVSQLINFC
Type  : CLP
Usage : CRTCLPGM RTVSQLINFC
        執行 CALL RTVSQLINFC 後,會產生 QSYSPRT 報表,檢視 QSYSPRT 報表,
        報表會顯示所有 QZDASOINIT job 所執行的最後一個 SQL statement。
        若無 QSYSPRT 報表產生,表示並無任何透過 ODBC 或 JDBC 連線進入
        系統執行 SQL statement。

/*  ===============================================================  */
/*  = Program: RtvSqlInfc                                         =  */
/*  = Type   : CLP                                                =  */
/*  = Description : Retrieve QZDASOINIT Job last SQL stmt         =  */
/*  ===============================================================  */
/*  = Date  : 2008/06/25                                          =  */
/*  = Author: Vengoal Chang                                       =  */
/*  ===============================================================  */

 RtvSQLINFC: PGM

             DCL        VAR(&JOBNAME)    TYPE(*CHAR) LEN(10)
             DCL        VAR(&USER)       TYPE(*CHAR) LEN(10)
             DCL        VAR(&CURUSR)     TYPE(*CHAR) LEN(10)
             DCL        VAR(&JOBNBR)     TYPE(*CHAR) LEN(6)
             DCL        VAR(&STATUS)     TYPE(*CHAR) LEN(10)
             DCL        VAR(&JOBTYPE)    TYPE(*CHAR) LEN(1)
             DCL        VAR(&SUBTYPE)    TYPE(*CHAR) LEN(1)

             DCL        VAR(&USP_NAME)   TYPE(*CHAR) LEN(10)
             DCL        VAR(&USP_LIB)    TYPE(*CHAR) LEN(10)
             DCL        VAR(&USP_QUAL)   TYPE(*CHAR) LEN(20)
             DCL        VAR(&USP_TYPE)   TYPE(*CHAR) LEN(10)
             DCL        VAR(&USP_SIZE)   TYPE(*CHAR) LEN(4)
             DCL        VAR(&USP_FILL)   TYPE(*CHAR) LEN(1)
             DCL        VAR(&USP_AUT)    TYPE(*CHAR) LEN(10)
             DCL        VAR(&USP_TEXT)   TYPE(*CHAR) LEN(50)
             DCL        VAR(&USP_REPL)   TYPE(*CHAR) LEN(10)
             DCL        VAR(&USP_RTNL)   TYPE(*CHAR) LEN(10)
             DCL        VAR(&USP_CHGATR) TYPE(*CHAR) LEN(16)
             DCL        VAR(&USP_ATRREC) TYPE(*CHAR) LEN( 4)
             DCL        VAR(&USP_ATRLEN) TYPE(*CHAR) LEN( 4)
             DCL        VAR(&USP_ATRKEY) TYPE(*CHAR) LEN( 4)
             DCL        VAR(&USP_ATRDTA) TYPE(*CHAR) LEN( 1)

             DCL        VAR(&API_USQUAL) TYPE(*CHAR) LEN(20)
             DCL        VAR(&API_JBQUAL) TYPE(*CHAR) LEN(26)
             DCL        VAR(&API_JBNAM)  TYPE(*CHAR) LEN(10)
             DCL        VAR(&API_USER)   TYPE(*CHAR) LEN(10)
             DCL        VAR(&API_JOBNR)  TYPE(*CHAR) LEN(6)
             DCL        VAR(&API_STATUS) TYPE(*CHAR) LEN(10)

             DCL        VAR(&STARTPOS)   TYPE(*CHAR) LEN(4)
             DCL        VAR(&DATALEN)    TYPE(*CHAR) LEN(4)
             DCL        VAR(&HEADER)     TYPE(*CHAR) LEN(150)
             DCL        VAR(&LST_OFFSET) TYPE(*DEC)  LEN(5 0)
             DCL        VAR(&LST_SIZE)   TYPE(*DEC)  LEN(5 0)
             DCL        VAR(&LST_DATA)   TYPE(*CHAR) LEN(4096)
             DCL        VAR(&LST_NBR)    TYPE(*DEC)  LEN(5 0)
             DCL        VAR(&LST_LEN)    TYPE(*DEC)  LEN(5 0)
             DCL        VAR(&LST_LENBIN) TYPE(*CHAR) LEN(4)
             DCL        VAR(&LST_POSBIN) TYPE(*CHAR) LEN(4)
             DCL        VAR(&LST_COUNT)  TYPE(*DEC)  LEN(5) VALUE(0)
             DCL        VAR(&TYPE) TYPE(*CHAR) LEN(1) VALUE('*')
             DCL        VAR(&NBRTORTN)  TYPE(*CHAR)  LEN(4)
             DCL        VAR(&KEYSTORTN) TYPE(*CHAR)  LEN(16)
             DCL        VAR(&KEY1     ) TYPE(*CHAR)  LEN(4)
             DCL        VAR(&KEY2     ) TYPE(*CHAR)  LEN(4)
             DCL        VAR(&KEY3     ) TYPE(*CHAR)  LEN(4)
             DCL        VAR(&KEY4     ) TYPE(*CHAR)  LEN(4)
             DCL        VAR(&SBSSYS   ) TYPE(*CHAR)  LEN(20)
             DCL        VAR(&WRKSTS   ) TYPE(*CHAR)  LEN(4)
             DCL        VAR(&MSGRPLY  ) TYPE(*CHAR)  LEN(1)
             DCL        VAR(&MSGTXT   ) TYPE(*CHAR)  LEN(256)
             DCL        VAR(&JOBTYPE  ) TYPE(*CHAR)  LEN(1)
             DCL        VAR(&RTNLIB   ) TYPE(*CHAR)  LEN(10)

             RTVJOBA    TYPE(&JOBTYPE)

             CHGVAR     VAR(%BIN(&NBRTORTN)) VALUE(4)
     /* 0101 -- Ststus as WRKACTJOB */
             CHGVAR     VAR(%BIN(&KEY1     )) VALUE(0101)
     /* 1906 -- Subsystem */
             CHGVAR     VAR(%BIN(&KEY2     )) VALUE(1906)
     /* 1307 -- Message Reply */
             CHGVAR     VAR(%BIN(&KEY3     )) VALUE(1307)
     /* 0305 -- Current user profile */
             CHGVAR     VAR(%BIN(&KEY4     )) VALUE(0305)
             CHGVAR     VAR(&KEYSTORTN) VALUE(&KEY1 *CAT &KEY2 *CAT +
                                              &KEY3 *CAT &KEY4)

             CHGVAR     VAR(&USP_NAME) VALUE('RTVSQLINFC')
             CHGVAR     VAR(&USP_LIB)  VALUE('QTEMP')
             CHGVAR     VAR(&USP_QUAL) VALUE(&USP_NAME *CAT +
                          &USP_LIB)
             CHGVAR     VAR(&USP_TYPE) VALUE('MYTYPE')
             CHGVAR     VAR(%BIN(&USP_SIZE)) VALUE(64000)
             CHGVAR     VAR(&USP_FILL) VALUE(' ')
             CHGVAR     VAR(&USP_AUT)  VALUE('*USE')
             CHGVAR     VAR(&USP_TEXT) VALUE('my user space')
             CHGVAR     VAR(&USP_REPL) VALUE('*YES')

             CHGVAR     VAR(%BIN(&USP_ATRREC)) VALUE( 1)
             CHGVAR     VAR(%BIN(&USP_ATRKEY)) VALUE( 3)
             CHGVAR     VAR(%BIN(&USP_ATRLEN)) VALUE( 1)
             CHGVAR     VAR(&USP_ATRDTA) VALUE('1')
             CHGVAR     VAR(&USP_CHGATR) VALUE( +
                            &USP_ATRREC *CAT &USP_ATRKEY *CAT +
                            &USP_ATRLEN *CAT &USP_ATRDTA)
LOOP:
 /* CREATE USER SPACE */
             CALL       PGM(QUSCRTUS) PARM(&USP_QUAL &USP_TYPE +
                          &USP_SIZE &USP_FILL &USP_AUT &USP_TEXT +
                          &USP_REPL X'00000000')

 /* SET AUTOMATIC EXTENDIBILITY */
             CALL       PGM(QUSCUSAT) PARM(&USP_RTNL &USP_QUAL +
                          &USP_CHGATR X'00000000')

             CHGVAR     VAR(&API_USQUAL) VALUE(&USP_QUAL)
             CHGVAR     VAR(&API_JBNAM)  VALUE('QZDASOINIT')
             CHGVAR     VAR(&API_USER)   VALUE('*ALL')
             CHGVAR     VAR(&API_JOBNR)  VALUE('*ALL')
             CHGVAR     VAR(&API_STATUS) VALUE('*ACTIVE')
             CHGVAR     VAR(&API_JBQUAL) VALUE(&API_JBNAM *CAT +
                          &API_USER *CAT &API_JOBNR)

             CALL       PGM(QUSLJOB) PARM(&API_USQUAL 'JOBL0200' +
                          &API_JBQUAL &API_STATUS X'00000000' +
                          &TYPE &NBRTORTN &KEYSTORTN)

             CHGVAR     VAR(%BIN(&STARTPOS)) VALUE(1)
             CHGVAR     VAR(%BIN(&DATALEN))  VALUE(140)

             CALL       PGM(QUSRTVUS) PARM(&API_USQUAL &STARTPOS +
                          &DATALEN &HEADER)

             CHGVAR     VAR(&LST_OFFSET) VALUE(%BIN(&HEADER 125 4))
             CHGVAR     VAR(&LST_SIZE)   VALUE(%BIN(&HEADER 129 4))
             CHGVAR     VAR(&LST_NBR)    VALUE(%BIN(&HEADER 133 4))
             CHGVAR     VAR(&LST_LEN)    VALUE(%BIN(&HEADER 137 4))

             CHGVAR     VAR(%BIN(&LST_POSBIN)) VALUE(&LST_OFFSET + 1)
             CHGVAR     VAR(&LST_LENBIN) VALUE(%SST(&HEADER 137 4))

             CHGVAR     VAR(&LST_COUNT) VALUE(0)

 LST_LOOP:   IF         COND(&LST_COUNT *EQ &LST_NBR) THEN(GOTO +
                          CMDLBL(LST_END))

             CALL       PGM(QUSRTVUS) PARM(&API_USQUAL &LST_POSBIN +
                          &LST_LENBIN &LST_DATA)

             CHGVAR     VAR(&JOBNAME) VALUE(%SST(&LST_DATA 1 10))
             CHGVAR     VAR(&USER)    VALUE(%SST(&LST_DATA 11 10))
             CHGVAR     VAR(&JOBNBR)  VALUE(%SST(&LST_DATA 21 6))
             CHGVAR     VAR(&STATUS)  VALUE(%SST(&LST_DATA 43 10))
             CHGVAR     VAR(&JOBTYPE) VALUE(%SST(&LST_DATA 53 1))
             CHGVAR     VAR(&SUBTYPE) VALUE(%SST(&LST_DATA 54 1))
      /* for status */
             CHGVAR     VAR(&WRKSTS ) VALUE(%SST(&LST_DATA 81 4))
      /* for subsystem */
             CHGVAR     VAR(&SBSSYS ) VALUE(%SST(&LST_DATA 101 20))
      /* for msgrply   */
             CHGVAR     VAR(&MSGRPLY) VALUE(%SST(&LST_DATA 137  1))
      /* for current user */
             CHGVAR     VAR(&CURUSR ) VALUE(%SST(&LST_DATA 157  10))


             RTVSQLINF  JOBNAME(&JOBNAME) JOBUSER(&USER) +
                          JOBNBR(&JOBNBR)

             CHGVAR     VAR(&LST_COUNT) VALUE(&LST_COUNT + 1)
             CHGVAR     VAR(%BIN(&LST_POSBIN)) +
                          VALUE(%BIN(&LST_POSBIN) + &LST_LEN)
             GOTO       CMDLBL(LST_LOOP)

 LST_END:    DLTUSRSPC  USRSPC(&USP_LIB/&USP_NAME)


 END:        ENDPGM
                



星期四, 11月 02, 2023

2002-08-12 如何從資料中取得數字欄位 Top 10 (前 10 名)的資料?


如何從資料中取得數字欄位 Top 10 (前 10 名)的資料?

一般最常從銷售或庫存資料中,取出前 10 名或前幾名作資料分析,AS/400 SQL 只提供
max() 函數取回最大值其語法如下:

select repid, amt from sales2 where amt =       
    (select max(amt) from sales2)

即可取出最佳銷售人員的資料及其銷售額,但要如何取出前幾名的資料呢?

假設您的資料樣本如下:

REPID        AMT 
JLM1      25,922 
NTP2     177,208 
LJS2      15,424 
CRC0     122,730 
HFH1      95,682 
JKS0      76,903 
JLM2      55,088 
JTL4      99,944 
MWS0      12,155 
BRS1      54,673

找第二位的語法如下:

select repid, amt from sales2 as a where 1 = 
  (select count(*) from sales2 as b where    
    b.amt > a.amt)  

這裡是利用 count(*) 筆數來決定,因為只有一筆資料比第二筆資料大,所以查詢結果如下:

REPID        AMT
CRC0     122,730

如果你想要找第三名,只要將 1 改為 2,語法如下:

select repid, amt from sales2 as a where 2 = 
  (select count(*) from sales2 as b where    
    b.amt > a.amt) 

查詢結果如下:

REPID        AMT
JTL4      99,944

如果你想列出前二名,改等號為大於等於,語法如下:

select repid, amt from sales2 as a where 1 >=
  (select count(*) from sales2 as b where    
    b.amt > a.amt)  

查詢結果如下:

REPID        AMT
NTP2     177,208
CRC0     122,730

接著你應該知道如何找前 10 名了,那就是將 1 改為 9 語法如下:


select repid, amt from sales2 as a where 9 >=
  (select count(*) from sales2 as b where    
    b.amt > a.amt)  





2002-06-25 如何將原有資料庫 Physical file DDS 格式轉成 SQL Script ?(Command GENDDL 利用 API QSQGNDDL)


如何將原有資料庫 Physical file DDS 格式轉成 SQL Script ?(Command GENDDL 利用 API QSQGNDDL)

利用 API  QSQGNDDL可將原有資料庫 Physical file DDS 格式轉成 SQL Script 。

File  : QRPGLESRC
Member: GENDDL01R
Type  : RPGLE
Usage : CRTBNDRPG GENDDL01R

      * Member GENDDL01R, type RPGLE
      *
      * Generate SQL DDL for a database object.
      * No warranty implied. Use at your own risk.
      *
      * To compile:
      * CRTBNDRPG PGM(XXX/GENDDL01R) +
      *    SRCFILE(XXX/QRPGLESRC) SRCMBR(GENDDL01R)

     H dftactgrp(*no) actgrp(*caller)

     D Template        ds           583
     D   DBObjName                  258
     D   DBObjLib                   258
     D   DBObjType                   10
     D   DBSrcFile                   10
     D   DBSrcLib                    10
     D   DBSrcMbr                    10
     D   Severity                    10i 0 inz(30)
     D   Replace                      1
     D   StmtFmtOpt                   1    inz('0')
     D   DateFmt                      3    inz('ISO')
     D   DateSep                      1
     D   TimeFmt                      3    inz('ISO')
     D   TimeSep                      1
     D   NamingOpt                    3    inz('SYS')
     D   DecimalPt                    1    inz('.')
     D   StdsOpt                      1    inz('0')
     D   DropOpt                      1    inz('0')
     D   MsgLvl                      10i 0 inz(0)
     D   CommentOpt                   1    inz('1')
     D   LabelOpt                     1    inz('1')
     D   HdrOpt                       1    inz('1')
     D TemplateLength  s             10i 0 inz(%size(Template))
     D TemplateFormat  s              8    inz('SQLR0100')
     D
     D ErrorDS         ds            16
     D   BytesProv                   10i 0 inz(15)
     D   BytesAvail                  10i 0
     D   ExceptionID                  7
     D
     D GenDDL          pr                  extpgm('QSQGNDDL')
     D    Template                  583
     D    Length                     10i 0
     D    Format                      8
     D    ErrorDS                    12
     D
     D*entry plist
     D GenDDL01R       pr                  extpgm('GENDDL01R')
     D   PIObjName                  258
     D   PIObjLib                   258
     D   PIObjType                   10
     D   PISrcFile                   10
     D   PISrcLib                    10
     D   PISrcMbr                    10
     D   PIReplace                    1
     D   PIError                      7
     D
     D GenDDL01R       pi
     D   PIObjName                  258
     D   PIObjLib                   258
     D   PIObjType                   10
     D   PISrcFile                   10
     D   PISrcLib                    10
     D   PISrcMbr                    10
     D   PIReplace                    1
     D   PIError                      7

     C
     C                   Eval      DBObjName = PIObjName
     C                   Eval      DBObjLib  = PIObjLib
     C                   Eval      DBObjType = PIObjType
     C                   Eval      DBSrcFile = PISrcFile
     C                   Eval      DBSrcLib  = PISrcLib
     C                   Eval      DBSrcMbr  = PISrcMbr
     C                   if        (PIReplace = '1') or
     C                             (PIReplace = 'Y') or
     C                             (PIReplace = 'y')
     C                   Eval      Replace = '1'
     C                   else
     C                   Eval      Replace = '0'
     C                   EndIf
     C
     C                   CallP     GenDDL (Template: TemplateLength:
     C                                     TemplateFormat: ErrorDS)
     C                   Eval      PiError = ExceptionID
     C                   Eval      *inlr = *on



File  : QCLSRC
Member: GENDDL01C
Type  : CLP
Usage : CRTCLPGM GENDDL01C

/******************************************************/
 /* Generate SQL DDL for a database object.           */
 /* No warranty implied. Use at your own risk.        */
 /*                                                   */
 /* To compile:                                       */
 /* CRTBNDCL PGM(XXX/GENDDL01C) SRCFILE(XXX/QCLSRC) + */
 /*SRCMBR(GENDDL01C) DFTACTGRP(*NO) ACTGRP(*NEW)      */
 /*****************************************************/
pgm (&obj &objlib &objtype +
     &srcfile &srclib &srcmbr &crtsrc &replace)

  dcl &obj     *char 258
  dcl &objlib  *char 258
  dcl &objtype *char  10
  dcl &srcfile *char  10
  dcl &srclib  *char  10
  dcl &srcmbr  *char  10
  dcl &replace *lgl    1
  dcl &crtsrc  *lgl    1
  dcl &error   *char   7

  monmsg cpf0000 exec(goto error)

  chkobj     obj(&srclib/&srcfile) objtype(*file) +
             aut(*objexist)
  monmsg cpf9801 exec(do)
     if &crtsrc +
         then( crtsrcpf (&srclib/&srcfile))
  enddo

  chkobj     obj(&srclib/&srcfile) objtype(*file) +
                mbr(&srcmbr) aut(*objexist)
  monmsg cpf9815 exec(do)
     if &crtsrc +
         then( addpfm  &srclib/&srcfile &srcmbr)
  enddo

  call genddl01r (&obj &objlib &objtype +
     &srcfile &srclib &srcmbr &replace &error)

  if (&error *eq ' ') do
     sndpgmmsg msgid(cpf9898) msgf(qcpfmsg) +
        msgdta('Generation of DDL was successful') +
        msgtype(*comp)
  enddo
  else do
     sndpgmmsg msgid(cpf9898) msgf(qcpfmsg) +
        msgdta('Generation of DDL failed. See +
           source member for errors') msgtype(*escape)
  enddo
  return
error:
     sndpgmmsg msgid(cpf9898) msgf(qcpfmsg) +
        msgdta('Generation of DDL failed with +
           an unexpected error') msgtype(*escape)
     monmsg cpf0000
endpgm



File  : QCMDSRC
Member: GENDDL
Type  : CMD
Usage : CRTCMD CMD(GENDDL) PGM(GENDDL01C)

/******************************************************/
 /* Generate SQL DDL for a database object.           */
 /* No warranty implied. Use at your own risk.        */
 /*                                                   */
 /* To compile:                                       */
 /* CRTCMD CMD(XXX/GENDDL) PGM(*LIBL/GENDDL01C) +     */
 /*    SRCFILE(XXX/QCMDSRC) SRCMBR(GENDDL)            */
 /*****************************************************/

CMD   PROMPT('Generate SQL DDL')
PARM  KWD(OBJECT) TYPE(*CHAR) LEN(258) MIN(1) +
        EXPR(*YES) PROMPT('Object name')
PARM  KWD(OBJECTLIB) TYPE(*CHAR) LEN(258) MIN(1) +
        EXPR(*YES) PROMPT('Object library')
PARM  KWD(OBJECTTYPE) TYPE(*CHAR) LEN(10) +
       RSTD(*YES) VALUES(TABLE VIEW ALIAS +
       CONSTRAINT FUNCTION INDEX SCHEMA TRIGGER +
       TYPE) MIN(1) EXPR(*YES) PROMPT('Object type')
PARM  KWD(SRCFILE) TYPE(*NAME) LEN(10) MIN(1) +
        EXPR(*YES) PROMPT('Source physical file')
PARM  KWD(SRCLIB) TYPE(*NAME) LEN(10) +
        SPCVAL((*CURLIB) (*LIBL)) MIN(1) +
        EXPR(*YES) PROMPT('Source library')
PARM  KWD(SRCMBR) TYPE(*NAME) LEN(10) +
        SPCVAL((*FIRST) (*LAST)) MIN(1) +
        EXPR(*YES) PROMPT('Source member')
PARM  KWD(CRTSRC) TYPE(*CHAR) LEN(4) RSTD(*YES) +
        DFT(*NO) VALUES(*YES *NO) SPCVAL((*YES +
        '1') (*NO '0')) EXPR(*YES) CHOICE('*YES, +
        *NO') PROMPT('Create file and/or member?')
PARM  KWD(REPLACE) TYPE(*CHAR) LEN(8) RSTD(*YES) +
        DFT(*APPEND) VALUES(*REPLACE *APPEND) +
        SPCVAL((*REPLACE '1') (*APPEND '0')) +
        EXPR(*YES) CHOICE('*REPLACE, *APPEND') +
        PROMPT('Replace or append to source?')





星期二, 10月 31, 2023

2001-07-17 如何讓你的 SQL 輸出讓人一目了然更有意義?


如何讓你的 SQL 輸出讓人一目了然更有意義?

使用 SQL Case 語法:

範例:

select tm01, tm02, tm10,              
  case                                
     when tm10 <=1000                 
       then 'Little'                  
     when tm10 > 1000 and tm10 <=10000
       then 'Midium'                  
     when tm10 > 10000                
       then 'Large'                   
       else '    '                    
  end as flag                         
  from imtmpf                         

其中 TM01,TM02 欄位是料號,TM10 是數量,
利用 CASE 函數將 TM10 依數值區間分類給一文字性敘述輸出,是不是較明白呢!

以下是輸出範例:

PART NO.         FREQUENCY      ACTUAL QTY   FLAG  
ATXN6058A        16.8            29,414.00   Large 
ATXN6058A        16.8            11,389.00   Large 
ATXN6062A        19.2            19,163.00   Large 
KFN6237A         109.65          10,000.00   Midium
ATXN6059B        14.85           28,770.00   Large 
ATXN6059B        14.85           24,287.00   Large 
ATXN6059A        14.85           11,872.00   Large 
ATFN6000A        45.1            10,000.00   Midium
ATFN6000A        45.1             6,000.00   Midium
KFN6138AB        73.35            6,000.00   Midium
KXN1476A         17.85            7,200.00   Midium




2001-07-13 如何於 SQL 中比較系統的 CURRENT DATE 與數字或文字性欄位?


如何於 SQL 中比較系統的 CURRENT DATE 與數字或文字性欄位?

SQL 的 CurDate 函數傳回一個 date 屬性的值,無法
直接拿來與數字或謂格式化的文字作比較,所以在比較
之前要先作型態轉換,有一個方法是使用 SQL/400
的 Year(),Month(),Day() 函數傳回數值,然後使用
數學運算式,產生數字性日期格式 YYYYMMDD,以下是
範例:

建立範例 Table TestDate:

Create Table TestDate (
  PKCol    Int             Primary Key,
  DecDate  Decimal( 9,0 ),
  CharDate Char( 8 ) )

輸入範例資料:

Insert Into TestDate Values ( 1, 20010711, '20010711' )

比較數字性欄位的SQL語法:

Select  *                                                         
  From  TestDate                                         
  Where DecDate =                                                
        100 * ( 100 * Year( CurDate() ) + Month( CurDate() ) ) + 
        Day( CurDate() )

比較文字性欄位的SQL語法:
使用 CAST 函數將數字轉換為文字

Select  *                                                         
  From  TestDate                                         
  Where CharDate = Cast(                                         
        100 * ( 100 * Year( CurDate() ) + Month( CurDate() ) ) + 
        Day( CurDate() ) As Char( 8 ) )

使用 CAST 函數時要注意 Month(),Day() 函數傳回
值若小於 10 時,CAST 函數轉換的結果會以 最後一
位為 空白,而非 0。


2001-06-18 如何於執行 SQL/400 查詢指令結果中加入最後一行 Total line 的功能?


如何於執行 SQL/400 查詢指令結果中加入最後一行 Total line 的功能?

1. STRSQL

2.

Select 'Item' As RowType,
       PartId,
       Price
  From Part  
Union  
Select 'Total'      As RowType,
       0            As PartId,
       Sum( Price ) As Price 
  From Part  
Order By RowType,
         PartId

3. PartID 是數字性欄位,若您的欄位是文字性,UNION 後之
0            As PartId
請改成
'0'            As PartId
      





2000-05-29 SQL -- 檔案中每筆資料間,有上下階關係,例如員工資,料中有含上司編號,上司亦為員工之一,要如何於一個 SQL 中,直接取得,下屬及上司資料



□ Tips :  SQL -- 檔案中每筆資料間,有上下階關係,例如員工資
料中有含上司編號,上司亦為員工之一,要如何於一個 SQL 中,直接取得
下屬及上司資料

--------------------------------

1. 員工資料
STRSQL 下 SQL command:
                                           
Create Table Employee                                                
       ( EmpId    Dec(7,0) Not Null,                                 
         FstNam   Char(20),                                          
         Mdlidl   Char(20),                                          
         LstNam   Char(30) Not Null,                                 
         MgrEmpId Dec(7,0),                                          
    Constraint EmpPK Primary Key( EmpId ) )                          
                                                                     
員工 Sample 資料
EmpID    FstNam    Mdlidl  LstNam     MgrEmpId                       
104681   Barb      L       Gibbens    898613                         
227504   Greg      J       Zimmerman  668466                         
668466   Dave      R       Bernard    709453                         
898613   Trish     S       Faubion    668466                         
899001   Rick      D       Castor     898613                         
                                                                     
2. 下 SQL Command 查詢上司名字
Select  Emp.EmpID,                                                   
        Emp.LstNam,                                                  
        Mgr.LstNam                                                   
  From  Employee Emp,                                                
        Employee Mgr                                                 
  Where Emp.MgrEmpID = Mgr.EmpID                                     
                                                                     
查詢結果 Sample Retrieval Using Join of a Table with Itself                   
Emp.EmpID   Emp.LstNam   Mgr.LstNam                                  
104681      Gibbens      Faubion                                     
227504      Zimmerman    Bernard                                     
898613      Faubion      Bernard                                     
899001      Castor       Faubion                                     


2000-04-21 如何於找出重複資料並將之刪除 ?(delete duplicated record)


 如何於找出重複資料並將之刪除 ?(delete duplicated record)

-- Usage : upload following code to source member
-- modify the library, file, key fields to your own, 
-- the use RUNSQLSTM command 
-- and specify the uploaded member

-- The initial DROP VIEWs will fail the
--   first time this runs because the views
--   do not exist yet.

DROP VIEW MYLIB/DUPV

;
DROP VIEW MYLIB/DUPV2

;
DROP VIEW MYLIB/DUPV3

;
DROP VIEW MYLIB/DUPV4

;

-- This creates a view that groups records and
--   then only includes keys that are duplicates
--   (or triplicates or more).
-- The CNT field reports the count of each set of
--   keys that is duplicated (HAVING count(*)>1).

CREATE VIEW MYLIB/DUPV (
    OrgKFld1,
    OrgKFld2,
    OrgKFld3,
    CNT
    ) AS SELECT
        OrgKFld1,
        OrgKFld2,
        OrgKFld3,
        count(*)
            FROM MYLIB/MyFile GROUP BY
                OrgKFld1,
                OrgKFld2,
                OrgKFld3
                    HAVING count(*)>1
;

-- This view is based on the view above which only
--   contains duplicated keys. That view is joined
--   to the original file to make the relative
--   record numbers available.

CREATE VIEW MYLIB/DUPV2 (
    KFld1,
    KFld2,
    KFld3,
    DRRN
    ) AS SELECT
        a.OrgKFld1,
        a.OrgKFld2,
        a.OrgKFld3,
        rrn(a)
            FROM MYLIB/MyFile a inner join MYLIB/DUPV B
              on a.OrgKFld1=b.OrgKFld1 and
                 a.OrgKFld2=b.OrgKFld2 and
                 a.OrgKFld3=b.OrgKFld3
;

-- This view is based on the view above. The purpose
--   is to find a single record number from a group
--   of duplicated (or triplicated or more) records.
--   By using the MAX() function, we get the highest
--   RRN() from a group. (We could use MIN() to get
--   the lowest.)

create view MYLIB/dupv3 (
    KFld1,
    KFld2,
    KFld3,
    mrrn
    ) as SELECT
        KFld1,
        KFld2,
        KFld3,
        max( DRRN )
            FROM MYLIB/dupv2 GROUP BY
                KFld1,
                KFld2,
                KFld3
;

-- This view provides direct access to the relative
--   record number of every record in the original
--   file. We cannot use the RRN() function to select
--   records in a delete unless we supply an actual
--   number such as WHERE RRN(MyFile)=1. So, we use
--   this view to turn RRN() into a column. Once we
--   have it as a column, we can reference it directly
--   in a DELETE statement.

CREATE VIEW MYLIB/DUPV4
    AS SELECT
        OrgKFld1,
        OrgKFld2,
        OrgKFld3,
        rrn(MyFile) AS DUPRRN
            FROM MYLIB/MyFile
;


-- This is where the actual deletes are done.
-- DO NOT run this statement unless FINDDUPES
--   has completed successfully.
--
-- The DUPV4 view references the original file
--   and exposes the record numbers. We can now
--   use a sub-SELECT to delete only records that
--   appear in our "duplicates" views.

DELETE FROM MYLIB/DUPV4
    WHERE DUPRRN in (
        SELECT MRRN FROM MYLIB/DUPV3
        )
;




星期四, 10月 05, 2023

IBM i SQL Catalog

 IBM i SQL Catalog

https://www.ibm.com/docs/en/i/7.5?topic=views-i-catalog-tables






Guru: Generating XML Using SQL – The Easy Way

Guru: Generating XML Using SQL – The Easy Way

https://www.itjungle.com/2023/09/18/guru-generating-xml-using-sql-the-easy-way/


Reference function:
XMLROW

ifs_write_UTF8

SQL sample:

SELECT
  xmlrow(
     cusnum as "CUSNUM", 
     TRIM(LSTNAM) as "LASTNAME",
     TRIM(INIT) as "INIT",
     TRIM(street) as "ADDRESS", 
     CITY as "CITY",
     STATE as "STATE",
     cast(digits(ZIPCOD) as varchar(6)) as "ZIPCODE"
   )
  FROM qiws.qcustcdt;
  

SELECT
  xmlrow(
     cusnum as "CUSNUM", 
     TRIM(LSTNAM) as "LASTNAME",
     TRIM(INIT) as "INIT",
     TRIM(street) as "ADDRESS", 
     CITY as "CITY",
     STATE as "STATE",
     cast(digits(ZIPCOD) as varchar(6)) as "ZIPCODE"
   OPTION ROW "CUSTOMER")
FROM qiws.qcustcdt;


RPGLE: GENXMLDEMO

**FREE
      ctl-opt dftactgrp(*NO);

      // ------------------------------------------------------
      // How to generate XML from Db2 and save that XML content
      // to the IFS as an ASCII text file.
      // ------------------------------------------------------

      dcl-s  content  SQLTYPE(CLOB:65532);
      dcl-s  start    int(10);
      dcl-s  ifsXMLFile varchar(1024) INZ('/home/<usrprf>/DEMO.XML');
      dcl-s  ifsUser  varchar(10) INZ(*USER);

      dcl-s parentNode varchar(16) inz('CUSTOMERS>');

      exec SQL SET OPTION commit=*NONE, NAMING=*SYS;
       *INLR = *ON;

       EXEC SQL DECLARE XC CURSOR for
          SELECT
            xmlrow(
               cusnum as "CUSNUM",
               TRIM(LSTNAM) as "LASTNAME",
               TRIM(INIT) as "INIT",
               TRIM(street) as "ADDRESS",
               CITY as "CITY",
               STATE as "STATE",
               cast(digits(ZIPCOD) as varchar(6)) as "ZIPCODE"
             OPTION ROW "CUSTOMER" )
         FROM QIWS.QCUSTCDT;

        EXEC SQL OPEN XC;

          // Read XML into a CLOB or you'll have a learning experience.
        EXEC SQL FETCH XC INTO :content;

        if (SQLState < '02000');
        ifsXMLFile  = %SCANRPL('<usrprf>' : %TrimR(ifsUser) : ifsXMLFile);
           // write out the starting/opening node to the IFS file
          EXEC SQL call qsys2.ifs_write_UTF8( :ifsXMLFile,
                                              '<' concat :parentNode );
          DOW (SQLState < '02000');
             // XMLROW returned via RPG IV SQL FETCH adds the  tag
             // We don't want that, so we skip past it using POSITION and SUBSTR
            EXEC SQL VALUES POSITION('<customer>', :content) INTO :START;
            EXEC SQL call qsys2.ifs_write_UTF8( :ifsXMLFile,
                                               substr(:content,:start));
            EXEC SQL FETCH XC INTO :content;
          enddo;
           // write out the ending/closing node to the IFS file
          EXEC SQL call qsys2.ifs_write_UTF8( :ifsXMLFile,
                                              '</' concat :parentNode );
        endif;
        EXEC SQL CLOSE XC;

星期四, 12月 02, 2010

How to find out indexes created or used during the execution of an SQL statement


Two methods as following:

1. Visual Explain tool, through iSeries Navigator.

2. - chgjob (4 0) *seclvl logclpgm(*yes)
- strdbg
- run your sql statement from interactive sql400
- quit sql400
- enddbg
and watch the joblog to see which indexes where used/built.

星期四, 5月 22, 2008