我有两个mysql表,我想在两个表中插入一封电子邮件。
我需要将电子邮件拆分为name
和domain name
,然后将其中的每一部分插入一个表格。
我的domain
表格如下:
+----+--------+
| id | domain | primary(id)
+----+--------+
和我的email
表是:
+-------+----------+
| eMail | domainId | primary key(eMail, domainId)
+-------+----------+
即:info@example.com> example.com
必须在domain
表中插入
info
必须在email
表中添加domainId。
域必须是唯一的。
我的尝试:
foreach($emails as $email)
{
list($account,$hostname) = explode('@',$email,2);
$query = $dbh->prepare("SELECT id FROM domain WHERE domain LIKE :domain LIMIT 0,1");
$query->execute(array(':domain'=>trim($hostname)));
if($query->rowCount())
{
$id = $query->fetch();
$id = $id['id'];
}else{
$insert = $dbh->prepare("INSERT INTO domain (domain) VALUES (:domain)");
$insert->execute(array(':domain'=>trim($hostname)));
$id = $dbh->lastInsertId();
}
$name = $dbh->prepare("INSERT INTO email (eMail, domainId) VALUES (:eMail, :domainId)");
$name->execute(array(':eMail'=>trim($account),':domainId'=>$id));
}
但是当我想添加批量电子邮件时,这种方式非常慢:
有没有更快的方法,或者我可以在单个查询中执行此操作..?
答案 0 :(得分:3)
仅插入电子邮件并向email
表添加触发器,以提取域名并自动将其插入domain
DELIMITER |
CREATE TRIGGER insert_domain_trigger BEFORE INSERT ON email
FOR EACH ROW
begin
set @domainname = substring(NEW.email, instr(NEW.email, '@') + 1);
if(select count(*) from domain where domain = @domainname) = 0
then
insert into domain (domain) values (@domainname);
end if;
end
|
答案 1 :(得分:1)
由于您有来自同一域的大量电子邮件,因此您可以尝试在本地php变量中缓存域ID,以减少对db的查询数。
此外,您应该在循环之外准备$insert
和$name
语句。
$domains = array();
foreach($dbh->query("SELECT id, domain FROM domain") as $domain) {
$domains[$domain['domain']] = $domain['id'];
}
$insert = $dbh->prepare("INSERT INTO domain (domain) VALUES (:domain)");
$name = $dbh->prepare("INSERT INTO email (eMail, domainId) VALUES (:eMail,:domainId)");
foreach($emails as $email)
{
list($account,$hostname) = explode('@',$email,2);
$hostname = trim($hostname);
if(!isset($domains[$hostname])) {
$insert->execute(array(':domain'=>$hostname));
$id = $dbh->lastInsertId();
$domains[$hostname] = $id;
}
else {
$id = $domains[$hostname];
}
$name->execute(array(':eMail'=>trim($account),':domainId'=>$id));
}
答案 2 :(得分:1)
也许一个简单的程序可以解决这个问题?
这需要数据库中的字段域为UNIQUE
语法的INSERT IGNORE INTO
类型。
DELIMITER $$
CREATE PROCEDURE `sp_InsertEmail`(IN p_Email VARCHAR(100))
BEGIN
-- Declare variables
DECLARE v_Email VARCHAR(100);
DECLARE v_Domain VARCHAR(100);
-- Set the variables
SET v_Email = SUBSTRING(p_Email,1,INSTR(p_email,'@')-1);
SET v_Domain =SUBSTRING(p_Email,INSTR(p_Email,'@'));
-- Now insert ignore into domain table
INSERT IGNORE INTO db.domain (domain) VALUES(v_Domain);
-- Then insert like this.
INSERT IGNORE INTO db.email SELECT v_Email,DomainId FROM domain WHERE domain=v_Domain;
END
然后只需调用程序
CALL db.sp_InsertEmail('name@domain.com')