php-pdo:两次使用参数时参数号无效?

42fyovps  于 2021-06-20  发布在  Mysql
关注(0)|答案(3)|浏览(463)

我有一个问题,当我两次使用位置参数时,我不能在pdo(php/mysql)中使用sql语句:

  1. SELECT `ID` FROM `_LOGIN_` WHERE `LoginName` = :loginName AND `sha512`= SHA2(CONCAT(:pw, (SELECT `salt` FROM `_LOGIN_` WHERE `LoginName` = :loginName)), 512)

如您所见,我使用“:loginname”两次。因此出现以下错误消息:

  1. PHP Fatal error: Uncaught PDOException: SQLSTATE[HY093]: Invalid parameter number in ...

我是否遗漏了什么,或者是否有其他方法来准备语句,以便可以多次使用参数?
下面是要复制的完整代码:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>pdo</title>
  5. <meta charset = "utf-8" />
  6. </head>
  7. <body>
  8. <h1>PDO Prepare</h1>
  9. <!--
  10. DB:
  11. DROP DATABASE IF EXISTS `pdoTestDB`;
  12. CREATE DATABASE `pdoTestDB`;
  13. ALTER DATABASE `pdoTestDB` DEFAULT CHARACTER SET 'utf8' DEFAULT COLLATE 'utf8_general_ci';
  14. CREATE TABLE `_LOGIN_` (
  15. `ID` int(11) NOT NULL
  16. ,`LoginName` TEXT NOT NULL
  17. ,`SALT` varchar( 6) NOT NULL
  18. ,`sha512` varchar(128) NOT NULL
  19. ,`registerTS` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
  20. ,`lastLoginTS` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
  21. , PRIMARY KEY (`ID`)
  22. ) ;
  23. SELECT @SALT:=SUBSTRING(MD5(RAND()) FROM 1 FOR 6);
  24. INSERT INTO `_LOGIN_`
  25. (`ID`, `LoginName`, `salt`, `sha512` , `registerTS` ) VALUES
  26. ( 1, 'muma' , @SALT, SHA2(CONCAT('123', @SALT), 512), '2018-06-04' );
  27. -->
  28. <?php
  29. $PDOcharset = 'utf8mb4';
  30. // set data source name:
  31. $dsn = "mysql:host=localhost;dbname=pdoTestDB;charset=$PDOcharset";
  32. $opt = [
  33. PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
  34. PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
  35. PDO::ATTR_EMULATE_PREPARES => false,
  36. ];
  37. $pdo = new PDO($dsn, "santisPHP", "123", $opt);
  38. // the sql
  39. $sql = "SELECT `ID` FROM `_LOGIN_` WHERE `LoginName` = :loginName AND `sha512`= SHA2(CONCAT(:pw, (SELECT `salt` FROM `_LOGIN_` WHERE `LoginName` = :loginName)), 512)";
  40. $stmt = $pdo->prepare($sql);
  41. $paramsAssoc = ['loginName' => "muma", 'pw' => "123"];
  42. //echo $paramsAssoc;
  43. var_dump($stmt);
  44. var_dump($paramsAssoc);
  45. $result = $stmt->execute($paramsAssoc);
  46. $fetched = $stmt->fetch();
  47. echo "stmt: ";
  48. var_dump($stmt);
  49. echo "<br />";
  50. echo "result: ";
  51. var_dump($result);
  52. echo "<br />";
  53. echo "fetched: ";
  54. var_dump($fetched);
  55. echo "<br />";
  56. ?>
  57. </body>
  58. </html>
vulvrdjw

vulvrdjw1#

pdo不允许在每个查询中多次使用同一参数标识符。您需要在查询中更改标识符的名称,然后在参数中添加另一个匹配的名称。
像这样:

  1. // the sql
  2. $sql = "SELECT `ID` FROM `_LOGIN_` WHERE `LoginName` = :loginName1 AND `sha512`= SHA2(CONCAT(:pw, (SELECT `salt` FROM `_LOGIN_` WHERE `LoginName` = :loginName2)), 512)";
  3. $stmt = $pdo->prepare($sql);
  4. $loginName = 'muma';
  5. $pw = '123';
  6. $stmt->bindParam(":loginName1", $loginName);
  7. $stmt->bindParam(":loginName2", $loginName);
  8. $stmt->bindParam(":pw", $pw);
  9. //echo $paramsAssoc;
  10. var_dump($stmt);
  11. //var_dump($paramsAssoc);
  12. $result = $stmt->execute();
  13. $fetched = $stmt->fetch();

我更喜欢像上面显示的那样绑定我的参数,但是使用您的方法我相信您也可以做到这一点-同样的原则:

  1. $paramsAssoc = ['loginName1' => "muma", 'pw' => "123", 'loginName2' => "muma"];
  2. $result = $stmt->execute($paramsAssoc);
展开查看全部
ulmd4ohb

ulmd4ohb2#

根据lowèu rents对类似问题的回答,在您的情况下,您可以执行以下操作:
首先,在查询之前,执行另一个查询来定义 loginName 作为一个 User-Defined Variable :

  1. $stmt = $pdo->prepare("SET @loginName = :loginName");
  2. $stmt->bindValue(":loginName", "muma", PDO::PARAM_STR);
  3. $stmt->execute();

然后,在查询中,替换所有 :loginName 具有现在定义的 @loginName :

  1. // the sql
  2. $sql = "SELECT `ID` FROM `_LOGIN_` WHERE `LoginName` = @loginName AND `sha512`= SHA2(CONCAT(:pw, (SELECT `salt` FROM `_LOGIN_` WHERE `LoginName` = @loginName)), 512)";

最后,像以前一样执行,但这次 $paramsAssoc 数组不需要 'loginName' => "muma" 因为它已经在mysql示例和查询中定义了,所以变得非常简单:

  1. $paramsAssoc = ['pw' => "123"];
yquaqz18

yquaqz183#

或者,您可以将设置更改为 PDO::ATTR_EMULATE_PREPARES => true . 这将允许您通过在pdo本身而不是mysql服务器上准备语句来多次绑定相同的命名参数。

相关问题