使用 php 脚本检查来自一个 table 的重复记录并将重复记录插入到另一个 table
Check duplication record from one table and duplication record insert to another table using php script
下面我有两个tables
1)候选人详情
EmployeeId FirstName LastName Mobile Email BatchId
1 fn1 ln1 123456789 Email1 75
2 fn2 ln2 123456790 Email2 75
3 fn3 ln3 123456791 Email3 75
4 fn4 ln4 123456792 Email4 75
2)重复候选人
EmployeeId FirstName LastName Mobile Email BatchId
我的要求是,如果 EmployeeId 在 CandidateDetails table 中已经可用,则复制记录插入到 DuplicateCandidate
下面是 PHP 脚本,仅用于将数组插入 CandidateDetails table,但我无法检查员工 ID 是否重复的条件然后将该记录插入另一个 DuplicateCandidate table.
<?php
header("Access-Control-Allow-Origin: http://localhost:4200");
header("Access-Control-Allow-Credentials: true ");
header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
header("Access-Control-Allow-Headers: X-Custom-Header, Origin, Content-Type , Authorisation , X-Requested-With");
header("Content-Type: application/json; charset=UTF-8 ");
$json = file_get_contents('php://input');
$decoded = json_decode($json, true);
print_r($decoded);
$id=$_GET['id'];
function conn() {
$dbhost = "xxxx";
$user = "xxx";
$pass = "xxx";
$db = "xxxx";
$conn = new PDO('mysql:host=xxx;dbname=xxx', $user, $pass);
return $conn;
}
$db = conn();
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$p = $db->prepare("INSERT INTO CandidateDetails(EmployeeId, FirstName, LastName, Mobile,Email,BatchId)VALUES(:EmployeeId,:FirstName,:LastName,:Mobile,:Email,'$id')");
foreach ($decoded as $item) {
$p->execute($item);
}
echo json_encode(true);
?>
<?php
header("Access-Control-Allow-Origin: http://localhost:4200");
header("Access-Control-Allow-Credentials: true ");
header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
header("Access-Control-Allow-Headers: X-Custom-Header, Origin, Content-Type , Authorisation , X-Requested-With");
header("Content-Type: application/json; charset=UTF-8 ");
$json = file_get_contents('php://input');
$decoded = json_decode($json, true);
print_r($decoded);
$id = $_GET['id'];
function conn()
{
$dbhost = "x.x.x.x";
$user = "x";
$pass = "x";
$db = "x";
$conn = new PDO('mysql:host=x;dbname=x', $user, $pass);
return $conn;
}
$db = conn();
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
foreach ($decoded as $item)
{
echo $item['EmployeeId'];
$sql = "SELECT * FROM CandidateDetails WHERE EmployeeId = " . $item['EmployeeId'];
//$result = $conn- >query($sql);
echo $item['EmployeeId'];
echo $sql;
$result = $db->query($sql);
//echo $result;
//echo $result->num_rows;
$count = $result->rowCount();
echo $count;
if ($count > 0)
{
//DuplicateCandidate
echo "duplicte results";
//$p = $db->prepare("INSERT INTO CandidateDetailsLog(EmployeeId, FirstName, LastName, Mobile,Email,BatchId)VALUES(:EmployeeId,:FirstName,:LastName,:Mobile,:Email,'$id')");
$p = $db->prepare("INSERT INTO CandidateDetailsLog(EmployeeId, FirstName, LastName, Mobile,Email,BatchId)
VALUES ('" . $item['EmployeeId'] . "', '" . $item['FirstName'] . "',
'" . $item['LastName'] . "', '" . $item['Mobile'] . "', '" . $item['Email'] . "',
'" . $id . "')");
$p->execute();
}
else
{
echo "0 results";
//$p = $db->prepare("INSERT INTO CandidateDetails(EmployeeId, FirstName, LastName, Mobile,Email,BatchId)VALUES(:EmployeeId,:FirstName,:LastName,:Mobile,:Email,'$id')");
$p = $db->prepare("INSERT INTO CandidateDetails(EmployeeId, FirstName, LastName, Mobile,Email,BatchId)
VALUES ('" . $item['EmployeeId'] . "', '" . $item['FirstName'] . "',
'" . $item['LastName'] . "', '" . $item['Mobile'] . "', '" . $item['Email'] . "',
'" . $id . "')");
$p->execute();
}
}
$o = $db->prepare("UPDATE BatchDetailsInfo SET BatchStatus='B2' WHERE BatchId='$id'");
$o->execute();
echo json_encode(true);
?>
虽然接受的答案可以完成这项工作,但它有几个 SQL injection 漏洞,包括 $_GET['id']
(不应该被信任 - 恶意行为者可以在此处放置任何东西,包括 SQL 命令来清除你的数据库),以及从 php://input
收集的 JSON(同样 - 即使它是有效的 JSON 你也可以在这里隐藏删除数据的命令)。参数转义(作为您的原始示例)是可行的方法。
<?php
/* Your headers etc here*/
///Build a database connection
function db_conn() {
/* Your Mysql setup with user/pass/db etc in a PDO object here*/
$db=new PDO('mysql:host=x;dbname=x', $user, $pass);
//You might want to set this here (for all connections:)
//$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $db;
}
///Search the candidate table for an entry for the given ID
function db_employeeCandidateExists($db,$dangerEmployeeId) {
$stmt=$db->prepare('SELECT EmployeeId FROM CandidateDetails WHERE EmployeeId=?');
$stmt->execute([$dangerEmployeeId]);
$result=$stmt->fetchAll();//We're expecting 0 rows (not found) or 1 row with the ID if it's a dup
return count($result)>0;
}
///Add a row to the DuplicateCandidate table
function db_addDuplicate($db,$dangerRow,$dangerBatchId) {
//All columns you want to fill out - layed out to be visually obvious how many there are
$cols=['EmployeeId',
'FirstName',
'LastName',
'Mobile',
'Email',
'BatchId'];
//Values for the above columns - layed out to be visually equal to above
// don't forget
$vals=[$dangerRow['EmployeeId'],
$dangerRow['FirstName'],
$dangerRow['LastName'],
$dangerRow['Mobile'],
$dangerRow['Email'],
$dangerBatchId];
//The parameters can use a count of the cols (above)
$params=substr(str_repeat('?,',count($cols)),0,-1);
$stmt=$db->prepare('INSERT INTO DuplicateCandidate ('.
implode(',',$cols).
') VALUES ('.
$params.
')');
$stmt->execute($vals);
//todo: You might want to check there are no SQL errors reported here
}
///Add a row to the CandidateDetails table
function db_addCandiate($db,$dangerRow,$dangerBatchId) {
//All columns you want to fill out - layed out to be visually obvious how many there are
$cols=['EmployeeId',
'FirstName',
'LastName',
'Mobile',
'Email',
'BatchId'];
//Values for the above columns - layed out to be visually equal to above
// don't forget
$vals=[$dangerRow['EmployeeId'],
$dangerRow['FirstName'],
$dangerRow['LastName'],
$dangerRow['Mobile'],
$dangerRow['Email'],
$dangerBatchId];
//The parameters can use a count of the cols (above)
$params=substr(str_repeat('?,',count($cols)),0,-1);
$stmt=$db->prepare('INSERT INTO CandidateDetails ('.
implode(',',$cols).
') VALUES ('.
$params.
')');
$stmt->execute($vals);
//todo: You might want to check there are no SQL errors reported here
}
///Get JSON from input and decode it into an associative array
function getJson() {
$json = file_get_contents('php://input');
return json_decode($json, true);
}
$db = db_conn();
//You might want to set this inside the `conn()` method for all usage?
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// *** *** Dangerous CONTENT *** ***
// Both $id (presuambly an integer) and $json (an associative array of data)
// are user-provided and therefore the cannot be trusted - you NEED to escape these
// values before using them in SQL
$dangerBatchId = $_GET['id'];
$dangerJson = getJson();
foreach($dangerJson as $dangerItem)
{
if (db_employeeCandidateExists($db,$dangerItem['EmployeeId'])) {
//Duplicate
db_addDuplicate($db,$dangerItem,$dangerBatchId);
echo 'Applicant '.$dangerItem['EmployeeId']." was a duplicate\n";
} else {
db_addCandiate($db,$item,$dangerBatchId);
echo 'Applicant '.$dangerItem['EmployeeId']." added\n";
}
}
// Further processing
我使用了位置参数转义 (?
),它应该也适用于 MySQL。命名位置转义 (:id
) 可能更好,但不允许我快速生成所有参数(构建 $params
字符串),而且我测试的数据库不支持它们。
将组件分离成函数后(就像我所做的那样),您会注意到我们有一些以 db_
开头的函数分组......您可以相反地配置捆绑这些变成class。那时你可以避免将 $db
作为第一个参数传递,因为你可以在 class 内部共享它。 但是那是一个完全不同的话题,超出了你原来问题的范围。
下面我有两个tables
1)候选人详情
EmployeeId FirstName LastName Mobile Email BatchId
1 fn1 ln1 123456789 Email1 75
2 fn2 ln2 123456790 Email2 75
3 fn3 ln3 123456791 Email3 75
4 fn4 ln4 123456792 Email4 75
2)重复候选人
EmployeeId FirstName LastName Mobile Email BatchId
我的要求是,如果 EmployeeId 在 CandidateDetails table 中已经可用,则复制记录插入到 DuplicateCandidate
下面是 PHP 脚本,仅用于将数组插入 CandidateDetails table,但我无法检查员工 ID 是否重复的条件然后将该记录插入另一个 DuplicateCandidate table.
<?php
header("Access-Control-Allow-Origin: http://localhost:4200");
header("Access-Control-Allow-Credentials: true ");
header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
header("Access-Control-Allow-Headers: X-Custom-Header, Origin, Content-Type , Authorisation , X-Requested-With");
header("Content-Type: application/json; charset=UTF-8 ");
$json = file_get_contents('php://input');
$decoded = json_decode($json, true);
print_r($decoded);
$id=$_GET['id'];
function conn() {
$dbhost = "xxxx";
$user = "xxx";
$pass = "xxx";
$db = "xxxx";
$conn = new PDO('mysql:host=xxx;dbname=xxx', $user, $pass);
return $conn;
}
$db = conn();
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$p = $db->prepare("INSERT INTO CandidateDetails(EmployeeId, FirstName, LastName, Mobile,Email,BatchId)VALUES(:EmployeeId,:FirstName,:LastName,:Mobile,:Email,'$id')");
foreach ($decoded as $item) {
$p->execute($item);
}
echo json_encode(true);
?>
<?php
header("Access-Control-Allow-Origin: http://localhost:4200");
header("Access-Control-Allow-Credentials: true ");
header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
header("Access-Control-Allow-Headers: X-Custom-Header, Origin, Content-Type , Authorisation , X-Requested-With");
header("Content-Type: application/json; charset=UTF-8 ");
$json = file_get_contents('php://input');
$decoded = json_decode($json, true);
print_r($decoded);
$id = $_GET['id'];
function conn()
{
$dbhost = "x.x.x.x";
$user = "x";
$pass = "x";
$db = "x";
$conn = new PDO('mysql:host=x;dbname=x', $user, $pass);
return $conn;
}
$db = conn();
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
foreach ($decoded as $item)
{
echo $item['EmployeeId'];
$sql = "SELECT * FROM CandidateDetails WHERE EmployeeId = " . $item['EmployeeId'];
//$result = $conn- >query($sql);
echo $item['EmployeeId'];
echo $sql;
$result = $db->query($sql);
//echo $result;
//echo $result->num_rows;
$count = $result->rowCount();
echo $count;
if ($count > 0)
{
//DuplicateCandidate
echo "duplicte results";
//$p = $db->prepare("INSERT INTO CandidateDetailsLog(EmployeeId, FirstName, LastName, Mobile,Email,BatchId)VALUES(:EmployeeId,:FirstName,:LastName,:Mobile,:Email,'$id')");
$p = $db->prepare("INSERT INTO CandidateDetailsLog(EmployeeId, FirstName, LastName, Mobile,Email,BatchId)
VALUES ('" . $item['EmployeeId'] . "', '" . $item['FirstName'] . "',
'" . $item['LastName'] . "', '" . $item['Mobile'] . "', '" . $item['Email'] . "',
'" . $id . "')");
$p->execute();
}
else
{
echo "0 results";
//$p = $db->prepare("INSERT INTO CandidateDetails(EmployeeId, FirstName, LastName, Mobile,Email,BatchId)VALUES(:EmployeeId,:FirstName,:LastName,:Mobile,:Email,'$id')");
$p = $db->prepare("INSERT INTO CandidateDetails(EmployeeId, FirstName, LastName, Mobile,Email,BatchId)
VALUES ('" . $item['EmployeeId'] . "', '" . $item['FirstName'] . "',
'" . $item['LastName'] . "', '" . $item['Mobile'] . "', '" . $item['Email'] . "',
'" . $id . "')");
$p->execute();
}
}
$o = $db->prepare("UPDATE BatchDetailsInfo SET BatchStatus='B2' WHERE BatchId='$id'");
$o->execute();
echo json_encode(true);
?>
虽然接受的答案可以完成这项工作,但它有几个 SQL injection 漏洞,包括 $_GET['id']
(不应该被信任 - 恶意行为者可以在此处放置任何东西,包括 SQL 命令来清除你的数据库),以及从 php://input
收集的 JSON(同样 - 即使它是有效的 JSON 你也可以在这里隐藏删除数据的命令)。参数转义(作为您的原始示例)是可行的方法。
<?php
/* Your headers etc here*/
///Build a database connection
function db_conn() {
/* Your Mysql setup with user/pass/db etc in a PDO object here*/
$db=new PDO('mysql:host=x;dbname=x', $user, $pass);
//You might want to set this here (for all connections:)
//$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $db;
}
///Search the candidate table for an entry for the given ID
function db_employeeCandidateExists($db,$dangerEmployeeId) {
$stmt=$db->prepare('SELECT EmployeeId FROM CandidateDetails WHERE EmployeeId=?');
$stmt->execute([$dangerEmployeeId]);
$result=$stmt->fetchAll();//We're expecting 0 rows (not found) or 1 row with the ID if it's a dup
return count($result)>0;
}
///Add a row to the DuplicateCandidate table
function db_addDuplicate($db,$dangerRow,$dangerBatchId) {
//All columns you want to fill out - layed out to be visually obvious how many there are
$cols=['EmployeeId',
'FirstName',
'LastName',
'Mobile',
'Email',
'BatchId'];
//Values for the above columns - layed out to be visually equal to above
// don't forget
$vals=[$dangerRow['EmployeeId'],
$dangerRow['FirstName'],
$dangerRow['LastName'],
$dangerRow['Mobile'],
$dangerRow['Email'],
$dangerBatchId];
//The parameters can use a count of the cols (above)
$params=substr(str_repeat('?,',count($cols)),0,-1);
$stmt=$db->prepare('INSERT INTO DuplicateCandidate ('.
implode(',',$cols).
') VALUES ('.
$params.
')');
$stmt->execute($vals);
//todo: You might want to check there are no SQL errors reported here
}
///Add a row to the CandidateDetails table
function db_addCandiate($db,$dangerRow,$dangerBatchId) {
//All columns you want to fill out - layed out to be visually obvious how many there are
$cols=['EmployeeId',
'FirstName',
'LastName',
'Mobile',
'Email',
'BatchId'];
//Values for the above columns - layed out to be visually equal to above
// don't forget
$vals=[$dangerRow['EmployeeId'],
$dangerRow['FirstName'],
$dangerRow['LastName'],
$dangerRow['Mobile'],
$dangerRow['Email'],
$dangerBatchId];
//The parameters can use a count of the cols (above)
$params=substr(str_repeat('?,',count($cols)),0,-1);
$stmt=$db->prepare('INSERT INTO CandidateDetails ('.
implode(',',$cols).
') VALUES ('.
$params.
')');
$stmt->execute($vals);
//todo: You might want to check there are no SQL errors reported here
}
///Get JSON from input and decode it into an associative array
function getJson() {
$json = file_get_contents('php://input');
return json_decode($json, true);
}
$db = db_conn();
//You might want to set this inside the `conn()` method for all usage?
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// *** *** Dangerous CONTENT *** ***
// Both $id (presuambly an integer) and $json (an associative array of data)
// are user-provided and therefore the cannot be trusted - you NEED to escape these
// values before using them in SQL
$dangerBatchId = $_GET['id'];
$dangerJson = getJson();
foreach($dangerJson as $dangerItem)
{
if (db_employeeCandidateExists($db,$dangerItem['EmployeeId'])) {
//Duplicate
db_addDuplicate($db,$dangerItem,$dangerBatchId);
echo 'Applicant '.$dangerItem['EmployeeId']." was a duplicate\n";
} else {
db_addCandiate($db,$item,$dangerBatchId);
echo 'Applicant '.$dangerItem['EmployeeId']." added\n";
}
}
// Further processing
我使用了位置参数转义 (?
),它应该也适用于 MySQL。命名位置转义 (:id
) 可能更好,但不允许我快速生成所有参数(构建 $params
字符串),而且我测试的数据库不支持它们。
将组件分离成函数后(就像我所做的那样),您会注意到我们有一些以 db_
开头的函数分组......您可以相反地配置捆绑这些变成class。那时你可以避免将 $db
作为第一个参数传递,因为你可以在 class 内部共享它。 但是那是一个完全不同的话题,超出了你原来问题的范围。