使用 PHP 将 CSV 文件上传到 SQL 服务器时出现问题
Problems with uploading CSV file to SQL Server with PHP
我创建了一个 Web 应用程序,允许用户将 CSV
文件上传到 SQL 服务器。我总共有 8 列。 SQL 服务器中的 id 列是自动递增的,因此减去该列。上传成功,但导入的数据在每一列中都是 null
。此外,我的 CSV
中的记录数少于 100,但我的 SQL 服务器显示导入的记录超过 100 条,这不符合要求。任何人都可以帮助检查我的代码有什么问题吗?
下面是我的代码和我的 CSV 文件和 SQL 服务器的屏幕截图 table。
<?php
$self = $_SERVER['PHP_SELF'];
$request = $_SERVER['REQUEST_METHOD'];
if (!isset($_GET['success'])) {
$get_success = "";
}
else {
$get_success = $_GET['success'];
}
if (!empty($_FILES)) {
/* Format the errors and die */
function get_last_error() {
$retErrors = sqlsrv_errors(SQLSRV_ERR_ALL);
$errorMessage = 'No errors found';
if ($retErrors != null) {
$errorMessage = '';
foreach ($retErrors as $arrError) {
$errorMessage .= "SQLState: ".$arrError['SQLSTATE']."<br>\n";
$errorMessage .= "Error Code: ".$arrError['code']."<br>\n";
$errorMessage .= "Message: ".$arrError['message']."<br>\n";
}
}
die ($errorMessage);
}
/* connect */
function connect() {
if (!function_exists('sqlsrv_num_rows')) { // Insure sqlsrv_1.1 is loaded.
die ('sqlsrv_1.1 is not available');
}
/* Log all Errors */
sqlsrv_configure("WarningsReturnAsErrors", TRUE); // BE SURE TO NOT ERROR ON A WARNING
sqlsrv_configure("LogSubsystems", SQLSRV_LOG_SYSTEM_ALL);
sqlsrv_configure("LogSeverity", SQLSRV_LOG_SEVERITY_ALL);
$conn = sqlsrv_connect('servername', array
(
'UID' => '',
'PWD' => '',
'Database' => 'databasename',
'CharacterSet' => 'UTF-8',
'MultipleActiveResultSets' => true,
'ConnectionPooling' => true,
'ReturnDatesAsStrings' => true,
));
if ($conn === FALSE) {
get_last_error();
}
return $conn;
}
function query($conn, $query) {
$result = sqlsrv_query($conn, $query);
if ($result === FALSE) {
get_last_error();
}
return $result;
}
/* Prepare a reusable query (prepare/execute) */
function prepare ( $conn, $query, $params ) {
$result = sqlsrv_prepare($conn, $query, $params);
if ($result === FALSE) {
get_last_error();
}
return $result;
}
/*
do the deed. once prepared, execute can be called multiple times
getting different values from the variable references.
*/
function execute ( $stmt ) {
$result = sqlsrv_execute($stmt);
if ($result === FALSE) {
get_last_error();
}
return $result;
}
function fetch_array($query) {
$result = sqlsrv_fetch_array($query, SQLSRV_FETCH_ASSOC);
if ($result === FALSE) {
get_last_error();
}
return $result;
}
$conn = connect();
/* prepare the statement */
$query = "INSERT TABLEName values ( ? , ? , ? , ?, ?, ?, ?, ?)";
$param1 = null; // this will hold col1 from the CSV
$param2 = null; // this will hold col2 from the CSV
$param3 = null; // this will hold col3 from the CSV
$param4 = null; // this will hold col4 from the CSV
$param5 = null; // this will hold col5 from the CSV
$param6 = null; // this will hold col6 from the CSV
$param7 = null; // this will hold col7 from the CSV
$param8 = null; // this will hold col8 from the CSV
$params = array( $param1, $param2, $param3, $param4, $param5, $param6, $param7, $param8 );
$prep = prepare ( $conn, $query, $params );
//$result = execute ( $prep );
//get the csv file
$file = $_FILES["csv"]["tmp_name"];
/*
Here is where you read in and parse your CSV file into an array.
That may get too large, so you would have to read smaller chunks of rows.
*/
$csv_array = file($file);
foreach ($csv_array as $row_num => $row) {
$row = trim ($row);
$column = explode ( ',' , $row );
$param1 = $column[0];
$param2 = $column[1];
$param3 = $column[2];
$param4 = $column[3];
$param5 = $column[4];
$param6 = $column[5];
$param7 = $column[6];
$param8 = $column[7];
// insert the row
$result = execute ( $prep );
}
/* Free statement and connection resources. */
sqlsrv_close($conn);
header( "Location: uploadcsv.php?success=1" );
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>CSV Upload</title>
</head>
<body>
<?php if (!empty($get_success)) { echo "<b>Your file has been imported.</b><br><br>"; } //generic success notice ?>
<form action="" method="post" enctype="multipart/form-data" name="uploadcsv" id="uploadcsv">
Upload a CSV file from your computer: <br />
<input name="csv" type="file" id="csv" />
<input type="submit" name="Submit" value="Submit" />
</form>
<body>
</html>
CSV 数据文件
sqlserver table
发布的代码有两个主要问题:
- 未正确读入 CSV 数据,并且
- 提供给
prepare()
的 $params
数组未正确更新。
问题 1:读取 CSV。
您正在使用 PHP 的 file() 方法读取 CSV 文件。
如果您试图逐行解析 CSV 文件,然后用逗号分隔行,那您就错了。通读 RFC 4180 Common Format and MIME Type for Comma-Separated Values (CSV) Files 以了解 CSV 文件的结构,并注意字段数据可以包含逗号、引号和换行符。即:您需要一个面向字符的状态机来解析它们。
正确的做法是使用别人已经为您编写和调试的CSV解析函数或库,例如:fgestcsv().
考虑以下示例...
foo1.csv:
col1,col2,col3
alpha,bravo,charlie
"hello,
""cruel""
world!",bravo,charlie
foo1.php:
<?php
if (($handle = fopen("foo1.csv", "r")) !== FALSE) {
$row = 1;
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
print "Row $row: ";
var_dump($data);
$row++;
}
fclose($handle);
}
?>
当 运行 输出...
% php -f foo1.php
Row 1: array(3) {
[0]=>
string(4) "col1"
[1]=>
string(4) "col2"
[2]=>
string(4) "col3"
}
Row 2: array(3) {
[0]=>
string(5) "alpha"
[1]=>
string(5) "bravo"
[2]=>
string(7) "charlie"
}
Row 3: array(3) {
[0]=>
string(19) "hello,
"cruel"
world!"
[1]=>
string(5) "bravo"
[2]=>
string(7) "charlie"
}
问题 2:正确更新 $params
发布的代码从变量构造一个数组,然后用 CSV 数据更新变量。这行不通,请考虑以下...
foo2.php:
<?php
$param1 = null;
print "$param1 = ";
var_dump($param1);
$params = array($param1);
print "$params = ";
var_dump($params);
$param1 = 42;
print "$param1 = ";
var_dump($param1);
print "$params = ";
var_dump($params);
$params[0] = 47;
print "$params = ";
var_dump($params);
?>
当 运行 输出...
% php -f foo2.php
$param1 = NULL
$params = array(1) {
[0]=>
NULL
}
$param1 = int(42)
$params = array(1) {
[0]=>
NULL
}
$params = array(1) {
[0]=>
int(47)
}
注意 $param1
如何成功更新为 42 但 $params[0]
仍然为 NULL? $params
仅在我们直接通过 $params[0]
设置应用时更新。
您的 CSV 读取代码(希望更新为使用 fgestcsv())应该直接更新 $params[0]
到 $params[7]
数组元素。
我创建了一个 Web 应用程序,允许用户将 CSV
文件上传到 SQL 服务器。我总共有 8 列。 SQL 服务器中的 id 列是自动递增的,因此减去该列。上传成功,但导入的数据在每一列中都是 null
。此外,我的 CSV
中的记录数少于 100,但我的 SQL 服务器显示导入的记录超过 100 条,这不符合要求。任何人都可以帮助检查我的代码有什么问题吗?
下面是我的代码和我的 CSV 文件和 SQL 服务器的屏幕截图 table。
<?php
$self = $_SERVER['PHP_SELF'];
$request = $_SERVER['REQUEST_METHOD'];
if (!isset($_GET['success'])) {
$get_success = "";
}
else {
$get_success = $_GET['success'];
}
if (!empty($_FILES)) {
/* Format the errors and die */
function get_last_error() {
$retErrors = sqlsrv_errors(SQLSRV_ERR_ALL);
$errorMessage = 'No errors found';
if ($retErrors != null) {
$errorMessage = '';
foreach ($retErrors as $arrError) {
$errorMessage .= "SQLState: ".$arrError['SQLSTATE']."<br>\n";
$errorMessage .= "Error Code: ".$arrError['code']."<br>\n";
$errorMessage .= "Message: ".$arrError['message']."<br>\n";
}
}
die ($errorMessage);
}
/* connect */
function connect() {
if (!function_exists('sqlsrv_num_rows')) { // Insure sqlsrv_1.1 is loaded.
die ('sqlsrv_1.1 is not available');
}
/* Log all Errors */
sqlsrv_configure("WarningsReturnAsErrors", TRUE); // BE SURE TO NOT ERROR ON A WARNING
sqlsrv_configure("LogSubsystems", SQLSRV_LOG_SYSTEM_ALL);
sqlsrv_configure("LogSeverity", SQLSRV_LOG_SEVERITY_ALL);
$conn = sqlsrv_connect('servername', array
(
'UID' => '',
'PWD' => '',
'Database' => 'databasename',
'CharacterSet' => 'UTF-8',
'MultipleActiveResultSets' => true,
'ConnectionPooling' => true,
'ReturnDatesAsStrings' => true,
));
if ($conn === FALSE) {
get_last_error();
}
return $conn;
}
function query($conn, $query) {
$result = sqlsrv_query($conn, $query);
if ($result === FALSE) {
get_last_error();
}
return $result;
}
/* Prepare a reusable query (prepare/execute) */
function prepare ( $conn, $query, $params ) {
$result = sqlsrv_prepare($conn, $query, $params);
if ($result === FALSE) {
get_last_error();
}
return $result;
}
/*
do the deed. once prepared, execute can be called multiple times
getting different values from the variable references.
*/
function execute ( $stmt ) {
$result = sqlsrv_execute($stmt);
if ($result === FALSE) {
get_last_error();
}
return $result;
}
function fetch_array($query) {
$result = sqlsrv_fetch_array($query, SQLSRV_FETCH_ASSOC);
if ($result === FALSE) {
get_last_error();
}
return $result;
}
$conn = connect();
/* prepare the statement */
$query = "INSERT TABLEName values ( ? , ? , ? , ?, ?, ?, ?, ?)";
$param1 = null; // this will hold col1 from the CSV
$param2 = null; // this will hold col2 from the CSV
$param3 = null; // this will hold col3 from the CSV
$param4 = null; // this will hold col4 from the CSV
$param5 = null; // this will hold col5 from the CSV
$param6 = null; // this will hold col6 from the CSV
$param7 = null; // this will hold col7 from the CSV
$param8 = null; // this will hold col8 from the CSV
$params = array( $param1, $param2, $param3, $param4, $param5, $param6, $param7, $param8 );
$prep = prepare ( $conn, $query, $params );
//$result = execute ( $prep );
//get the csv file
$file = $_FILES["csv"]["tmp_name"];
/*
Here is where you read in and parse your CSV file into an array.
That may get too large, so you would have to read smaller chunks of rows.
*/
$csv_array = file($file);
foreach ($csv_array as $row_num => $row) {
$row = trim ($row);
$column = explode ( ',' , $row );
$param1 = $column[0];
$param2 = $column[1];
$param3 = $column[2];
$param4 = $column[3];
$param5 = $column[4];
$param6 = $column[5];
$param7 = $column[6];
$param8 = $column[7];
// insert the row
$result = execute ( $prep );
}
/* Free statement and connection resources. */
sqlsrv_close($conn);
header( "Location: uploadcsv.php?success=1" );
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>CSV Upload</title>
</head>
<body>
<?php if (!empty($get_success)) { echo "<b>Your file has been imported.</b><br><br>"; } //generic success notice ?>
<form action="" method="post" enctype="multipart/form-data" name="uploadcsv" id="uploadcsv">
Upload a CSV file from your computer: <br />
<input name="csv" type="file" id="csv" />
<input type="submit" name="Submit" value="Submit" />
</form>
<body>
</html>
CSV 数据文件
sqlserver table
发布的代码有两个主要问题:
- 未正确读入 CSV 数据,并且
- 提供给
prepare()
的$params
数组未正确更新。
问题 1:读取 CSV。
您正在使用 PHP 的 file() 方法读取 CSV 文件。
如果您试图逐行解析 CSV 文件,然后用逗号分隔行,那您就错了。通读 RFC 4180 Common Format and MIME Type for Comma-Separated Values (CSV) Files 以了解 CSV 文件的结构,并注意字段数据可以包含逗号、引号和换行符。即:您需要一个面向字符的状态机来解析它们。
正确的做法是使用别人已经为您编写和调试的CSV解析函数或库,例如:fgestcsv().
考虑以下示例...
foo1.csv:
col1,col2,col3
alpha,bravo,charlie
"hello,
""cruel""
world!",bravo,charlie
foo1.php:
<?php
if (($handle = fopen("foo1.csv", "r")) !== FALSE) {
$row = 1;
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
print "Row $row: ";
var_dump($data);
$row++;
}
fclose($handle);
}
?>
当 运行 输出...
% php -f foo1.php
Row 1: array(3) {
[0]=>
string(4) "col1"
[1]=>
string(4) "col2"
[2]=>
string(4) "col3"
}
Row 2: array(3) {
[0]=>
string(5) "alpha"
[1]=>
string(5) "bravo"
[2]=>
string(7) "charlie"
}
Row 3: array(3) {
[0]=>
string(19) "hello,
"cruel"
world!"
[1]=>
string(5) "bravo"
[2]=>
string(7) "charlie"
}
问题 2:正确更新 $params
发布的代码从变量构造一个数组,然后用 CSV 数据更新变量。这行不通,请考虑以下...
foo2.php:
<?php
$param1 = null;
print "$param1 = ";
var_dump($param1);
$params = array($param1);
print "$params = ";
var_dump($params);
$param1 = 42;
print "$param1 = ";
var_dump($param1);
print "$params = ";
var_dump($params);
$params[0] = 47;
print "$params = ";
var_dump($params);
?>
当 运行 输出...
% php -f foo2.php
$param1 = NULL
$params = array(1) {
[0]=>
NULL
}
$param1 = int(42)
$params = array(1) {
[0]=>
NULL
}
$params = array(1) {
[0]=>
int(47)
}
注意 $param1
如何成功更新为 42 但 $params[0]
仍然为 NULL? $params
仅在我们直接通过 $params[0]
设置应用时更新。
您的 CSV 读取代码(希望更新为使用 fgestcsv())应该直接更新 $params[0]
到 $params[7]
数组元素。