JCL创建数据集是否已经存在

JCL to create dataset whether it already exists or not

我想写一些 JCL 来创建数据集,要求是:

  1. 如果数据集不存在,请创建它

以及:

  1. 如果数据集已经存在,覆盖它

  1. 如果数据集已经存在,什么也不做

据我了解,(1) 可以通过 DISP=NEW 来完成,(2) 通过 DISP=OLD,但是我无法从文档和我的课程中弄清楚 material 如何同时做。如果数据集存在,则 NEW 会抛出一个 JCL 错误;如果不存在,则 OLD 会抛出一个错误。我不知道该怎么做 (3)。

我知道有一些方法可以查询 JCL 中是否存在数据集,但我们还没有涉及到它,所以我认为没有它也是可能的?

我认为您正在寻找生成数据组。这不会 覆盖 现有数据集,但会在每次执行 JCL 时为您提供一个新数据集。

首先,您必须使用记录在案的 IDCAMS 命令创建生成数据组基础条目 here。这是一次性操作。

//MAKEGDG1 EXEC PGM=IDCAMS
//SYSPRINT DD  SYSOUT=*
//SYSIN    DD  *
 DEFINE GDG (NAME(MY.DSN) LIMIT(255))
//*

要使用它,您需要编写 JCL,例如...

//USEGDG1  EXEC PGM=IEFBR14
//DD001    DD  DISP=(NEW,CATLG,DELETE),
//             DSN=MY.DSN(+1),
//             SPACE=(...),
//             and so on

...其中 (+1) 表示在组内创建新一代。实际上创建的是一个名称为MY.DSN.G####V00的数据集,其中####是系统为你管理的序号,但你总是可以用MY.DSN(0)得到最新的一代。您可以使用 MY.DSN(-1).

的前一代到最新一代

需要注意一些,如果您在编码 MY.DSN 时未在括号中指定世代编号,您将获得所有现存的世代。

如果 GDG 不是您要查找的内容,您还可以在对新数据集进行分类的步骤之前编写一个 IDCAMS 步骤。 IDCAMS 步骤的目的是删除数据集。如果数据集不存在,IDCAMS DELETE 命令会给你一个错误的 return 代码(12,如果没记错的话),但你可以在这种情况下通过编码 IF MAXCC=12 THEN SET MAXCC=0 来修改它。

根据允许的额外限制进行更新

如果您想要创建数据集(如果它不存在)并追加(如果存在),可以使用DISP=(MOD,CATLG) 来完成。我不相信有一种方法可以在不使用 IDCAMS 或编写基本上完成 IDCAMS DELETE 所做的事情的 clist 或 Rexx 程序的情况下实现您所说的目标。

您可以编写代码 DISP=(NEW,CATLG) 并在数据集已存在的情况下让作业失败。这是一件糟糕的事情,但我认为它符合您的标准。

我现在无法对此进行测试,但您可以试试...

//CKEXIST1 EXEC PGM=IEFBR14
//DD001    DD  DISP=OLD,DSN=MY.DSN
//*
//IF001    IF  CKEXIST.RUN=TRUE THEN
//* step with DISP=OLD
//         ELSE
//* step with DISP=NEW
//IF001E   ENDIF

...但即使它有效,我仍然认为它很丑陋。这个想法是 IEFBR14 步骤不会执行,因为数据集分配会失败。 IF001 语句正在检查步骤 运行,我 认为 如果数据集不存在则测试为假,如果存在则为真。我不建议将其用于生产作业流。

@cschneids 是一个很好的解决方案;但是要执行 1 和 2 你可以做到

//CREATE   EXEC PGM=IEFBR14
//DD001    DD  DISP=(MOD,CATLG,DELETE),
//             DSN=MY.DSN,...
//*
//USEGDG1  EXEC PGM=MYPGM,COND=(0,NE)
//DD001    DD  DISP=OLD,
//             DSN=MY.DSN

对于选项 3,您可以使用 IDCAMS

用额外的步骤创建一个 jcl(我写 JCL 已经 21 年了,所以我会把确切的编码留给你)。

// step1 exec pgm=idcams
  rename my.dsn in my.otherdsn
/*
//step2 exec pgm=idcams, cond=(0, eq, step1)  rename successful: rename back
 rename my.otherdsn in mydsn
/*
//step3 exec pgm=IEFBR14, cond=(0, ne, step1) did not exist, create it
//mydsn dd my.dsn,disp(new,catlg), etc
/*
//step4a exec pgm=myprogram, parm='EXISTS", cond=(0, eq, step1)
// ....
//step4b exec pgm=myprogram, parm='NEW", cond=(0, ne, step1)
// ....

使用 myprogram 的参数来计算您的程序逻辑!

像这样的方法也对我们有用,可以自动恢复文件:第一步将 a 重命名为 b。如果失败,则作业已中止,因此 step2 恢复数据库。然后包含实际的工作 jcl。作业的最后一步将 b 重命名为 a.

通常我会在创建数据集之前创建一个删除数据集的步骤。虽然我使用 DISP=(MOD,DELETE)。 SPACE=(TRK,0) 实际上是 space 的空值,因为我们将删除 DSN 或在没有 space 的情况下分配以删除它。这与@bruce_martin 的答案之间的区别在于数据集创建与实际编写数据集的步骤相关联。

这意味着如果文件不存在则创建它,如果存在则使用它并且 DELETE 表示在步骤终止时将其删除。最终结果是在下一步之前删除 DSN,无论它是否存在。

这是一个例子,

//DEL0010  EXEC PGM=IEFBR14
//DSN2DEL  DD   DSN=dataset.to.write.to,DISP=(MOD,DELETE),
//              SPACE=(TRK,0),UNIT=SYSALLDA
//*
//STEP0010 EXEC PGM=MYPROG
//DSN2CR8  DD   DSN=dataset.to.write.to,DISP=(,CATLG,DELETE),
//              SPACE=...,UNIT=...

使用这种方法可以确保下一步没有数据集,因此您不必担心有条件的重启。