【问题标题】:Best way to INSERT from CSV file into two 1 to many related MySQL tables从 CSV 文件插入两个 1 到多个相关 MySQL 表的最佳方法
【发布时间】:2013-04-14 21:36:54
【问题描述】:

我正在使用 PHP 和 MySQL

我有 2 个表格,布局如下:(还有其他字段与此问题无关)

QUESTIONS Q_ID, int, auto incrementing, primary key Question, varchar(255)

ANSWERS A_ID, int, auto incrementing, primary key Q_ID, int Key, varchar(255) D1, varchar(255) D2, varchar(255) D3, varchar(255) D4, varchar(255)

我有一个 CSV 文件,其布局如下:

NULL, Question, Key, D1, D2, D3, D4 -- The NULL is for the Q_ID autoincrement field.

我想将 CSV 文件中的数据插入到 2 个相关表中,QuestionsAnswers,以一对多关系连接。注意: NULL 和问题进入问题表(1 行) 键、D1、D2、D3 和 D4 进入 Answers 表,但作为单独的记录,每个记录都有一个 Q_ID,该 Q_ID 链接回其匹配的问题。

我有一个文件,它读取 CSV 并创建一个正常工作的 $array

如果我遍历 $array 以创建带有复合 VALUES 子句的单个 INSERT 语句,那么我将所有问题插入到一个查询中,即

INSERT INTO Questions 
    (Q_ID, Client_ID, Question, Key, D1, D2, D3, D4)
VALUES 
    ('$arr[0][1]', '$client_ID', '$arr[0][2]', '$arr[0][3]', '$arr[0][4]', '$arr[0][5]', '$arr[0][6]'' )
    ('$arr[1][1]', '$client_ID', '$arr[1][2]', '$arr[1][3]', '$arr[1][4]', '$arr[1][5]', '$arr[1][6]'' )
    ('$arr[2][1]', '$client_ID', '$arr[2][2]', '$arr[2][3]', '$arr[2][4]', '$arr[2][5]', '$arr[2][6]'' )
    ('$arr[n][1]', '$client_ID', '$arr[n][2]', '$arr[n][3]', '$arr[n][4]', '$arr[n][5]', '$arr[n][6]'' );

在多用户环境中,我可以指望自动增量Q_ID 字段对于这些记录是连续的,即使它们有很多?将其作为交易进行处理吗?如果我可以确定连续的Q_IDs,我可以通过少得多的查询来提高效率。还是担心这种类型的性能会适得其反?

然后我将能够通过从插入执行后收集的last_insert_id 中减去插入的行数来计算第一个Q_ID 数。在将INSERTs 创建到 Answers 表中时,我将使用它,为每个新行递增它。

我无法在我的单用户开发环境中对此进行测试。当然,Q_IDs 总是连续的。

如果我不能指望 Q_ID 是连续的,看来我必须在“问题”中插入一次,获取last_insert_id,然后在答案中执行多VALUES 子句INSERT CSV 中的每一行。

虽然我没有在这里展示,但我将使用 mysql_real_escape_string 来清理这个用户在这两种方法中提交的数据。

或者有没有更好的方法?

arheops 在下面建议我创建一个临时表以避免使用许多查询。我理解这种推理,但不明白他对如何将每条记录 INSERTed 答案中的多个记录 INSERT 到问题中的解释。

【问题讨论】:

  • 尝试循环和字符串连接

标签: php mysql sql-insert


【解决方案1】:

最好的方法是创建与 csv 文件相同的临时表,然后创建插入/选择语句来填充您的表。

注意,serial(autoincrement) 值并不总是一对一的。在并发环境下可以+2或+3差。

我通常是这样的:

1) 一张表全部导入

2) 做 insert into table1(field1,field2,...fieldn) select field1,field2,... fieldn from temp_table;

3) 之后连接 table1 和 temp_table 以获取 ID 并创建 select 以插入 table2。

注意,为了加速连接需要在连接列上创建索引(问题文本?)

【讨论】:

  • 好的,我想我使用LOAD DATA INFILE 将数据放入临时表中?我什么时候清理这个用户提交的 CVS 文件中的数据。如果我在临时文件上有一个索引并且仍然进行 2 次单独的插入,这会更快还是更容易?
  • 以插入的形式插入 tab1(field1,field,...fieldn) 值 (1,2,...n),(11,22, .. nn)... ;所以在这一步检查它。或加载数据,但这需要特殊权限。因为您确实批量选择每个表,所以速度会更快。 last_insert_id 不是那么快(每次新查询)。
  • 我不明白。一旦我在临时表中获得数据,其中问题、关键和所有干扰项都是同一记录中的字段,我该如何创建您说要使用的 INSERT 命令?
  • 您需要创建 2 个选择:第一个用于将插入到第一个表中,第二个用于在第一个表中查找(使用连接)插入到几秒钟内。如果两个 quaries 都小心创建,它会比你的变体更快地运行很多小查询。
猜你喜欢
  • 2014-12-08
  • 1970-01-01
  • 1970-01-01
  • 2014-04-13
  • 2012-03-15
  • 2016-08-08
  • 2018-03-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多