![](/img/trans.png)
[英]PHP - Uploading CSV, inserting to multiple tables and displaying elsewhere
[英]PHP/SQL - Uploading CSV to database - Different sheets daily/Multiple Tables
昨天我問了一個不清楚的問題,現在我將其稍作擴展。 簡而言之,當前項目需要一個簡單的Web界面,用戶可以在其中上傳CSV文件(此網頁已創建)。 我已經為測試文件修改了PHP,但是我的情況要求有所不同。 每天,用戶將上傳1至5個不同的CSV報告。 這些報告大約有110個字段/列,盡管並非所有字段都將填寫在每個報告中。 我創建了一個包含5個表的數據庫,每個表涵蓋110個表中的不同字段。例如,一個表包含有關水表的信息(25個字段),另一個表包含有關在水表上進行的測試的信息(45個字段) )。 我很難找到一種方法,可以將CSV文件上傳后上傳,並將數據拆分到不同的表中。 我聽說過將整個CSV放入一個表中,並使用INSERT語句從那里拆分,但是我對此有疑問:
有沒有一種方法可以將包含110個字段的CSV放入一個表中而無需創建字段? 還是我必須在MYSQL工作台中創建110個字段,然后在PHP中為每個字段創建一個變量?
如果沒有,我是否可以從表轉儲中聲明變量,以便正確的數據進入正確的表中?
我對CSV這樣的上傳不太熟悉,通常只是從具有已知文件名的文件夾中提取一個CSV,所以這就是我的困惑所在。 這是我僅用10列就用作簡單測試的PHP。 這樣做是為了確保CSV上傳成功。
<?php
$server = "localhost";
$user = "root";
$pw = "root";
$db = "uwstest";
$connect = mysqli_connect($server, $user, $pw, $db);
if ($connect->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
if(isset($_POST['submit']))
{
$file = $_FILES['file']['tmp_name'];
$handle = fopen($file, "r");
$c = 0;
while(($filesop = fgetcsv($handle, 1000, ",")) !== false)
{
$one = $filesop[0];
$two = $filesop[1];
$three = $filesop[2];
$four = $filesop[3];
$five = $filesop[4];
$six = $filesop[5];
$seven = $filesop[6];
$eight = $filesop[7];
$nine = $filesop[8];
$ten = $filesop[9];
$sql = "INSERT INTO staging (One, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten) VALUES ('$one','$two', '$three','$four','$five','$six','$seven','$eight','$nine','$ten')";
}
if ($connect->query($sql) === TRUE) {
echo "You database has imported successfully";
} else {
echo "Error: " . $sql . "<br>" . $conn->error;
}
}
}?>
根據CSV大小,您可能要考慮使用MySQL的本機CSV導入功能,因為它的運行速度快10到100倍。
如果確實堅持逐行導入,則可以使用PDO進行類似的操作(或使其適應mysqli)。
如果要匹配列,則將csv存儲為關聯數組,或者解析第一行並將其存儲在$ cols之類的數組中。
在這種情況下,$ results是一個關聯數組,用於存儲一行csv,其中column_name => column_value
$cols=implode(',',array_keys($result));
$vals=':'.str_replace(",",",:",$cols);
$inserter = $pdo->prepare("INSERT INTO `mydb`.`mytable`($cols) VALUES($vals);");
foreach ($result as $k => $v) {
$result[':' . $k] = utf8_encode($v);
if(is_null($v))
$result[':' . $k] = null;
unset($result[$k]);
}
$inserter->execute($result);
希望這可以幫助。 我建議使用PDO只是為了避免在CSV數據中可能遇到的各種怪異現象。
這就是我創建列/值的方式。
$is_first=true;
$cols='';
$vals='';
$cols_array=array();
while (($csv = fgetcsv($handle)) !== false) {
if($is_first)
{
$cols_array=$csv;
$cols=implode(',',$csv);
$is_first=false;
$vals=':'.str_replace(",",",:",$cols);
continue;
}
foreach ($result as $k => $v) {
$result[':' . $cols_array[$k]] = utf8_encode($v);
if(is_null($v))
$result[':' . $cols_array[$k]] = null;
unset($result[$k]);
}
$inserter->execute($result);
}
這是我用於CSV導入的代碼。
$file='data/data.csv';
$handle = fopen($file, "r");
$path=realpath(dirname(__FILE__));
$full_path=$path."/../../$file";
$cnt = 0;
$is_first = true;
$headers=array();
$bind=array();
$csv = fgetcsv($handle, 10000, ",");
$headers=$csv;
$alt_query='LOAD DATA LOCAL INFILE \''.$full_path.'\' INTO TABLE mytable
FIELDS TERMINATED BY \',\'
ENCLOSED BY \'\"\'
LINES TERMINATED BY \'\r\n\'
IGNORE 1 LINES
(' . implode(',',$headers).')';
echo exec("mysql -e \"USE mydb;$alt_query;\"",$output,$code);
假設表和CSV之間的關系是任意的,但現在是統一的,則只需建立一次對應數組索引->表列即可。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.