如果满足其中一个case语句,如何结束SQL case语句?

时间:2017-03-05 21:42:21

标签: mysql sql oracle case-statement

我目前正在构建一个应用程序,其中包含一个数据库,用于保存包含四十个插槽的用户库存。在此数据库中,一行等于一个用户。我希望这个查询要做的是搜索每个插槽,当它找到一个零的插槽时,查询应该将其更新为不同的预定数字然后停止。但是,我遇到了我发现的解决方案的问题,而不是在更新特定节点后停止查询,它会继续更新其中包含零的每个节点。如何在更新一个节点后结束此查询?

CODE:

SET SQL_SAFE_UPDATES = 0;
SELECT *
FROM userinfo;

UPDATE userinfo SET
InvSlot1 = CASE WHEN InvSlot1 = 0 THEN 4 ELSE InvSlot1 END,
InvSlot2 = CASE WHEN InvSlot2 = 0 THEN 4 ELSE InvSlot2 END,
InvSlot3 = CASE WHEN InvSlot3 = 0 THEN 4 ELSE InvSlot3 END,
InvSlot4 = CASE WHEN InvSlot4 = 0 THEN 4 ELSE InvSlot4 END,
InvSlot5 = CASE WHEN InvSlot5 = 0 THEN 4 ELSE InvSlot5 END,
InvSlot6 = CASE WHEN InvSlot6 = 0 THEN 4 ELSE InvSlot6 END,
InvSlot7 = CASE WHEN InvSlot7 = 0 THEN 4 ELSE InvSLot7 END,
InvSlot8 = CASE WHEN InvSlot8 = 0 THEN 4 ELSE InvSlot8 END,
InvSlot9 = CASE WHEN InvSlot9 = 0 THEN 4 ELSE InvSlot9 END,
InvSlot10 = CASE WHEN InvSlot10 = 0 THEN 4 ELSE InvSlot10 END,
InvSlot11 = CASE WHEN InvSlot11 = 0 THEN 4 ELSE InvSlot11 END,
InvSlot12 = CASE WHEN InvSlot12 = 0 THEN 4 ELSE InvSlot12 END,
InvSlot13 = CASE WHEN InvSlot13 = 0 THEN 4 ELSE InvSlot13 END,
InvSlot14 = CASE WHEN InvSlot14 = 0 THEN 4 ELSE InvSlot14 END,
InvSlot15 = CASE WHEN InvSlot15 = 0 THEN 4 ELSE InvSlot15 END,
InvSlot16 = CASE WHEN InvSlot16 = 0 THEN 4 ELSE InvSlot16 END,
InvSlot17 = CASE WHEN InvSlot17 = 0 THEN 4 ELSE InvSlot17 END,
InvSlot18 = CASE WHEN InvSlot18 = 0 THEN 4 ELSE InvSlot18 END,
InvSlot19 = CASE WHEN InvSlot19 = 0 THEN 4 ELSE InvSlot19 END,
InvSlot20 = CASE WHEN InvSlot20 = 0 THEN 4 ELSE InvSlot20 END,
InvSlot21 = CASE WHEN InvSlot21 = 0 THEN 4 ELSE InvSlot21 END,
InvSlot22 = CASE WHEN InvSlot22 = 0 THEN 4 ELSE InvSlot22 END,
InvSlot23 = CASE WHEN InvSlot23 = 0 THEN 4 ELSE InvSlot23 END,
InvSlot24 = CASE WHEN InvSlot24 = 0 THEN 4 ELSE InvSlot24 END,
InvSlot25 = CASE WHEN InvSlot25 = 0 THEN 4 ELSE InvSlot25 END,
InvSlot26 = CASE WHEN InvSlot26 = 0 THEN 4 ELSE InvSlot26 END,
InvSlot27 = CASE WHEN InvSlot27 = 0 THEN 4 ELSE InvSlot27 END,
InvSlot28 = CASE WHEN InvSlot28 = 0 THEN 4 ELSE InvSlot28 END,
InvSlot29 = CASE WHEN InvSlot29 = 0 THEN 4 ELSE InvSlot29 END,
InvSlot30 = CASE WHEN InvSlot30 = 0 THEN 4 ELSE InvSlot30 END,
InvSlot31 = CASE WHEN InvSlot31 = 0 THEN 4 ELSE InvSlot31 END,
InvSlot32 = CASE WHEN InvSlot32 = 0 THEN 4 ELSE InvSlot32 END,
InvSlot33 = CASE WHEN InvSlot33 = 0 THEN 4 ELSE InvSlot33 END,
InvSlot34 = CASE WHEN InvSlot34 = 0 THEN 4 ELSE InvSlot34 END,
InvSlot35 = CASE WHEN InvSlot35 = 0 THEN 4 ELSE InvSlot35 END,
InvSlot36 = CASE WHEN InvSlot36 = 0 THEN 4 ELSE InvSlot36 END,
InvSlot37 = CASE WHEN InvSlot37 = 0 THEN 4 ELSE InvSlot37 END,
InvSlot38 = CASE WHEN InvSlot38 = 0 THEN 4 ELSE InvSlot38 END,
InvSlot39 = CASE WHEN InvSlot39 = 0 THEN 4 ELSE InvSlot39 END,
InvSlot40 = CASE WHEN InvSlot40 = 0 THEN 4 ELSE InvSlot40 END
WHERE Username = 'test' 

1 个答案:

答案 0 :(得分:1)

这是一个丑陋的黑客解决方案,可以做你想做的事。

首先,使用您要放入表中的值定义User-defined session variable

SET @x := 4;

然后像以前一样做你的大屁股UPDATE语句,但是将插槽设置​​为@x变量,并附加一些额外的东西:作为表达式的一部分,你还要将新赋值的结果添加到变量中零。添加零不会影响结果,但它具有副作用,即@x的值更改为零,并且这将在后续插槽分配中使用,直到查询结束。

只有之前为零的第一个插槽才会触发更改@x的表达式,但是任何后续的零插槽都会再次设置为零,这无效。

UPDATE userinfo SET
InvSlot1 = CASE WHEN InvSlot1 = 0 THEN @x+(@x:=0) ELSE InvSlot1 END,
InvSlot2 = CASE WHEN InvSlot2 = 0 THEN @x+(@x:=0) ELSE InvSlot2 END,
InvSlot3 = CASE WHEN InvSlot3 = 0 THEN @x+(@x:=0) ELSE InvSlot3 END,
InvSlot4 = CASE WHEN InvSlot4 = 0 THEN @x+(@x:=0) ELSE InvSlot4 END,
...

这可能与您当前的数据库设计有关。

但是,我同意其他评论者关于此问题和your previous question - 您不应该以这种方式组织数据库。

而是创建另一个每个用户最多包含40行的表。如果在表中包含userid列,则每个用户不需要一个表,因此您可以为每个用户重复40行,并指定哪些插槽属于哪个用户。

要将插槽限制为不超过40,请创建一个查找表以枚举40行并使用外键约束。 (您可以在以后通过向此表中再添加三行来扩展到43个插槽。)

CREATE TABLE slots ( slot TINYINT PRIMARY KEY );
INSERT INTO slots (slot) VALUES (1), (2), (3), (4), ... 

CREATE TABLE userinfoInvslots (
  userid INT NOT NULL,
  slot TINYINT NOT NULL,
  slotvalue INT NOT NULL,
  PRIMARY KEY (userid, slot),
  FOREIGN KEY (slot) REFERENCES slots(slot)
);

现在不是使用零来表示插槽未被占用,而是不插入该插槽号的行。没有行意味着插槽未使用。清除插槽可以通过删除此表中的一行来完成。

查询最低的未使用插槽很简单:

SELECT MIN(s.slot) AS minSlot
FROM slots AS s
LEFT OUTER JOIN userinfoInvslots AS u
  ON s.slot = u.slot and u.userid = 1234
WHERE u.slot IS NULL;

来自@ CRSoftware33的评论

  

因此,如果我在第一个表中将用户用户名作为主键,我是否会将第二个表中的用户名作为该表的主键?(我对SQL很新)我是否只有我的第二个表中有两列,一个用于用户名,另一个用于存储在库存槽中的int值?

我假设您在userinfo表中有一个整数主键,但我显示了一个列userid,但是如果你有用户名作为主键,那么就是使用它。

  

我真的不知道如何使这项工作,因为在我的正好有四十个插槽,而在我的GUI中有四十个ImageView,它们对应于我的库存中的每个插槽。我怎样才能用两个表复制这个?

如果要显示给定用户的插槽,请查询userinfoInvslots表WHERE userid=?并获取与所需用户对应的40行。然后在代码中循环遍历此结果集。在您获取行时,显示它们。

  

有没有办法在我的第二个表中生成一个用户库存的查询,其中包含用户名列,插槽列和项目ID列?换句话说,它将是一个查询,它会添加40行,并为每列添加用户名,并将其插槽列从1到40编号,并将每行的每个项ID设置为零?

是的,您可以在SQL中执行此操作,但老实说,在应用程序代码的循环中执行此操作会更简单。使用循环变量从1到40计数,并在循环的每次迭代中插入一行。我并不是故意侮辱,但这是你在任何课堂或任何书中学到的基本内容。