SQL - 循环遍历列,一旦找到空,更新它

问题描述:

我启动了类似的线程,但由于问题更困难,我想从头开始。
想象一下,有10个库存插槽(在DB中它们是用户行中的列)。当用户选择一个项目时,它应该被放置到第一个空列(它被更新)。但是如果我想要仍然灵活的设计,如何在查询中循环查找(除了IF EXISTS)? 由于项目的顺序很重要(每个项目属于特定的槽),所以不能很好地解决问题。如果用户有第一个和第三个插槽已满,下一个挑选的项目应该进入第二个。 现在希望它更清楚,谢谢!SQL - 循环遍历列,一旦找到空,更新它

+1

如果顺序很重要,请将“插槽”列添加到行中以表示其顺序。 – 2010-07-26 14:11:34

+0

听听@dcp和@Chris在下面说什么。您的模式已经融合,您应该在继续之前解决这个问题。 – 2010-07-26 14:17:21

为什么不只是有另一个表的库存项目?所以你有一个库存表和inventory_item表,就像这样:

---------- 
inventory 
---------- 
id int 
description varchar(100) 

--------------- 
inventory_item 
--------------- 
id int 
inventory_id int (foreign key to inventory table) 
sequence_num int (indicates which "slot" the data represents) 

所以,现在,你可以在库存有行,然后你可以插入行到inventory_item当你的价值观。因此,如果您有3个值,则只需将3行插入inventory_item。至于什么“插槽”他们进去,sequence_num字段会告诉你。

编辑
要查询现有inventory_items找出下一个可用的插槽数,你可以这样做:

SELECT coalesce(MAX(sequence_num),0) + 1 next_sequence_num 
    FROM inventory_item 
WHERE inventory_id = xxx 

如果没有inventory_items存在,这将返回1.如果现有的项目都存在,它会给你下一个“插槽编号”使用(我称之为sequence_number,但同样的事情)。

+0

当新物品被拿起时,它如何知道它属于哪个“插槽”? (这是第一个空) – Thomas 2010-07-26 14:18:31

+0

@Tomas - 查看我的最新编辑的答案。 – dcp 2010-07-26 14:28:13

+0

谢谢。库存是否需要?我的意思是,如何为每个项目分配简单的“用户”和用户ID(说它是所有者) – Thomas 2010-07-26 14:35:13

你用这种方式破坏1NF,这就是你遇到这个问题的原因。

我认为它可以通过在行中的项目来解决。您可以将每一行放入另一个表中,并使用该表中的另一列指定顺序。

我不确定Inventoryslot在你的例子中涉及什么,但是表格应该看起来与此类似。

InventorySlots(InventorySlotId, RelatedFieldID, OrderNumber, ItemID) 

你可以把RelatedFieldID和订单号码具有唯一索引,以防止在同一位置上有两个项目。

我会说你可能仍然使用行。只需添加一列“SlotOrder”或其他。然后,你的查询会是这样(警告:伪码 - 没有测试所有):

declare @Slot int 
set @Slot = 1 
if @Slot <= (Select Max(SlotOrder) from Inventory) 
    select @Slot = (Select Max(SlotOrder) + 1 from Inventory) 
if @Slot >= 10 
    Insert Into Inventory(Item, SlotOrder) 
    Values(@Item, @Slot) 
Else -- Tell the user the inventory is full 

在一个表中的项目有没有特定的顺序,那么孤单顺序不能用来区分不同的插槽。

但是,这可能并不重要,因为您想查找第一个空插槽。没有任何对插槽的排序,这相当于找到任何空插槽。如果添加slotNr领域的插槽表(从1开始编号用户的插槽

update slots s 
set slotValue=newValue 
WHERE s.userID = <UserID> AND slotValue IS NULL AND NOT EXISTS 
(SELECT 1 FROM slots s2 WHERE s2.userid=s.userid AND s2.slotValue IS NULL AND s2.slotID<s.slotID) 

..:

这是这样做10),那么查询将如下所示:

update slots s 
set slotValue=newValue 
WHERE s.userID = <UserID> AND slotValue IS NULL AND NOT EXISTS 
(SELECT 1 FROM slots s2 WHERE s2.userid=s.userid AND s2.slotValue IS NULL AND s2.slotNr<s.slotNr) 

当您执行查询时,数据库将返回受影响的行数。如果所有插槽都在使用中,则返回值将为0,否则为1,如果插槽已更新。

你可以找到多少空闲插槽有写

select count(*) FROM slots 
WHERE slots.userID=<userID> AND slots.slotValue IS NULL 

虽然即使这个返回空闲插槽,也不能保证,当你真正到了改变的空插槽值,即有任何空闲插槽 - 为该用户添加插槽值的其他操作可能会占用最后一个可用插槽。因此,最好使用ROW_COUNT变量来确定插槽是否被修改。