【问题标题】:Possible to loop through tables in mySQL (using PHP) with table name containing a variable?可以使用包含变量的表名遍历 mySQL(使用 PHP)中的表吗?
【发布时间】:2018-03-08 11:05:02
【问题描述】:

我对编程和尝试设计一个 Web 应用程序非常陌生,该应用程序提供了一个前端来更新在线课程数据库的数据(表格,包括用户、作业、问题、答案等)。通过课程管理系统提交后,所有数据都将进入该数据库。目前正在使用虚拟数据进行开发。

这个想法是允许用户从前端进行更新,而不是从后端自动进行更新(如使用触发器)。这是因为我们的数据集比较小,不熟悉mysql的用户只需要更新的表就可以导出到数据分析程序中。

使用多个连接,我创建了一个用户已经完成的任务列表,如下所示:

+----+---------------+---------------------------------------+
| id | assignment_id | quiz_name                             |
+----+---------------+---------------------------------------+
|  1 |             2 | Guidance Counselors (Post-Assessment) |
|  2 |             3 | Guidance Counselors (Pre-Assessment)  |
|  3 |             4 | Guidance Counselors (Pre-Assessment)  |
+----+---------------+---------------------------------------+

在 PHP 中,我编写了一个基本的前端代码,用于在多选下拉列表中显示和更新这些分配,如下所示:

Assignment list table

每当用户想要更新列表时,php 都会运行这个 if 语句(与生成上表相同):

  //update assignment list when button is clicked
  if(isset($_POST['updatelist'])){
  //query to update the assignment list
  $sql_update = "DELETE FROM assignment_list;";
  $sql_update .= "TRUNCATE assignment_list;";
  $sql_update .= "INSERT INTO assignment_list....
  #values added from joined assignment, quizzes, and user_quizzes tables
  SELECT...
  INNER JOIN ...
  INNER JOIN ...
   ...
  GROUP BY assignment_id";

      $update_result = mysqli_multi_query($conn,$sql_update);

      //success and error messages here

    }

ETA:然后反映在下拉菜单中。然后,此菜单应允许用户选择一个或多个要更新数据的作业,假设是否有新的用户提交和可用于该作业的分数(即每个作业中包含的数据——在结构上它们都是相同的)。

更新列表似乎有效,但我正在努力找出更新我们所谓的“合并数据”表的最佳方法(为每个单独的任务附加“_(assignment_id)”。所以当一个用户选择“更新数据”,上面所选分配的表中的数据应该更新。例如,consolidated_data_4 看起来像这样(为了更好的可读性省略了一些字段):

+------------------+---------+---------------+---------+-----------------------------+----------------------------+--------------------------------------+-----------+
| consolidation_id | user_id | assignment_id | quiz_id | assignment_pass_score_point | assignment_pass_score_perc | quiz_name                            | answer_id |
+------------------+---------+---------------+---------+-----------------------------+----------------------------+--------------------------------------+-----------+
|                1 |      34 |             4 |      50 |                        5.00 |                      50.00 | Guidance Counselors (Pre-Assessment) |    175973 |
|                2 |      34 |             4 |      50 |                        5.00 |                      50.00 | Guidance Counselors (Pre-Assessment) |    175981 |
|                3 |      34 |             4 |      50 |                        5.00 |                      50.00 | Guidance Counselors (Pre-Assessment) |    175985 |
|                4 |      34 |             4 |      50 |                        5.00 |                      50.00 | Guidance Counselors (Pre-Assessment) |    175991 |
|                5 |      34 |             4 |      50 |                        5.00 |                      50.00 | Guidance Counselors (Pre-Assessment) |    175995 |
|                6 |      34 |             4 |      50 |                        5.00 |                      50.00 | Guidance Counselors (Pre-Assessment) |    175999 |
|                7 |      34 |             4 |      50 |                        5.00 |                      50.00 | Guidance Counselors (Pre-Assessment) |    176002 |
|                8 |      34 |             4 |      50 |                        5.00 |                      50.00 | Guidance Counselors (Pre-Assessment) |    176009 |
|                9 |      34 |             4 |      50 |                        5.00 |                      50.00 | Guidance Counselors (Pre-Assessment) |    176015 |
|               10 |      34 |             4 |      50 |                        5.00 |                      50.00 | Guidance Counselors (Pre-Assessment) |    176021 |
+------------------+---------+---------------+---------+-----------------------------+----------------------------+--------------------------------------+-----------+

当前每个表都由其分配 ID 标识,例如“consolidated_data_4”是一个表,其中该表中的每条记录的 assignment_id = 4。

我尝试遍历每个表(使用 foreach 循环)并执行与上述分配列表类似的查询,但我收到错误,除非我像这样将查询分开(也被删节):

//for each assignment user selects, start with an empty table and join data from corresponding course database tables

    foreach($_POST['selectassign'] as $assignment){
  $table = "quiz_data_update_application.consolidated_data_".$assignment;
  //query updates consolidated data table(s) for selected assignments
  $sql_del = "DELETE FROM $table";
  $sql_trunc = "TRUNCATE $table";

  //records added from joining tables in course db
  $sql_ins = //sql omitted here for brevity
  ....
  $del_sel_res = mysqli_query($conn,$sql_del);
  $trunc_sel_res = mysqli_query($conn,$sql_trunc);
  $ins_sel_res = mysqli_query($conn,$sql_ins);
}

(这与不起作用的代码之间的唯一区别是查询以与上面第一个 PHP sn-p 相同的方式组合;在这里发布似乎是多余的)。

使用单个查询似乎效率低下,并且会降低应用程序的速度。我想知道是否有比在 PHP 循环中使用表名的一部分作为变量更好的方法来解决这个问题。 (不要看到太多人问这个问题或遍历实际表而不是字段)似乎我遗漏了一些愚蠢的语法错误,或者 mysqli_multiquery() 不能在循环中使用/总体上很差方法?

我工作的一些高层建议:

(1) 创建单独的循环 - 一个基于用户选择的分配临时创建一个新表,另一个通过分配将其拆分为单独的表(他们说这部分是优化数据分析所必需的。 IMO 这使得一切都比拥有一个用于所有任务的大型“主”数据表更具挑战性——事实上我确实成功地做到了——但唉,这就是他们要求完成的方式)。这些表将在更新完成后被删除;

(2) 使用存储过程。这我不太熟悉,也不确定它是如何工作的,但如果它比(1)更可行,我可以进一步研究。

任何其他替代方案,更可行的建议也将不胜感激。我在这方面取得了很大进展,但过去几周一直被困在这里,并没有找到太多在线资源。

对帖子的长度表示歉意。我认为有必要提供更多而不是更少的上下文。

【问题讨论】:

  • 如果要使用 truncate 不需要删除
  • multi_query 几乎总是一个坏主意,很难调试
  • 你会建议什么替代方案?
  • 另外,我不知道为什么会同时使用 delete 和 truncate ;这是由一位比我更熟悉mysql的前同事完成的,所以我认为有一个超出我理解范围的原因并就这样离开了。
  • 运行每个查询,检查它是否有效,然后运行下一个查询

标签: php mysql database-design web-applications phpmyadmin


【解决方案1】:

单一查询是要走的路。感知到的低效率并不存在——操作成本比mysqli_query 更高。

如果您有数以千计的表格可供使用,那么我质疑拥有多个相似表格是否明智。相反,有一个额外的列来指示涉及的内容。

DELETE(整个表格)和TRUNCATE 具有几乎相同的效果;没有必要两者都做。 TRUNCATE 更快。

从表中删除一个索引行比截断+插入要快得多。

此外,将删除批处理成单个 SQL 语句甚至更快。一次批量插入多行也是如此。这很容易快 10

【讨论】:

  • 批量删除和插入在遍历表时仍会涉及类似的结构,对吗?我不确定删除一行是什么意思,因为这里的问题是如果不使用触发器就无法检测到新数据的添加位置。因此只需截断表并从立即接收新信息的表中提取所有信息.我同意单独的表格;最初的计划是用一张大表汇总所有作业,然后从那里按作业选择。
  • @R.J. - 如果您能解释数据流(导致删除/插入的原因、频率等),我们可能会更具体,更少挥手。
  • 不确定导致删除/插入的原因是什么意思?正如我所描述的,查询是由用户自行决定运行的,因为当他们从前端选择“更新”选项时,它实际上会刷新整个表。新数据通过插入中的一系列连接语句从课程系统的数据库中添加(应用程序有自己的数据库)。这旨在在不使用触发器的情况下更新数据。抱歉,如果我误解了您的问题。
  • 我还不明白为什么会有多个表,也不明白为什么需要遍历它们。您的上一条评论听起来更像是UPDATEing 一个表中的一行,然后是SELECTing 一个整表。 SHOW CREATE TABLE 可能有助于我理解。
【解决方案2】:

@Rick James 是其中一张表的 SHOW CREATE TABLE,尽管所有表的结构都相同。

+---------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table               | Create Table                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
+---------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| consolidated_data_2 | CREATE TABLE `consolidated_data_2` (
  `consolidation_id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL,
  `assignment_id` int(11) NOT NULL,
  `quiz_id` int(11) NOT NULL,
  `assignment_pass_score_point` decimal(10,2) DEFAULT NULL,
  `assignment_pass_score_perc` decimal(10,2) DEFAULT NULL,
  `quiz_name` varchar(3800) NOT NULL,
  `question_id` int(11) NOT NULL,
  `question_text` varchar(3800) CHARACTER SET utf8 NOT NULL,
  `question_type_id` int(11) NOT NULL,
  `answer_id` int(11) DEFAULT NULL,
  `answer_textA` varchar(800) CHARACTER SET utf8 DEFAULT NULL,
  `answer_added_ts` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `group_id` int(11) DEFAULT NULL,
  `user_answer_text` varchar(3800) CHARACTER SET utf8 DEFAULT NULL,
  `answer_image` varchar(800) DEFAULT NULL,
  `is_correct` int(11) DEFAULT NULL,
  `correct_answer_text` varchar(3800) CHARACTER SET utf8 DEFAULT NULL,
  PRIMARY KEY (`consolidation_id`)
) ENGINE=InnoDB AUTO_INCREMENT=128 DEFAULT CHARSET=latin1 |
+---------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

拥有多个表的原因是每个分配 id 都有一个唯一的表,因此每个分配表可以单独/有选择地更新以进行分析。 它不一定只是更新一行,因为每个作业通常是 10 个问题。因此,在大多数情况下,每个新用户提交都会增加 10 行。

我附上了一个 ER 图,它显示了所有具有合并数据表源数据的表。

ER Diagram for consolidated_data tables

(蓝色 = 用于连接的字段;黄色 = 表中包含的所有其他字段;某些数据类型信息供参考)

【讨论】:

    猜你喜欢
    • 2020-01-20
    • 2010-12-07
    • 1970-01-01
    • 1970-01-01
    • 2011-07-14
    • 1970-01-01
    • 2014-11-04
    • 1970-01-01
    • 2021-07-28
    相关资源
    最近更新 更多