Sql server 如何插入动态行数
我有一个材料表作为源表,如下所示:Sql server 如何插入动态行数,sql-server,tsql,cursor,temp-tables,Sql Server,Tsql,Cursor,Temp Tables,我有一个材料表作为源表,如下所示: CREATE TABLE dbo.MATERIAL ( ID int IDENTITY(1,1) NOT NULL, CATEGORY_ID int NOT NULL, SECTION_ID int NOT NULL, STATUS_ID int NOT NULL ) CREATE TABLE dbo.ORDER ( ID int IDENTITY(1,1) NOT NULL, MATERIAL_ID int
CREATE TABLE dbo.MATERIAL (
ID int IDENTITY(1,1) NOT NULL,
CATEGORY_ID int NOT NULL,
SECTION_ID int NOT NULL,
STATUS_ID int NOT NULL
)
CREATE TABLE dbo.ORDER (
ID int IDENTITY(1,1) NOT NULL,
MATERIAL_ID int NOT NULL
)
CATEGORY_ID SECTION_ID STATUS_ID COUNT
----------- ---------- --------- -----
3 8 1 10
8 2 2 11
4 6 1 8
我还有一个订单表作为目标表,如下所示:
CREATE TABLE dbo.MATERIAL (
ID int IDENTITY(1,1) NOT NULL,
CATEGORY_ID int NOT NULL,
SECTION_ID int NOT NULL,
STATUS_ID int NOT NULL
)
CREATE TABLE dbo.ORDER (
ID int IDENTITY(1,1) NOT NULL,
MATERIAL_ID int NOT NULL
)
CATEGORY_ID SECTION_ID STATUS_ID COUNT
----------- ---------- --------- -----
3 8 1 10
8 2 2 11
4 6 1 8
我将ome数据发送到SQL server存储过程,并创建以下临时表
DECLARE @temptable TABLE (
CATEGORY_ID int NOT NULL,
SECTION_ID int NOT NULL,
STATUS_ID int NOT NULL,
COUNT int NOT NULL
)
并填写了如下数据:
CREATE TABLE dbo.MATERIAL (
ID int IDENTITY(1,1) NOT NULL,
CATEGORY_ID int NOT NULL,
SECTION_ID int NOT NULL,
STATUS_ID int NOT NULL
)
CREATE TABLE dbo.ORDER (
ID int IDENTITY(1,1) NOT NULL,
MATERIAL_ID int NOT NULL
)
CATEGORY_ID SECTION_ID STATUS_ID COUNT
----------- ---------- --------- -----
3 8 1 10
8 2 2 11
4 6 1 8
我想要的是匹配物料表中的物料计数,该物料表与同一行中给定的类别ID、区段ID和状态ID三元组匹配;然后将这些记录的ID插入目标表ORDER
我怎样才能完成这项任务
问候。现在我想我理解了需求,所以扔掉了一堆以前的工作 这里有一个工作: 这将生成一个名为GENROWS的数据集,其中包含的行数等于表中的max count。它是通过使用递归公共表表达式CTE来实现这一点的,以便在TESTERABLE中为max count的每个计数生成1行。 然后,它使用此数据集连接到诱惑和材质,以生成按顺序插入材质的时间 我不太喜欢使用保留字,所以我将order调整为morder,并且我建议调整列计数,否则您将不时被困在[]中包装字 注意:这假设物料表中不会有具有相同类别ID、区段ID和状态ID的重复记录。如果有,;那么这可能会也可能不会像预期的那样 最后一点,现在我已经更好地了解了您所追求的目标,我不确定您会看到与使用游标相比,性能有很大的提高。因为行必须以某种方式生成。这可能会更快一些,因为我们一次生成集合并插入,而不是单独生成。但是,生成、存储和检索生成的数据集会带来开销,这可能会抵消这一收益。只有测试才能说明问题
WITH
GenRows (RowNumber, Val) AS (
-- Anchor member definition
SELECT 1 AS RowNumber, (Select max(count) val from temptable) val
UNION ALL
-- Recursive member definition
SELECT a.RowNumber + 1 AS RowNumber, a.val
FROM GenRows a
WHERE a.RowNumber < a.val
)
Insert into morder (Material_ID)
SELECT A.ID
FROM material A
INNER JOIN temptable B
on A.Category_ID = B.Category_ID
and A.Section_Id = B.Section_Id
and A.Status_Id = B.Status_ID
INNER JOIN GenRows
on GenRows.RowNumber <= b.[count]
我想我已经找到了解决办法。我应该用游标。下面的代码实现了这一点:
DECLARE @MATERIAL_ID int
DECLARE @CATEGORY_ID int
DECLARE @SECTION_ID int
DECLARE @STATUS_ID int
DECLARE @COUNT int
DECLARE cur CURSOR LOCAL FOR
SELECT
CATEGORY_ID,
SECTION_ID,
STATUS_ID,
COUNT
FROM
@temptable
OPEN cur
FETCH NEXT FROM cur INTO @CATEGORY_ID, @SECTION_ID, @STATUS_ID, @COUNT
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO
dbo.ORDER
(MATERIAL_ID)
SELECT
TOP (@COUNT) ID
FROM
dbo.MATERIAL AS m
WHERE
m.CATEGORY_ID = @CATEGORY_ID
AND m.SECTION_ID = @SECTION_ID
AND m.STATUS_ID = @STATUS_ID
FETCH NEXT FROM cur INTO @CATEGORY_ID, @SECTION_ID, @STATUS_ID, @COUNT
END
CLOSE cur
DEALLOCATE cur
这听起来像是一个解释不当的消耗库存问题。物料是一张库存表。然后,在@tentable中组装一个BoM表,描述完成订单所需的项目和数量。问题是如何使用BoM从物料中提取库存的一些奇怪的变化,尽管没有跟踪任何以前消耗的库存,并将结果插入到订单中。由于项目数量大,减少往返次数和性能对项目至关重要。为了防止多次访问数据库,我们将带有子对象的对象序列化为XML,然后在数据库服务器上处理所有数据。使用此技术,我们可以一次插入数千种材料,并观察与多个项目类似的性能。@user3021830更新了答案,为您提供了一种不使用光标的方法,我相信光标会影响性能。最后一个响应对于您来说可能是最干净的。您正在失去使用游标所获得的一些性能。在RDBMS中,当您可以使用集合逻辑进行处理时,您将获得更好的性能。非常感谢您的更新。但它似乎仍然没有达到我的要求。我刚刚对查询做了一些微小的更改,并在@tentable中更新了所需数量的材料,不幸的是,ode现在没有运行正确的结果。请看我没有理解这个要求。我的印象是,您只想将记录插入到与材料中数据记录的数量精确匹配的顺序中,因此在fiddle示例中。。。诱惑有3,8,1,3。其中3是最后一个3是计数。如果查看物料表,有3,8,1的记录,但这些记录的计数大于3,因此没有匹配的数据。在Tentiable中的所有其他记录也是如此。现在,如果你在插入任何随机的一组记录后,从TESTERABLE中选择与3,8,1匹配的10个记录中的任意3个,我很抱歉没有提供正确的详细信息。让我们用集合论来举例说明这个项目。材料表是通用设置。所有项目都驻留在该表中,不属于该表的任何项目都不能添加到订单表中。用户发送dta,我将其填入@tentable,该dta描述了要拾取的材料的规格,以及计数为要拾取的材料数量。我需要的是找到与spesc匹配的材料,选择它们的计数编号,然后将这些材料的ID保存到订单表中。@user3021830现在我想我明白了你的想法,我想生成测试数据,当这看起来更像实际操作数据时,我已经更新了小提琴和结果;并清理了早些时候的垃圾。