mysqli和PDO中的bindValue和bindParam忽略变量类型

时间:2013-08-14 15:08:37

标签: pdo mysqli bind-variables variable-types

我在理解PDO和mysqli中绑定某些变量类型的意义的一部分时遇到了问题,如果在我的情况下给出的类型似乎毫无意义。在以下代码中,类型绑定(如is)将被忽略。数据库中的表行“wert_sortierung”是INT(11)。无论$val_int是否真的是整数,如果我通过is / PDO::PARAM_INT_STR绑定它,查询总是有效,没有中断,没有错误或警告,绑定和数据库或变量本身的类型不适合。

<?
class PDOTest {
    protected $pdo;

    function __construct(){

        $usr="usr";        
        $pwd="pwd";     
        $host="localhost";    
        $db="db";
        $val_int="I'm a string";
        $val_str="OP";

        $querystring="SELECT wert_langtext FROM TB_wert WHERE wert_sortierung = ? AND wert_CD = ?";

        try {

            $db_info = "mysql:host=$host;dbname=$db";  // usually provided via require_once and during construction

            $this->pdo = new PDO($db_info, $usr, $pwd);
            $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
            $this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

            $stmt = $this->pdo->prepare($querystring);

            $stmt->bindValue(1,$val_int,PDO::PARAM_INT);
            $stmt->bindValue(2,$val_str,PDO::PARAM_STR);

            $stmt->execute(); 

            $row_return = $stmt->fetchAll(PDO::FETCH_ASSOC);
            $this->varprint($row_return);
            $this->pdo = NULL;
            }

        catch (PDOException $ex) {
            printf ('Es spricht:');
            $this->printerror("Fehla! (" .  $ex->getMessage() . ")");
            $this->pdo = NULL;
            exit();
        }

        printf("<br />-------<br />");      
        //Added for comparison
        $mysqli = new mysqli($host, $usr, $pwd, $db);

        $m_stmt = $mysqli->prepare($querystring);
        $m_stmt->bind_param('is',$val_int, $val_str);

        $m_stmt->execute();
        $m_stmt->bind_result($row_return);
        $m_stmt->fetch();

        $this->varprint($row_return);

        $m_stmt->close();
        $mysqli->close(); 

    }

    private function printerror($txt) {
            printf("<p><font color=\"#ff0000\">%s</font></p>\n",
            htmlentities($txt));  
    }

    private function varprint($var) {
        echo "<br />";
        echo "<pre>";
        echo var_dump($var);
        echo "</pre>";  
    }
}

new PDOTest();

?>

任何人都可以在推理中指出我的错误。

1 个答案:

答案 0 :(得分:0)

实际上是Mysql的松散输入欺骗了你。

事实上,常规的Mysql查询可以接受数字值的字符串:

SELECT wert_langtext FROM TB_wert WHERE wert_sortierung = '1' AND wert_CD = '1';

虽然准备好的声明只是遵循这种行为。

然而,相反的情况并非那么无害。使用数字

寻址字符串值
SELECT wert_langtext FROM TB_wert WHERE wert_sortierung = 1; 
如果wert_sortierung是字符串类型和一些意外行为,

将导致无限数量的警告,例如匹配所有行。

所以,作为一般建议我建议默认使用's'。唯一的缺点是PDO的模拟准备和它can be easily worked around.

因此,要明确回答您的问题 - 准备好的语句只允许与常规查询相同的行为,不向其添加任何内容。使用预处理语句也可以通过常规查询完成所有操作。不,绑定不会验证您的数据(但它应该。我的类我测试整数占位符,如果没有给出数值,则抛出异常)