Php 使用数据中的单引号将csv数据插入数据库 CSV转义
在字段周围加引号,以便在CSV文件中包含撇号。例如,在您的CSV中:Php 使用数据中的单引号将csv数据插入数据库 CSV转义,php,csv,insert,Php,Csv,Insert,在字段周围加引号,以便在CSV文件中包含撇号。例如,在您的CSV中: function csv_file_to_mysql_table($source_file, $target_table, $max_line_length=10000) { if($source_file != '') { if (($handle = fopen($source_file, "r")) !== FALSE) { $columns = fgetcsv($handle, $max_li
function csv_file_to_mysql_table($source_file, $target_table, $max_line_length=10000) {
if($source_file != '')
{
if (($handle = fopen($source_file, "r")) !== FALSE) {
$columns = fgetcsv($handle, $max_line_length, ",");
$esc_columns = array();
foreach ($columns as &$column) {
$column = str_replace(".","",$column);
$esc_columns[] = escapeSqlName($column);
}
$esc_columns[] = escapeSqlName('custgroup');
$esc_columns[] = escapeSqlName('user_id');
$sqlsmttempl = 'INSERT INTO %s (%s) VALUES (%s)';
$sqlsmt = sprintf($sqlstmttempl,
escapeSqlName($target_table),
implode(',', $esc_columns),
implode(',',array_fill(0, count($esc_columns), '?')) // the parameter placeholders
);
$db = new PDO("mysql:host=localhost;dbname=test;","root","");
$insert = $db->prepare($sqlsmt);
while (($data = fgetcsv($handle, $max_line_length, ",")) !== FALSE) {
while(count($data) < count($columns)) {
$data[] = NULL;
}
$data[] = $_POST['custgroup'];
$data[] = $_POST['user_id'];
if($insert->execute($data))
{
header("Location:customer-search.php");
}
else
{
echo "no";
}
}
fclose($handle);
}
}
if (isset($_POST['submit'])) {
$file = $_FILES['filename']['tmp_name'];
$table = 'UserAddedRecord';
csv_file_to_mysql_table($file,$table);
}
数据库转义
您应该像@VolkerK建议的那样,使用PDO转义数据。准备好的报表的一个好处(甚至可能是目的)是将实际报表及其参数(paylod数据)分离开来。不要构建包含paylod数据的字符串,而应该通过或绑定这些参数。使用 在数组中插入值之前,为csv文件中的每个条目 那么,替换
"title", "name"
"Mr", "O'Hara"
与
您已经在使用PDO,因此应该让PDO为您处理转义 带着你准备好的声明。下面的代码就是这样做的 请注意,由于分配了表,所以仍然可能存在安全问题 和列名。下面的代码试图确保不会发生这种情况 导致任何SQL注入,但仍应谨慎 但是,对于
VALUES()
部分的未切换输入,您不会有任何问题,
而且插入应该更快,因为您准备了语句
只有一次
$data[$i] = "'".mysql_real_escape_string($data[$i])."'";
函数escapeSqlName($name,$quotechar='`')){
//这是转义列名。此$quotechar仅适用于MYSQL
//ANSI语法是在表名中使用$quotechar='“'并在任何地方将它们加倍”。
返回$quotechar.str_替换($quotechar,$quotechar.$quotechar,$name)。$quotechar;
}
if($handle=fopen($source_文件,“r”)!==FALSE){
$columns=fgetcsv($handle,$max\u line\u length,“,”);
$esc_columns=array();
foreach($columns as&$column){
$column=str_replace(“.”,“”,$column);
$esc_columns[]=escapeSqlName($column);
}
//你的两个额外专栏
$esc_columns[]=escapeSqlName('custgroup');
$esc_columns[]=escapeSqlName('user_id');
$sqlsmttempl='插入到%s(%s)值(%s)';
$sqlsmt=sprintf($sqlsmttempl,
escapeSqlName($target_table),//转义的表名
内爆(“,”,$esc_columns),//转义的列名
内爆(“,”,数组填充(0,计数($esc_列),“?”)//参数占位符
);
//$sqlsmt现在应该看起来像“插入到'thetable'('col1','col2',…)值(?,,…)”;
$db=new-PDO(“mysql:host=localhost;dbname=test;”,“root”,“”);
$insert=$db->prepare($sqlsmt);//准备语句一次,使用新值执行多次
while(($data=fgetcsv($handle,$max\u line\u length,“,”)!==FALSE){
while(count($data)execute($data);//为您进行数据转义。
}
}
考虑到这里真正的问题是对sql查询的输入进行不正确的转义,给出一个似乎可以解决问题但并不十分危险的变通方法。@FrancisAvila我正在编写DB转义示例,但注意到VolkerK已经涵盖了它。明确地说,我并没有提供解决方案,但指出CSV数据应该进行布局。认为正确格式化CSV文件是危险的说法是可笑的。他的CSV文件没有问题(fgetcsv
读得很好),他没有构建CSV文件,而且这不是一套足够的转义规则来正确构建CSV。(并不是说他应该用手来做——他应该使用fputcsv
)但是既然你改变了你的问题,使它仅仅是无益的,而不是有害的,我将删除我的反对票。非常感谢你的脚本Francis,我很抱歉我的反应太晚。我刚才试过了,但我发现了这个错误<代码>致命错误:[]字符串不支持运算符您应该给出有错误的行,但我认为是这一行:$esc_columns=escapeSqlName($column)代码>应为$esc\u列[]
。在回答中修复了我很抱歉,是的,这是行。我更改了它,它运行时没有错误,但没有插入数据。我试图编辑它,但对我来说太难了…可以帮我看看吗?我在问题中发布了它。谢谢。你发布的代码有语法错误。缺少一个右大括号。哦,因为我没有在问题中粘贴else
部分编码,所以我想我错过了右大括号。很抱歉..但在我的脚本中,所有的右大括号都在那里。
$data[$i] = "'{$data[$i]}'";
$data[$i] = "'".mysql_real_escape_string($data[$i])."'";
function escapeSqlName($name, $quotechar='`') {
// This is to escape column names. This $quotechar ONLY WORKS WITH MYSQL
// ANSI syntax is to use $quotechar='"' and double them where-ever " is in the table name.
return $quotechar.str_replace($quotechar, $quotechar.$quotechar, $name).$quotechar;
}
if (($handle = fopen($source_file, "r")) !== FALSE) {
$columns = fgetcsv($handle, $max_line_length, ",");
$esc_columns = array();
foreach ($columns as &$column) {
$column = str_replace(".","",$column);
$esc_columns[] = escapeSqlName($column);
}
// your two extra columns
$esc_columns[] = escapeSqlName('custgroup');
$esc_columns[] = escapeSqlName('user_id');
$sqlsmttempl = 'INSERT INTO %s (%s) VALUES (%s)';
$sqlsmt = sprintf($sqlsmttempl,
escapeSqlName($target_table), // the escaped table name
implode(',', $esc_columns), // the escaped column names
implode(',',array_fill(0, count($esc_columns), '?')) // the parameter placeholders
);
// $sqlsmt should now look like 'INSERT INTO `thetable` (`col1`,`col2`,...) VALUES (?,?,...)';
$db = new PDO("mysql:host=localhost;dbname=test;","root","");
$insert = $db->prepare($sqlsmt); // prepare statement ONCE, execute with new values MULTIPLE TIMES
while (($data = fgetcsv($handle, $max_line_length, ",")) !== FALSE) {
while(count($data) < count($columns)) {
$data[] = NULL;
}
// your two extra values
$data[] = $_POST['custgroup'];
$data[] = $_POST['user_id'];
$insert->execute($data); // does data escaping for you.
}
}