如提,上網查了方式有看到
使用transaction 方式做的,還有看到準備好多筆的,想請問這兩種方式有差別嗎?
想請問如果是PDO 然後寫成第一種方式,新增筆數不固定應該如何寫呢?
第一種
INSERT INTO table_name
VALUES (value1_1, value2_2, value3_3,···),
(value2_1, value2_2, value2_3,···),
(value3_1, value3_2, value3_3,···),
······;
第二種
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDBPDO";
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// begin the transaction
$conn->beginTransaction();
// our SQL statements
$conn->exec("INSERT INTO MyGuests (firstname, lastname, email)
VALUES ('John', 'Doe', 'john@example.com')");
$conn->exec("INSERT INTO MyGuests (firstname, lastname, email)
VALUES ('Mary', 'Moe', 'mary@example.com')");
$conn->exec("INSERT INTO MyGuests (firstname, lastname, email)
VALUES ('Julie', 'Dooley', 'julie@example.com')");
// commit the transaction
$conn->commit();
echo "New records created successfully";
} catch(PDOException $e) {
// roll back the transaction if something failed
$conn->rollback();
echo "Error: " . $e->getMessage();
}
$conn = null;
?>
以下是小弟的程式
try{
$conn->beginTransaction();
// add_room
for($i=0;$i<count($_POST['data_ar']);$i++){
$sql_add_room = "INSERT INTO
`tw_room_list`(`room_name`,`monthly_rental_amount`,`security_deposit_amount`,`room_floor`)
VALUES
(:house_id,:room_name,:monthly_rental_amount,:security_deposit_amount,:room_floor)";
$result_add_room = $conn->prepare($sql_add_room);
$status = $result_add_room->execute(array(
":room_name"=>"{$_POST['data_ar'][$i]['room_name']}",
":monthly_rental_amount"=>"{$_POST['data_ar'][$i]['monthly_rental_amount']}",
":security_deposit_amount"=>"{$_POST['data_ar'][$i]['security_deposit_amount']}",
":room_floor"=>"{$_POST['data_ar'][$i]['room_floor']}",
));
}
if($conn->commit()){
echo 'success';
}
}catch(PDOException $e){
$conn->rollBack();
echo 'error';
}
$conn=null;
兩種我都會視情況使用。
第一種在速度上會比較快且直接。
但記憶體用量會很多。效能不允許的情況下會比較容易發生問題。
一般適合少欄位資料的情況下。或是一筆資料不會超過1k容量。且不超過1000~2000筆的情況下。
我會用第一種。
第二種速度會比較慢。(慢很多)。但比較不容易去影響到業務操作。
基本上來說,需要即時性的情況下。會選擇第一種插入的方式。
如果可以後續處理的,會選用第二種方式處理。
兩者方法都各有其優缺點。沒辦法說哪一種比較好比較不好。
我是兩種都會用。
感謝,想請問,我試著用PDO去寫,但卡在execute。
我的execute()要怎麼放入呢?謝謝
$sql_add_room = "INSERT INTO
`tw_room_list`(`house_id`,`room_name`,`monthly_rental_amount`,`security_deposit_amount`,`room_floor`)
VALUES
(:house_id,:room_name,:monthly_rental_amount,:security_deposit_amount,:room_floor),
(:house_id,:room_name,:monthly_rental_amount,:security_deposit_amount,:room_floor)";
$result_add_room = $conn->prepare($sql_add_room);
$status = $result_add_room->execute(array(':house_id' => '321',':room_name' => '2'),array(':house_id' => '321',':room_name' => '2'));
非常感謝
說真的,我會直接串字串。
但如果為了安全起見。我會程式化字串出來。
$sql_add_room = "INSERT INTO `tw_room_list`(`house_id`,`room_name`,`monthly_rental_amount`,`security_deposit_amount`,`room_floor`)
VALUES ";
$sqlAdd=[];
$dataAdd=[];
foreach($data AS $n=>$_d){
$sqlAdd[] = "(:house_id_{$n},:room_name_{$n},:monthly_rental_amount_{$n},:security_deposit_amount_{$n},:room_floor_{$n})";
$dataAdd[':house_id_'.$n] = $_d['house_id'];
$dataAdd[':room_name_'.$n] = $_d['house_id'];
$dataAdd[':monthly_rental_amount_'.$n] = $_d['house_id'];
$dataAdd[':security_deposit_amount_'.$n] = $_d['house_id'];
$dataAdd[':room_floor_'.$n] = $_d['house_id'];
}
$sql_add_room .= implode(',',$sqlAdd);
$result_add_room = $conn->prepare($sql_add_room);
$status = $result_add_room->execute($dataAdd);
上面我只大略打一下,不確定正確性。自已研究一下。
我只是給個理念出來而已。請不要照抄
簡單來說第一種在寫入的時候速度比較快(就是一次寫入多筆)
第二種比較慢因為它算是一筆一筆寫入
第一種遇到不固定筆數的寫法
//先組合data
$data = [];
foreach($data as $item){
$data[] = "(value1, value2, value3, .... )";
}
$sql = "INSERT INTO table_name VALUES" . implode(',', $data);
大概這樣
應該這樣講,一筆一筆insert的,你在無法保証工作是否會因為網路或電腦不穩定而中斷的情況下,是非常冒險的一件事,你的交易如果有10000行,你執行到100行時電腦當掉,你能忍受只有存進了99筆?還是一定要保証10000筆都完成才可以?真的要缺一不可,那你就得做
start transaction ;
....
commit ;
雖然說現在的電腦、網路都已不是吳下阿蒙,但~~意外總是會在意想不到的時候出現
兩種都是全寫入或是全不寫入。
第一種算是只下一次命令,第二種是分好幾次下。
但是第一種如果是自己接字串的話,可能要做好過濾,不然會有注入的風險。
第二種則是要注意效能的問題,也有可能會出現 deadlock(死鎖 OR 死結) 的狀況。
PS. 第一種配合 prepare 的方式研究中...
關於程式的部分:
for($i=0;$i<count($_POST['data_ar']);$i++){
這邊建議把count($_POST['data_ar'])
先用變數暫存起來,才不用迴圈每跑一次都要呼叫 count 函式。try{
$conn=new PDO('...略');
$sql = 'INSERT INTO `test`(
`name`,
`price`
) VALUES (
:name,
:price
)';
$stmt = $conn->prepare($sql);
$stmt->bindParam(':name', $name, PDO::PARAM_STR);
$stmt->bindParam(':price', $price, PDO::PARAM_INT);
foreach($datas as $row){
$name=$row['name'];
$price=$row['price'];
if($stmt->execute()===false) {
throw new Exception('error');
}
}
echo 'success';
}catch(PDOException $e){
echo $e;
}
非常感謝
把資料先弄成 json 格式,
然後在 stored procedure 中去解析 json
組成 prepare
接著套用
start transaction ;
....
commit ;