【问题标题】:PHP PDO - import sql files ignoring duplicatesPHP PDO - 导入忽略重复的sql文件
【发布时间】:2016-03-22 14:55:47
【问题描述】:

我编写了一个脚本,负责将 sql 文件导入数据库。这是它的样子:

<?php

$mysql_host = 'localhost';
$mysql_username = '';
$mysql_password = '';
$mysql_database = '';

try
   {
     $db = new PDO('mysql:dbname='.$mysql_database.';host='.$mysql_host,$mysql_username,$mysql_password);
     $sql = implode(array_map(function ($v) {
        return file_get_contents($v);
        }, glob(__DIR__ . "/*.sql")));

     $qr = $db->exec($sql); 
     echo "Import action - 100% successfull";
   }
   catch (PDOException $e) 
   {
     echo 'Connection failed: ' . $e->getMessage();
}
?>
<BR />

它有效。但我想再添加一项功能 - 避免插入重复项。目前,每次我运行脚本时,我都会导入文件,最后 - 创建一堆重复项。如何让它正常工作?或者至少 - 覆盖数据库中的所有内容(但我想避免这样的解决方案..)

【问题讨论】:

  • 你在说什么样的重复?有同名的文件吗?或者单独的文件是否包含相同的 INPUT 语句?

标签: mysql database pdo import


【解决方案1】:
  1. 在需要唯一的字段上创建unique index or primary key

  2. 可选 - 如果您想在事务中执行多个插入:确保您的会话的 sql mode 未设置为严格。如果设置为严格,则将其更改为非严格。

  3. 执行插入

3.b 可选:如果您选择不使用sql模式,但仍希望每个事务执行超过1次插入,则通过在php代码中插入后插入ignore关键字将插入更改为插入忽略。

  1. 可选:如果您必须在第 2 步中更改 sql 模式,则将 sql 模式设置回原来的模式。

如果您使用插入忽略或禁用严格 sql 模式(引用自 sql 模式链接)会有一些缺点:

如果严格模式未生效,MySQL 会为无效或缺失值插入调整值并产生警告(请参阅第 13.7.5.40 节,“显示警告语法”)。在严格模式下,您可以使用 INSERT IGNORE 或 UPDATE IGNORE 来产生这种行为。

【讨论】:

  • 我在所有要通过上述文件插入数据的表中都有主键。然而,我的代码仍然重复了一些行。您能以某种方式帮助我处理脚本本身吗?
  • 如果你定义了一个主键,那么你不能有重复的行,至少pk必须不同。因此,您需要更具体地了解重复记录的含义。
  • ok - 假设我们有一个名为 VISITORS 的表,其中包含列(id、name、surname、phone、sales)。我的主键是 id。我有一排:#1 |约翰 |道尔 | 4433222 | 320)。该记录存在于我从中创建 sql 文件的离线数据库中,也存在于在线数据库(目标之一)中。当我使用我的脚本时,这条记录将被添加为例如#201 |约翰 |道尔 | 4433222 | 320. 我想避免这种情况——我只想插入那些在目标数据库中仍然不可用的行。
  • 那么你需要在你不想重复的字段组合上创建一个唯一索引。另一种选择是将数据导入到一个空的临时表中,并使用带有左连接的插入选择将数据移动到那里不存在的生产表中。
  • 在哪里创建唯一索引?在脚本或表格中还是在哪里?
【解决方案2】:

我怀疑你的意思是那里有一堆相同的陈述。如果都是简单的语句,并且没有;的字符串值,那么你可以尝试使用:

$sql = implode(';', array_unique(array_map('trim', explode(';', $sql))));

但话说回来,有很多极端情况

  • 不同的语句可以插入相同的东西
  • 有一个带有;的字符串值(这不一定是问题)
  • 在 sql 中使用不同的分隔符
  • 如果SQL文件中有存储过程/触发器/函数
  • ...

但这只是一个开始,也许它足以满足您的用例

【讨论】:

  • 我每天上传几次几个 sql 文件。它们中的每一个都包含对特定数据库表的插入语句。我想避免的是通过文件导入复制某些值时的情况。原因是这些文件是由备份脚本生成的,因此它们包含所有数据库数据。我只想导入目标数据库中不存在的此类数据
  • @JuliaGalden 表上没有主键/唯一键吗?
  • 一切(在所有文件中)看起来像这样:INSERT INTO SALES(DATA, WIZ_ID, CUST_ID, ANI_ID, DOCTOR_ID, TYP_WIZ, DOC_TYPE_ID, AMOUNT, DBS-DATE, DBS-HOUR) VALUES ('2015 -07-27', 10000012, '011500010', '011500012', 3431, 1, 'PARAGON', 100.0000, '2015-07-27', '10:25:56');
猜你喜欢
  • 2017-11-15
  • 2011-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-24
  • 1970-01-01
  • 2018-04-26
相关资源
最近更新 更多