【问题标题】:Query to procedure firebird database with PHP使用 PHP 查询程序 firebird 数据库
【发布时间】:2020-08-29 14:22:41
【问题描述】:

我正在为 firebase 数据库创建 Web 服务。我需要对程序 firebird 执行查询。我以这种方式使用带有 PDO 的 PHP 来执行此操作(这是我的总结代码):

$instalacion = $_REQUEST['instalacion'];
$fecha = $_REQUEST['fecha'];
$inicio = date("m/d/Y",strtotime($fecha))." ".$_REQUEST['inicio'];
$fin = date("m/d/Y",strtotime($fecha))." ".$_REQUEST['fin'];

$reserva_annio = 0;
$reserva = 0;
$numero = 0;
$serie = '';

        $annio = date("Y", strtotime($fecha));

        $res=$dbh->query("execute procedure INS_CREA_RESERVA (date('m/d/Y',strtotime($fecha)), $inicio, $fin, $instalacion)

returning_values($reserva_annio, $reserva, $numero, $serie);  ");

我的 firebird 中的程序运行正常,但是这个查询返回了这个:

致命错误:未捕获的 PDOException:SQLSTATE[HY000]:一般错误: -104 动态 SQL 错误 SQL 错误代码 = -104 令牌未知 - 第 3 行,第 25 列“0”

这个错误告诉我失败的部分是返回值行。但在我的火鸟中工作正常。

我可能需要在 php.ini 或类似的东西中安装一个库吗?我已经激活了这个:extension=pdo_firebird,但不工作。

对我的错误有什么建议吗?谢谢!

【问题讨论】:

  • 我认为这行不通 - returning_values($reserva_annio - 这对我来说毫无意义。要将值推回应用程序,您的服务器应该被赋予变量(C++ 术语中的 LVALUE),而不是常量(RVALUE)!尽管出于多种原因将值拼接到 SQL 文字中是一件坏事,即使对于只读值也是如此。见bobby-tables.com/php
  • 是的,你是对的。在网上研究之后,我发现这可以通过更简单的选择查询来完成。我为将来可能出现的错误提出了解决方案。谢谢!
  • 我还是强烈建议你反对字符串拼接!一定要使用参数。它更具可预测性和安全性。特别是,您不需要所有这些date('m/d/Y' 并猜测有关此或该 SQL 服务器的文本日期时间格式的工作。并且您将能够prepare 经常使用的查询,因此您可以重新运行它们而无需重新编译,只需更改参数值。
  • RETURNING_VALUES 子句仅用于 PSQL(存储过程代码),不适用于 DSQL。部分问题在于您使用的是字符串插值(这会使您的代码容易受到 SQL 注入的影响),而不是实际参数。
  • 是的,没错。我只是写了示例代码,为了清楚起见,我这样发布它。实际上,查询当然是在准备好的语句下构建的。

标签: php pdo firebird procedure


【解决方案1】:

试试

$dt=date('m/d/Y',strtotime($fecha));
$res=$dbh->query("execute procedure INS_CREA_RESERVA ('$dt', ......

【讨论】:

  • 好收获。仍然拼接对 OUTPUT 参数几乎不起作用,还是在 PHP 中起作用?
  • 有效。这一直是寻找解决方案的提示。谢谢!
  • 这样做会使代码容易受到 SQL 注入的攻击。
  • 是的,没错。我只是写了示例代码,为了清楚起见,我这样发布它。实际上,查询当然是在准备好的语句下构建的。
【解决方案2】:

经过网上研究,我发现这可以通过更简单的选择查询来完成。请求它返回数据是没有意义的,使用 php 可以通过类似这样的简单查询来完成:

$instalacion = $_REQUEST['instalacion'];
$fecha = $_REQUEST['fecha'];
$inicio = date("m/d/Y",strtotime($fecha))." ".$_REQUEST['inicio'];
$fin = date("m/d/Y",strtotime($fecha))." ".$_REQUEST['fin'];

$res=$dbh->query("select * from INS_CREA_RESERVA($fecha, $inicio, $fin, $instalacion)");

注意,'Where'子句必须用方括号代替,传递参数用逗号隔开。

【讨论】:

  • 这实际上是非常值得怀疑的。在 Interbase/Firebird 中,程序可以选择也可以不选择。可选择的可以返回许多行,零或一或多。并且将与select .... from 命令一起使用。不可选择不返回任何行,应使用execute procedure 命令调用。如果您在一个可选行上执行execute procedure - 它会尝试返回第一行并删除其他行。通过不匹配的命令调用错误种类的 SP 是程序设计错误。
  • 如果 SP 返回零行怎么办?我不记得了。它摇摇欲坠。如果你对一个不可选择的对象执行select 怎么办?我也不记得具体的细节了,摇摇晃晃的。所以,你的一个命令,这个或之前的一个,是一个错误,使程序的行为更不可预测,特别是反对使用任何不同的 Firebird 版本(过去或未来)运行程序的可能性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-04
  • 1970-01-01
  • 1970-01-01
  • 2014-05-24
  • 2018-10-05
  • 2017-08-01
  • 1970-01-01
相关资源
最近更新 更多