【问题标题】:Problems with uploading CSV file to SQL Server with PHP使用 PHP 将 CSV 文件上传到 SQL Server 的问题
【发布时间】:2020-07-23 02:38:37
【问题描述】:

我创建了一个 Web 应用程序,允许用户将 CSV 文件上传到 SQL Server。我总共有 8 列。 SQL Server 中的 id 列是自动递增的,因此减去该列。上传成功,但是每列导入的数据都是null。我的CSV 中的记录数也少于 100 条,但是我的 SQL Server 显示导入的记录超过 100 条,这些记录不相符。谁能帮忙检查一下我的代码有什么问题?

以下是我的代码以及我的 CSV 文件和 SQL Server 表的屏幕截图。

<?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 表

【问题讨论】:

    标签: php sql-server csv upload sqlsrv


    【解决方案1】:

    贴出的代码有两个主要问题:

    1. CSV 数据未正确读取,并且
    2. 提供给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] 数组元素。

    【讨论】:

      猜你喜欢
      • 2011-06-06
      • 2016-03-13
      • 2011-11-09
      • 2021-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-18
      相关资源
      最近更新 更多