【问题标题】:how to remove quotes of any string when preparing queries准备查询时如何删除任何字符串的引号
【发布时间】:2013-03-27 11:53:18
【问题描述】:
$desc = 'DESC';

$getRecords = $conn->prepare('SELECT * FROM `courses` ORDER BY `id` :sort LIMIT :limitInc, :limit ');

$getRecords->bindValue(':limit',$limit,PDO::PARAM_INT);  // working

$getRecords->bindValue(':limitInc',$limitInc,PDO::PARAM_INT); // working

// *** The line below isn't working ***
$getRecords->bindValue(':sort', $desc ,PDO::PARAM_STR); // not working

$getRecords->execute();

我试图在我的准备查询中调用$desc..

致命错误:带有消息的未捕获异常“PDOException” 'SQLSTATE[42000]: 语法错误或访问冲突:1064 你有一个 SQL 语法错误;检查与您对应的手册 MySQL 服务器版本,用于在 ''DESC' LIMIT 0 附近使用正确的语法, 5' 在 C:\xampp\htdocs\portfolio\nasiraan\try\indexx.php:89 中的第 1 行 堆栈跟踪:#0 C:\xampp\htdocs\portfolio\nasiraan\try\indexx.php(89): PDOStatement->execute() #1 {main} 抛出 C:\xampp\htdocs\portfolio\nasiraan\try\indexx.php 在第 89 行

我确定解决方案是......从字符串$desc 中删除引号......但是如何?

【问题讨论】:

  • 随便$getRecords->bindValue(':sort', DESC ,PDO::PARAM_STR);?
  • 绑定只适用于“参数”,不能用于“结构化”SQL查询。
  • 你不能使用 '' 像这样':key' 那样提供:key 就这样做:key。绑定函数将 ' 放入其中,因此请注意这一点。

标签: php mysql pdo quotes


【解决方案1】:

参数标记只能用于应该出现数据值的地方,不能用于 SQL 关键字、标识符等。

PREPARE Syntax

你不能对它使用准备好的语句。

  • 如果你想使用简单的绑定值语法,你可以使用

    SELECT * FROM `courses` ORDER BY `id`*:sort LIMIT :limitInc, :limit 
    

然后绑定带符号的数值。但是这个查询will not be optimized by MySQL

  • 如果你想“吞下”错误的顺序,你可以使用@Jack 的解决方案,但是方向错误可能会得到错误的结果。如果顺序很重要,您必须检查这两个值:

    strcasecmp($desc, 'DESC') && strcasecmp($desc, 'ASC') ? error() : $desc;
    

您也可以包装 PDO 并添加特殊方法 prepare_ordered($query, $order); 或更复杂的方法并在那里进行比较。

或者你可以使用没有问题的外国图书馆。但是你必须学习它的API。

附:我看到您正在使用准备好的语句的模拟。

【讨论】:

  • 我无法得到您的答复。那是什么*:sort?重点是不能绑定关键字
  • @YourCommonSense,可以按表情排序。所以 id*-1 将是表达式。
【解决方案2】:

$query = 'SELECT * FROM courses ORDER BY id '.$desc .'限制 :limit, :limitInc';

$getRecords = $conn->prepare($query); // 将我的查询存储在一个变量名 $query 中,并在其中传递了我的变量.. 所以现在我不需要绑定它..

$getRecords->bindValue(':limit',$limit,PDO::PARAM_INT);

$getRecords->bindValue(':limitInc',$limitInc,PDO::PARAM_INT);

$getRecords->执行();

【讨论】:

  • 您的问题中没有针对 SQL 注入的解决方案。
【解决方案3】:

我总是扩展 PDO 并添加一些我自己方便的东西。所以首先你像这样扩展:

<?php

    //Database class
    class db extends Pdo{
        public function __construct(){
            global $conf;
            try
                {   
                    parent::__construct('DBTYPE:dbname=DBNAME;host=DBHOST', 'DBUSER', 'DBPASS');

                        $this->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
                        $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
                }
            catch(PDOException $e){
                throw new myPdoException($e);
            }
        }

        public function quest($queryString){
            try
                {
                    $query = $this->query($queryString);

                        return $query;                      
                }
            catch(PDOException $e){
                throw new myPdoException($e);
            }
        }

        public function doPrepare($queryString, $param){
            try
                {
                    $query = $this->prepare($queryString);

                    $query->execute($param);

                        return $query;
                }
            catch(PDOException $e)
            {
                throw new myPdoException($e);
            }
        }

        public function doPrepareBind($queryString, $param){
            try
                {
                    $query = $this->prepare($queryString);

                        foreach($param as $par){
                            switch($par[2]):
                                case 'int':
                                    $query->bindParam($par[0], $par[1], PDO::PARAM_INT);
                                break;

                                case 'str':
                                    $query->bindParam($par[0], $par[1], PDO::PARAM_STR);
                                break;
                                case 'blob':
                                    $query->bindParam($par[0], $par[1], PDO::PARAM_LOB);
                                break;

                                default:
                                    $query->bindParam($par[0], $par[1], PDO::PARAM_STR);
                                break;
                            endswitch;
                        }

                    $query->execute();

                        return $query;
                }
            catch(PDOException $e)
            {
                throw new myPdoException($e);
            }
        }
    }

    class myPdoException extends PdoException{
        private $_debug = DB_DEBUG;

        public function __construct($e){
            parent::__construct($e);

                $this->showException();
        }

        private function showException(){
            if($this->_debug){
                echo
                "<div id='transparant'><div id='error'><br /><br />" . 
                     $this->message
                . "<br /><br /><br /></div></div>";
            }
            else{
                echo    "<div id='transparant'><div id='error'><br /><br />
                            Er is iets mis gegaan, probeer later nog eens.<br />Sorry voor het ongemak.
                        <br /><br /><br /></div></div>";
            }
        }
    }

?>

您在第 9 行看到一个父构造函数。您必须添加您的数据库信息来代替大写字母。

请注意,DBTYPE 是您正在使用的数据库服务的类型。可能只是mysql。

这就是我在对一系列字符串进行消毒时使用它的方式:

//first include db class I made above.
$db = new db();

$query = "INSERT INTO `database`.`users` (`id`, `naam`, `email`, `pass`, `key`, `status`) VALUES (NULL, :name, :mail, :pass, '$key', '0')";
$param = array(
                    array(':name', $_POST['name']),
                    array(':mail', $_POST['mail']),
                    array(':pass', $pass_hash)
                );
$query = $db->doPrepareBind($query, $param);

【讨论】:

    【解决方案4】:

    恐怕您必须使用文字字符串,因为占位符不能包含用于排序顺序的关键字(以及其他关键字):

    $query = sprintf('SELECT * FROM `courses` ORDER BY `id` %s LIMIT :limitInc, :limit ', 
        strcasecmp($desc, 'DESC') === 0 ? 'DESC' : 'ASC')
    );
    $getRecords = $conn->prepare($query);
    

    以这种方式构建查询还不错,因为只有两个选项。

    【讨论】:

    • +1,最简单的解决方案。但是为了避免将来出现问题,最好将$desc替换为strtoupper($desc)
    • @Narek 我想这很公平 :)
    • strcasecmp($desc, 'DESC') ? '' : $desc 射手一点。更好的?不确定:)
    猜你喜欢
    • 2017-10-08
    • 1970-01-01
    • 1970-01-01
    • 2022-01-01
    • 2011-05-12
    • 1970-01-01
    • 2016-11-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多