【问题标题】:How to bind a param inside of single quotes in PHP PDO for QCMDEXC如何在 PHP PDO 中为 QCMDEXC 绑定单引号内的参数
【发布时间】:2022-06-17 20:22:37
【问题描述】:

为了调用 IBMI 上的程序,我需要使用 QCMDEXC 来调用程序。我正在尝试做的一个例子是

$query = "CALL QCMDEXC('CALL PGM(IBMIPGM) PARM(?,?)')";

这些参数是程序的输入和输出变量。我如何使用以下方法绑定 pdo 参数:

$result->bindParam(1, $invalue, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 11);
$result->bindParam(2, $outvalue, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 11);

我意识到语句中的单引号造成了破坏,但为了使语句起作用,它需要这样构造,除非有我不知道的解决方法。

【问题讨论】:

  • 我花了一段时间试图帮助你解决这个问题,我浏览了 IMB 的文档,但我找不到任何东西。我假设这根本行不通,对吧?它是在 PHP 端还是 IBM 端失败?另外,如果您确实知道这一点,请发布答案,因为我敢打赌会有少数人拔掉头发,而您将成为救生员。

标签: php pdo db2


【解决方案1】:

好的,这里就讲这么多。 首先,QSYS2.QCMDEXC 过程只接受一个参数,该参数是要运行的命令的字符串,最长可达 32k。 其次,它不返回任何内容,甚至不返回状态(但如果失败会抛出 sql 错误)。 但是有一个 QSYS2.QCMDEXC 标量函数,它将返回整数 1 或成功或 -1 表示失败。你使用哪一个取决于你。 那么,如何使用 CL CALL PGM 调用程序并发送数据?

方案一) 如果只需要输入数据,可以在字符串中传递数据,还是取不回任何东西。 您可以为整个命令绑定一个变量:

$query = "CALL QCMDEXC(?)";
$result->bindParam(1, $cmd, PDO::PARAM_STR|PDO::PARAM_INPUT);
$cmd = "CALL PGM(IBMIPGM) PARM(INPARM)";

这会将文本“INPARM”传递给程序。 您将遇到的下一个问题是参数定界和转义字符。 IBM 参数以空格分隔,因此您可以传递两个或更多参数,它们之间有空格:

$cmd = 'CALL PGM(IBMIPGM) PARM(INPARM1 INPARM2)';

如果字符串中有空格,则必须用单引号分隔:

$cmd = "CALL PGM(IBMIPGM) PARM('INPARM1PART1 INPARM1PART2' INPARM2)";

到目前为止,还可以为字符串使用 php 双引号。如果我们使用 php 单引号,那么我们将不得不用反斜杠转义它们。更复杂的是,如果您不转义 IBM 参数,则字符串将被转换为大写。如果您的字符串包含单引号,则必须对其进行转义。 sql 和 CL 中的 IBM 转义字符是单引号。 下面是一个设置数据区的例子:

$query = "CALL QCMDEXC(?)";
$result->bindParam(1, $cmd, PDO::PARAM_STR|PDO::PARAM_INPUT);
$val = "Don''t forget to escape single quotes";
$cmd = "CHGDTAARA DTAARA(MYLIB/TESTDTA *ALL) VALUE('$val')";

您必须考虑嵌套字符串和转义,如果您不使用绑定变量,则必须双重转义:

$cmd = "CALL QCMDEXC('CHGDTAARA DTAARA(MYLIB/TESTDTA *ALL) VALUE(''Don''''t forget to escape single quotes'')')";

例如,如果您要使用 php 单引号:

$cmd = 'CALL QCMDEXC(\'CHGDTAARA DTAARA(MYLIB/TESTDTA *ALL) VALUE(\'\'Don\'\'\'\'t forget to escape single quotes\'\')\')';

你应该有一个功能来清理来自用户(甚至你自己)的任何数据,以防止注入攻击,因为绑定变量只是绑定命令字符串,它们可以注入命令字符串,所以清理和转义是非常重要!

选项 2) 使用 PHP XMLSERVICE 工具包。 您将能够添加输入和输出参数,您可以使用 PGMCall 方法直接调用程序,或者使用 CLCommand 方法运行 CL,该方法也返回数据。我知道它适用于 ibm_db2 和 odbc 连接器,但不确定您将哪个连接器与 PDO 一起使用。它还有一个实验性的 http 传输类型。

选项 3) 创建外部绑定过程 如果您调用的 *PGM 是 ILE,那么您可能可以为其创建外部绑定过程。 在sql中创建:

CREATE PROCEDURE PGM_PROC ( IN INVALUE CHAR(10), OUT OUTVALUE CHAR(10), INOUT INOUTVAL CHAR(20) ) 
LANGUAGE C
EXTERNAL NAME IBMIPGM
PARAMETER STYLE GENERAL;

然后可以绑定php变量直接调用:

$query = "CALL PGM_PROC(?,?)";

$result->bindParam(1, $invalue, PDO::PARAM_STR|PDO::PARAM_INPUT, 10);
$result->bindParam(2, $outvalue, PDO::PARAM_STR|PDO::PARAM_OUTPUT, 10);
$result->bindParam(3, $inoutvalue, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 10);

您也可以创建和编译您自己的 ILE 程序,如果需要,它可以调用 CL 命令等。也可以为 Java 和其他程序创建外部绑定过程。

资源: 申请服务:https://www.ibm.com/docs/en/i/7.5?topic=services-qcmdexc-procedure XMLSERVICE 工具包:http://www.youngiprofessionals.com/wiki/index.php/XMLSERVICE/XMLSERVICEhttps://github.com/IBM/xmlservicehttps://help.zend.com/zend/current/content/toolkit_service_class.htm 外部程序:https://www.ibm.com/docs/cs/db2-for-zos/12?topic=statements-create-procedure-external 优秀的 IBMi 博客:https://www.rpgpgm.com/p/list-of-all-posts.html#3

【讨论】:

    猜你喜欢
    • 2013-11-01
    • 2015-05-11
    • 1970-01-01
    • 1970-01-01
    • 2011-03-23
    • 2017-01-31
    • 2017-12-21
    • 2019-05-13
    • 2017-01-29
    相关资源
    最近更新 更多