sql插入

kmpatx3s  于 2021-07-26  发布在  Java
关注(0)|答案(1)|浏览(375)

这个问题已经有人问过了,但我找不到答案。我搜索了一段时间,发现了这些相关的问题,但它们并没有帮助我理解或回答我的问题。
带内部联接的sql插入
带左连接的t-sql插入
我的问题是如何使用连接在两个表中插入数据。例如(使用php),用户可以输入他/她的名字和他/她喜欢的食物。
我将它们存储在一个变量和一个数组中(数组的长度并不总是3,如下所示):

  1. $name = "Niels"
  2. $foodsHeLikes = array("apple", "pear", "banana");

这就是我想要存储它们的方式:

  1. USERS:
  2. UserID name
  3. 1 Niels
  4. FOODS:
  5. FoodID userID name //userID is linked to UserID in users table
  6. 1 1 apple
  7. 2 1 pear
  8. 3 1 banana

我在上面粘贴的第一个问题的链接有一个带有连接的insert,但是我没有看到任何地方可以像普通insert一样放入值?
这个问题的疑问是:

  1. INSERT INTO orders (userid, timestamp)
  2. SELECT o.userid, o.timestamp FROM users u INNER JOIN orders o ON o.userid = u.id
nwwlzxa7

nwwlzxa71#

从评论部分的情况来看,您的问题是希望有一个更优化的查询过程。现在您正在使用两个不同的查询来填充两个表,您想知道是否可以以更优化的方式来完成。
首先,不可能用一个查询填充两个不同的表。
但是,您可以做的是使用事务。
这个答案的其余部分将遵循这样的假设:您使用php作为后端脚本语言(正如您标记自己一样)。
另外,您是否在查询中使用准备好的语句本身并不明显。如果你不这样做,我强烈建议你使用事先准备好的陈述。否则,您将面临sql注入(sqli攻击)。
我将继续使用mysqli在这个答案中准备的语句。

  1. <?php
  2. // Your input post variables
  3. $name = $_POST['name'];
  4. $foodArray = $_POST['foodArray'];
  5. /*
  6. I'm using a function to handle my queries,
  7. simply because it makes large piles of code easier to read.
  8. I now know that every time the function:
  9. createUserAndFood($name, $foodArray);
  10. is called, that it will populate my user and food table.
  11. That way I don't have to worry about writing all the code multiple times.
  12. * /
  13. function createUserAndFood($name, $foodArray){
  14. // food array values
  15. $foodValues = array_values($foodArray);
  16. // DB variables
  17. $servername = "localhost";
  18. $username = "username";
  19. $password = "password";
  20. $dbname = "myDB";
  21. // Create connection
  22. $conn = new mysqli($servername, $username, $password, $dbname);
  23. // Check connection
  24. if($conn->connect_error){
  25. die("Connection failed: " . $conn->connect_error);
  26. }
  27. /*
  28. Stops the query from auto commiting,
  29. I'll explain later, you can "maybe" disregard this.
  30. */
  31. $conn->autocommit(FALSE);
  32. // Declare the query
  33. $sql = "INSERT INTO userTable(name) VALUES(?)";
  34. // Prepare and bind
  35. $stmt = $conn->prepare($sql);
  36. $stmt->bind_param("s", $name);
  37. // Execute the query
  38. $stmt->execute();
  39. // Fetch last inserted id
  40. $lastID = $conn->insert_id;
  41. $sql = "INSERT INTO foodTable(userId, food) VALUES(?, ?)";
  42. $stmt = $conn->prepare($sql);
  43. for($i = 0; $length = count($foodValues) > $i; $i++){
  44. $stmt->bind_param("is", $lastID, $food);
  45. $food = $foodValues[$i];
  46. $stmt->execute();
  47. }
  48. // Commits the query / queries
  49. $conn->commit();
  50. // Close connection
  51. $stmt->close();
  52. $conn->close();
  53. }
  54. ?>

因为您想优化查询,所以我们在这里使用的一般思想是使用mysql函数 LAST_INSERT_ID(); 并将其存储到变量中。
现在,如果您使用的是自动递增的id,那么这主要是相关的。如果你不是,你可以忽略这个特定的逻辑,使用其他的东西。但如果你是,那就继续读下去。
我们之所以将最后一个id存储到变量中,是因为我们需要多次使用它(新用户可能有多个最喜欢的食物)。如果不将最后一个id存储到变量中,它将采用初始insert后第二个表的自动递增值,这意味着在执行第三个insert语句并转发时,您将使用错误的id。
现在,正如我承诺要解释的,我使用 $conn->autocommit(FALSE); 以及 $conn->commit(); 是因为您可能不希望数据库中存在不完整的数据集。假设一个用户输入正在发生,但数据库却在其中崩溃。您将拥有不完整的数据集。如果这不是你真正关心的问题,那么你可以忽略它。
为了简化mysql方面的工作,可以这样想:

  1. BEGIN;
  2. INSERT userTable SET name = '$name';
  3. SET @lastID = LAST_INSERT_ID();
  4. INSERT foodTable SET id = @lastID, food = '$food';
  5. COMMIT;
展开查看全部

相关问题