1

我有以下代码:

    function insertrow($tablename,$record){
        $columns = $this->gettablecol($tablename);
        $types = $this->getbindtypestring($columns);    
        array_unshift($record, $types);                                             
        if(count($columns) && $types){              
            $query = 'INSERT INTO '.$tablename.' VALUES (?'.str_repeat(',?',count($columns)-1).')';
            if($stm = $this->linkid->prepare($query)){                  
                $res = call_user_func_array(array(&$stm,"bind_param"), $params);                    
                $stm->execute();                    
                print_r($stm);
                $stm->close();                                      
            }
        }
    }

$record 数组如下所示:

    (
        [0] => sssisssssssssssi
        [recordid] => TEST1
        [recdate] => 2012-10-31 08:45:49
        [lastmod] => 2012-10-31 08:45:49
        [delflag] => 0
        [cusname] => Dilbert
        [address1] => 181 Somewhere
        [address2] => 
        [city] => St. Petersburg
        [state] => FL
        [zipcode] => 33713
        [telephone] => 8135551212
        [faxnumber] => 8135551313
        [webaddress] => 
        [taxid] => 260708780
        [pinnumber] => 12345
        [isactive] => 0 
)

但是 $stm 告诉我没有数据:

mysqli_stmt Object
(
    [affected_rows] => 0
    [insert_id] => 0
    [num_rows] => 0
    [param_count] => 16
    [field_count] => 0
    [errno] => 2031
    [error] => No data supplied for parameters in prepared statement
    [sqlstate] => HY000
    [id] => 1
)

$record 数组似乎格式不正确。任何见解将不胜感激。


嗨,比尔,感谢您的提醒。我接受了您的建议并将 API 切换到 PDO....我必须承认我喜欢它的使用容易得多;但是,我的问题还没有解决。我将 insertrow 方法更改为如下所示:

    function insertrow($tablename,$record){         
        $this->connect();
        $columns = $this->gettablecol($tablename);      
        if(count($columns)){                
            $query = 'INSERT INTO '.$tablename.' VALUES (?'.str_repeat(',?',count($columns)-1).')';
            try{
                $stm = $this->linkid->prepare($query);                  
                $stm->execute($record);
            }catch(PDOException $e){
                $this->errormsg = $e.getMessage();
                $this.errhandler();
                exit();
            }           
        }
    }

记录如下所示:

Array
(
    [recordid] => TEST1
    [recdate] => 2012-11-01 09:12:50
    [lastmod] => 2012-11-01 09:12:50
    [delflag] => 0
    [cusname] => Dilbert
    [address1] => 181 Somewhere
    [address2] => 
    [city] => St. Petersburg
    [state] => FL
    [zipcode] => 33713
    [telephone] => 8135551212
    [faxnumber] => 8135551313
    [webaddress] => 
    [taxid] => 260708780
    [pinnumber] => 12345
    [isactive] => 0
)

我什至将 $record 的值复制到一个新数组中:

$newrec = array();
foreach($record as $row){
   $newrec = $row;
}

它看起来像这样:

 Array
(
    [0] => TEST1
    [1] => 2012-11-01 09:01:32
    [2] => 2012-11-01 09:01:32
    [3] => 0
    [4] => Dilbert
    [5] => 181 Somewhere
    [6] => 
    [7] => St. Petersburg
    [8] => FL
    [9] => 33713
    [10] => 8135551212
    [11] => 8135551313
    [12] => 
    [13] => 260708780
    [14] => 12345
    [15] => 0
)

并将其传递给 $stm->execute($newrec) 但它不起作用并且没有抛出异常。还有什么我可以看的吗?

在这一点上,我已经删除了传递 $record 数组,只是硬编码了这些值:

$stm->execute(array('TEST2','2012-10-10 00:00:00','2012-10-10 00:00:00',0,'1','2','3','4','5','6','7','8','9','0','11',0));

即使准备和执行都恢复正常,我仍然没有将记录插入表中。

我有必要将参数绑定到它们的特定数据类型吗?

4

1 回答 1

2

使用 bind_param 的困难是我在开发可重用数据库访问层时不喜欢使用 Mysqli 的原因。可以做到,但是 PHP 的引用使它变得不必要地晦涩难懂。

有关解决方案,请参阅我在mysqli_prepare vs PDO中的回答

基本上,您传递的数组必须是引用数组,而不是标量数组。

我发现在开发 DBAL 时使用 PDO 要容易得多。你不必绑定任何东西。您只需将数组传递给PDOStatement::execute()


重新编辑:

我是 PDO 对你有帮助。但这毕竟可能不是您最初问题的根本原因。如果我的建议是野鹅追逐,我深表歉意。但至少现在您正在使用 PDO,所以这是一次角色构建体验。:-)

我在您的代码中注意到了两件事,但我不确定这些是否是问题:

您根据 $columns 数组的计数添加了许多参数占位符,但是您怎么知道这与 $record 数组的计数相同?如果参数占位符的数量与提供给 execute() 的值的数量不匹配,那么这是一个错误。

你应该检查:

if (count($columns) != count($record)) { 
  // report error
}

或者,您可以确保仅在 $record 数组中包含作为键提到的列:

$columns_to_insert = array_intersect($columns, array_keys($record));

顺便说一句(这不是一个错误,只是一个提示),我会生成这样的参数占位符序列,只是为了避免字符串连接和错误的风险:

join(",", array_fill(0, count($record), "?"))

我注意到的另一件事是您没有检查 execute() 的返回值。如果它返回false,则说明有错误,您应该调查错误的性质

您正在捕获异常,但 PDO 的默认模式是抛出异常,而只是设置函数的返回值来指示错误。您可以以这种方式使用它,否则您必须显式启用异常抛出模式:

$this->linkid->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

该设置在 PDO 连接期间是全局的;您不必每次插入一行时都这样做。

于 2012-11-01T02:10:26.523 回答