我有以下代码:
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数组以某种方式格式错误。任何见解都将不胜感激。
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->执行($ 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));
即使准备和执行都恢复正常,我仍然没有将记录插入表中。
我是否有必要将参数绑定到特定的数据类型?
答案 0 :(得分: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
,那么就会出现错误,您应该investigate the nature of the error。
您正在捕获异常,但PDO的默认模式是而不是以抛出异常,而只是设置函数的返回值以指示错误。您可以以这种方式使用它,否则您必须明确启用异常抛出模式:
$this->linkid->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
该设置在PDO连接期间是全局的;每次插入行时都不必这样做。