【问题标题】:sql multiple insert on one table, while looping/iterating over another table?sql 在一个表上多次插入,同时在另一个表上循环/迭代?
【发布时间】:2011-03-09 18:01:12
【问题描述】:

我有两个表“TempStore”和“Store”,它们的列名为“Items”。

“TempStore”表中有数据,我需要将其移至“Store”表,需要少量修改。

我需要遍历“TempStore”数据(即项目)并插入到 Store...

更具体地说:我如何迭代 TempStore(在 sql 中),其中“对于 'TempStore' 中的每个项目,我需要在 'Store' 中存储 2 或 3 个项目而几乎没有修改”,我该如何实现呢?

我想做的是从“[SELECT * FROM TempStore]”中获取每个行数据,并在“Store”中插入三个记录,并能够更改“items”

【问题讨论】:

  • 您应该更具体地了解一排如何变成三排。理想情况下,包括样本数据和预期结果。
  • 假设 TempStore 表有 {Items, Cost, Price, ActualCost, ActualPrice} 但在 Store 表中我需要存储 {Items, Cost, Price}。 TempStore 数据行中的 ActualCost 和 ActualPrice 需要添加为 Store 中的另一行......(我希望这是有道理的)......无论如何,解决方案是使用“WHILE-BEGIN-END”吗??

标签: sql database sybase


【解决方案1】:

尝试插入选择:

INSERT INTO Store
        (col1, col2, col3...)
    SELECT
        col1, col2, col3...
        FROM TempStore
        WHERE ...

只需让 SELECT 为每个插入返回一行,并在 Cols 中生成您需要的值。您可能需要 CASE 并连接到另一个表来创建额外的行。

编辑基于 cmets,OP 想查看实际的数字表

假设 TempStore 表有 {Items, 成本、价格、实际成本、实际价格} 但是在 Store 表中我需要存储 {项目,成本,价格}。实际成本 和来自 TempStore 数据行的 ActualPrice 需要添加为另一行 在商店中......(我希望这使得 感觉)....无论如何,是解决方案 使用“WHILE-BEGIN-END”??

CREATE TABLE Numbers (Number int NOT NULL PRIMARY KEY)
INSERT INTO Numbers VALUES(1)
INSERT INTO Numbers VALUES(2)
INSERT INTO Numbers VALUES(3)


INSERT INTO Store
        (Items, Cost, Price)
    SELECT
        t.Items, t.Cost
            ,CASE
                 WHEN n.Number=1 THEN t.Price
                 WHEN n.Number=2 THEN t.ActualCost
                 ELSE t.ActualPrice
             END
        FROM TempStore         t
            INNER JOIN Numbers N ON n.Number<=3
        WHERE ...

你甚至可以使用 UNION:

INSERT INTO Store
        (Items, Cost, Price)
    SELECT
        t.Items, t.Cost, t.Price
        FROM TempStore t
    UNION ALL
    SELECT
        t.Items, t.Cost, t.ActualCost
        FROM TempStore t
    UNION ALL
    SELECT
        t.Items, t.Cost, t.ActualPrice
        FROM TempStore t

无论是 Numbers 表还是 UNION,我们都会WAY比循环更好!

【讨论】:

  • @KM 你确定是 MS-SQL 吗?不知道sybase是什么,用的是什么sql?
  • @KM:谢谢 - 这很好,但是如何在 TempStore 中为每个 rowdata 在 Store 中插入 3 条记录?
  • SQL语句只运行三遍怎么样?或者重复一遍,将 INSERT-SELECT 包装在 WHILE-BEGIN-END 中。
  • @VoodooChild,创建一个数字表:stackoverflow.com/questions/1393951/…,您可以将 TempStore 加入其中。创建 Numbers 表后,将其添加到选择中:INNER JOIN Numbers N ON n.Number&lt;=3
  • @DOK,如果不需要,永远不要循环,基于集合是进入数据库的最快和最好的方法
【解决方案2】:

好的,我认为 KM 提出了一个涉及“数字表”的出色解决方案。但是,VoodooChild 在评论中要求我发布示例代码,以建议在 INSERT-SELECT 周围使用 WHILE-BEGIN-END。

我创建了两个表,例如 VoodooChild's Store 和 TempStore。

Store 包含 StoreID、StoreName、StoreState、StoreNumber 列。

TempStore 包含列 TempStoreID、TempStoreName。

我用值 First、Second、Third 和 Fourth 预填充了 TempStoreName。

现在,我的 SQL 将为 TempStore 表中满足 WHERE 子句条件的每条记录插入三条记录到 Store 表中。该条件是 TempStoreName 的长度,显然不是真实世界的示例。

DECLARE @counter int 
SET @counter = 0;
WHILE @counter < 3
BEGIN
INSERT INTO Store (StoreName, StoreState, StoreNumber)
    SELECT TempStoreName, 'AZ', @counter FROM TempStore WHERE LEN(TempStoreName) = 5
SET @counter = @counter + 1
END

当应用到一个空的 Store 表时,结果是:

StoreID StoreName   StoreState  StoreNumber
1           First       AZ          0
2           First       AZ          1
3           First       AZ          2
4           Third       AZ          0
5           Third       AZ          1
6           Third       AZ          2

所以,这种方法有效。它似乎满足了 VoodooChild 的需求。它可能是最好的选择,也可能不是最好的选择,但我们不知道决定中涉及的其他因素,例如该操作将重复多少次。

【讨论】:

  • +1,感谢您完成我的请求。嗯,如果您感到无聊:p 您可以根据“数字表”发布另一个答案,如果没有,那么我仍然认为您很棒。
  • 哎呀,我看到 KM 已经使用数字表更新了他的答案...我要看看它,看看哪个更有意义。非常感谢您的帮助,你们太棒了
  • @VoodooChild SO 在这里非常适合您。您可以选择两种非常好的方法。如果对您有用,我认为 KM 的解决方案会更优雅。
  • 是的,我刚刚在我的实际解决方案中尝试了 Number Table 方法,它比循环更有效,而且操作起来非常简单 - 我很高兴遇到它,它非常完美。再次非常感谢,非常感谢您的帮助。干杯:)
【解决方案3】:
INSERT INTO Store ( SELECT * FROM TempStore UNION ALL SELECT * FROM TempStore )

上面的语句将为 TempStore 中的每一行在 store 中插入两行。您可以将 SELECT * 更改为您想要对项目进行的任何修改。

【讨论】:

  • 我想要做的是从“[SELECT * FROM TempStore]”中获取每个行数据,并在“Store”中插入三条记录,并能够更改“items”。
【解决方案4】:

鉴于您的最新评论,这应该可以满足您的需求。一旦它们到达那里,您可能应该有某种方法来区分 Stores 表中的值。也许是一个“实际的”BIT 列或类似的东西:

INSERT INTO Stores (item, cost, price, actual)
SELECT item, cost, price, 0
FROM TempStores
UNION ALL
SELECT item, actual_cost, actual_price, 1
FROM TempStores

如果您需要调整列(例如,将 actual_price 增加 10%),那么您可以这样做:

INSERT INTO Stores (item, cost, price, actual)
SELECT item, cost, price, 0
FROM TempStores
UNION ALL
SELECT item, actual_cost, 1.1 * actual_price, 1
FROM TempStores
WHERE actual_cost IS NOT NULL

我还在第二个 SELECT 语句中添加了 WHERE 子句,以表明您可以过滤行。该 WHERE 子句只会影响第二个 SELECT。所以,你也可以这样做:

INSERT INTO Stores (item, cost, price, actual)
SELECT item, cost, price, 0
FROM TempStores
WHERE cost IS NOT NULL
UNION ALL
SELECT item, actual_cost, 1.1 * actual_price, 1
FROM TempStores
WHERE actual_cost IS NOT NULL

【讨论】:

  • +1 嗯,这很有趣。我想我可以继续执行“UNION ALL”的次数,只要表相同,选择就会起作用。这种方法的唯一问题是,例如上面我将获得两个插入 - 但我无法编辑要插入的数据......或者我不知道如何插入?请指教,谢谢!
  • 只要列数据类型匹配,选择就会起作用。他们可能来自不同的桌子。我不确定您所说的“编辑”到底是什么意思。您当然可以在上面的列中使用函数。我将添加一个简短的示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-04-07
  • 2015-08-27
  • 1970-01-01
  • 1970-01-01
  • 2018-12-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多