我有一个像这样的数组
$a = array( 'phone' => 111111111, 'image' => "sadasdasd43eadasdad" );
当我进行var-dump时,我得到了这个 - >
{ ["phone"]=> int(111111111) ["image"]=> string(19) "sadasdasd43eadasdad" }
现在我尝试使用IN语句将其添加到数据库 -
$q = $DBH->prepare("INSERT INTO user :column_string VALUES :value_string");
$q->bindParam(':column_string',implode(',',array_keys($a)));
$q->bindParam(':value_string',implode(',',array_values($a)));
$q->execute();
我遇到的问题是implode返回一个字符串。但'phone'列是数据库中的整数,并且数组也将其存储为整数。因此我得到SQL错误,因为我的最终查询看起来像这样 -
INSERT INTO user 'phone,image' values '111111111,sadasdasd43eadasdad';
哪个查询错误。有没有办法解决它。
我的列名是动态的,基于用户想要插入的内容。因此,我无法使用:phone 和:image 等占位符,因为我可能无法始终获得这两列的值。如果有办法,请告诉我。否则我将不得不为每种类型的更新定义多个函数。
感谢。
答案 0 :(得分:10)
上次我检查时,不可能准备一份声明,其中受影响的列在准备时是未知的 - 但这似乎有用 - 也许你的数据库系统比我正在使用的那些(主要是postgres)更宽容< / p>
implode()语句显然是错误的,因为每个变量都应该由它自己处理,你还需要在insert语句中的字段列表周围使用括号。
要插入用户定义的字段,我认为你必须做这样的事情(至少我是怎么做的);
$fields=array_keys($a); // here you have to trust your field names!
$values=array_values($a);
$fieldlist=implode(',',$fields);
$qs=str_repeat("?,",count($fields)-1);
$sql="insert into user($fieldlist) values(${qs}?)";
$q=$DBH->prepare($sql);
$q->execute($values);
如果您不相信$ a中的字段名称,则必须执行类似
的操作foreach($a as $f=>$v){
if(validfield($f)){
$fields[]=$f;
$values[]=$v;
}
}
其中validfields是您编写的函数,用于测试每个fieldname并检查它是否有效(通过创建关联数组来快速和脏化$ valfields = array('name'=&gt; 1,'email'=&gt; 1 ,'phone'=&gt; 1 ...然后通过从服务器获取字段名称来检查$ valfields [$ f]的值,或(我希望如此)
答案 1 :(得分:6)
SQL查询参数只能用于放置文字值的位置。
因此,如果您可以看到自己在查询中的该位置放置带引号的字符串文字,日期文字或数字文字,则可以使用参数。
您不能将参数用于列名,表名,值列表,SQL关键字或任何其他表达式或语法。
对于这些情况,您仍然需要将内容插入到SQL字符串中,因此您有一些SQL注入的风险。防止这种情况的方法是使用白名单列名称,并拒绝任何与白名单不匹配的输入。
答案 2 :(得分:4)
因为所有其他答案都允许 SQL注入。对于用户输入,您需要筛选允许的字段名称:
// change this
$fields = array('email', 'name', 'whatever');
$fieldlist = implode(',', $fields);
$values = array_values(array_intersect_key($_POST, array_flip($fields)));
$qs = str_repeat("?,",count($fields)-1) . '?';
$q = $db->prepare("INSERT INTO events ($fieldlist) values($qs)");
$q->execute($values);
答案 3 :(得分:2)
您实际上可以提前使用空值绑定:phone
和:image
字段。无论如何,表的结构是固定的,你可能应该这样。
但你问题的答案可能如下:
$keys = ':' . implode(', :', array_keys($array));
$values = str_repeat('?, ', count($array)-1) . '?';
$i = 1;
$q = $DBH->prepare("INSERT INTO user ($keys) VALUES ($values)");
foreach($array as $value)
$q->bindParam($i++, $value, PDO::PARAM_STR, mb_strlen($value));
答案 4 :(得分:2)
我知道很久以前这个问题已经得到解答了,但我今天发现它并且除了@MortenSickel的答案之外还有一些贡献。
下面的类允许您将关联数组插入或更新到数据库表。有关MySQL PDO的更多信息,请访问:http://php.net/manual/en/book.pdo.php
<?php
class dbConnection
{
protected $dbConnection;
function __construct($dbSettings) {
$this->openDatabase($dbSettings);
}
function openDatabase($dbSettings) {
$dsn = 'mysql:host='.$dbSettings['host'].';dbname='.$dbSettings['name'];
$this->dbConnection = new PDO($dsn, $dbSettings['username'], $dbSettings['password']);
$this->dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
function insertArray($table, $array) {
$fields=array_keys($array);
$values=array_values($array);
$fieldlist=implode(',', $fields);
$qs=str_repeat("?,",count($fields)-1);
$sql="INSERT INTO `".$table."` (".$fieldlist.") VALUES (${qs}?)";
$q = $this->dbConnection->prepare($sql);
return $q->execute($values);
}
function updateArray($table, $id, $array) {
$fields=array_keys($array);
$values=array_values($array);
$fieldlist=implode(',', $fields);
$qs=str_repeat("?,",count($fields)-1);
$firstfield = true;
$sql = "UPDATE `".$table."` SET";
for ($i = 0; $i < count($fields); $i++) {
if(!$firstfield) {
$sql .= ", ";
}
$sql .= " ".$fields[$i]."=?";
$firstfield = false;
}
$sql .= " WHERE `id` =?";
$sth = $this->dbConnection->prepare($sql);
$values[] = $id;
return $sth->execute($values);
}
}
?>
dbConnection类用法:
<?php
$dbSettings['host'] = 'localhost';
$dbSettings['name'] = 'databasename';
$dbSettings['username'] = 'username';
$dbSettings['password'] = 'password';
$dbh = new dbConnection( $dbSettings );
$a = array( 'phone' => 111111111, 'image' => "sadasdasd43eadasdad" );
$dbh->insertArray('user', $a);
// This will asume your table has a 'id' column, id: 1 will be updated in the example below:
$dbh->updateArray('user', 1, $a);
?>
答案 5 :(得分:2)
我很欣赏MortenSickel的回答,但我想使用命名参数来保证安全:
$keys = array_keys($a);
$sql = "INSERT INTO user (".implode(", ",$keys).") \n";
$sql .= "VALUES ( :".implode(", :",$keys).")";
$q = $this->dbConnection->prepare($sql);
return $q->execute($a);
答案 6 :(得分:0)
public function insert($data = [] , $table = ''){
$keys = array_keys($data);
$fields = implode(',',$keys);
$pre_fields = ':'.implode(', :',$keys);
$query = parent::prepare("INSERT INTO $table($fields) VALUES($pre_fields) ");
return $query->execute($data);
}