我应该如何编写基于输入检查下一个空闲数字(字符串)的过程。 该过程应具有2个输入值,第一个是用户输入(数字),第二个是字符串中最大字符数。
这是我尝试编写的过程:
CREATE DEFINER=`root`@`localhost` PROCEDURE `getfreenum`(IN num CHAR(20), IN maxval CHAR(20))
begin
set @compare := (num + num *10);
set @maxId := (select sifra from artikli where sifra >= @compare order by sifra asc limit 1);
while @compare = @maxId do
set @compare := @compare + 1;
set @maxId = (select sifra from artikli where sifra >= @compare order by sifra asc limit 1);
end while;
select @compare;
end
此过程将在输入后找到下一个可用值,但该数字不包括我的输入,这意味着如果我调用过程Call getfreenum(1,5)
会得到值779
,但我应该得到下一个5个字符的值其中包括输入数字1
。
因此,如果从10000到100042之间(包括100042)取所有内容,则Call getfreenum(1,5)
过程应返回10043,并且Call getfreenum(11,5)
应该检查其余3个字符并返回11000。如果从11000取所有内容,则返回11600。到11599。即使我输入了4个字符,它也应该像每次输入一样工作:Call getfreenum(1234,5)
过程应检查12340、12341、12342,如果12349是空闲的,则应返回该值,但不返回值这会更改输入数字,也就是说,如果我调用Call getfreenum(1234,5)
,并且一切都包括“ 123459”在内,那么函数应该为所有错误返回NULL或某个固定值。
答案 0 :(得分:2)
功能用于将商品编号分配给商店中的商品。有时,对于某些物品,最大位数为3,有时为5。某些物品的起始数字为:假设香烟为“ 1254”。和“ 12”是奢侈品的起始编号。收银员在分配物料编号时更容易使用此逻辑。对我来说,这更复杂:) @Schwern – 3分钟前堆叠
这可以通过更好的模式设计更好地解决。
认识到“ 1254”实际上是两个部分。有类别ID 12和项目ID54。您无需将“ 1254”存储在这两个文件中。
create table item_categories(
id integer primary key auto_increment,
shop_id_padding integer not null default 5,
name text not null
);
create table items (
id integer primary key auto_increment,
name text not null,
category_id integer not null,
foreign key(category_id) references item_categories(id)
);
显式的item_categories
表为我们提供了参照完整性,一个存储类别名称的位置以及要使用的填充量。
现在,您可以让auto_increment
来完成它的工作。
insert into item_categories (id, name, shop_id_padding) values (12, "cigarettes", 2);
insert into items (name, category_id) values ("Coffin Nails", 12);
insert into items (name, category_id) values ("Death Sticks", 12);
select * from items;
+----+--------------+-------------+
| id | name | category_id |
+----+--------------+-------------+
| 1 | Coffin Nails | 12 |
| 2 | Death Sticks | 12 |
+----+--------------+-------------+
使用concat
构造商店ID。根据类别填充ID。
select concat(i.category_id, lpad(i.id, cat.shop_id_padding, '0')) as shop_id
from items i
join item_categories cat on i.category_id = cat.id;
+---------+
| shop_id |
+---------+
| 1201 |
| 1202 |
+---------+
答案 1 :(得分:1)
您可以使用sifra
和相关子查询来获得sifra + 1
不存在的所有NOT EXISTS
的集合。
num * power(10, maxval - floor(log10(num)) - 1)
为您提供了最小数量,例如21000(代表21、5和num * power(10, maxval - floor(log10(num)) - 1) + power(10, maxval - floor(log10(num)) - 1)
)比最大数量多一个,例如22000 for 21,5。相应地将sifra + 1
与之比较。
最后,您必须确保请求的位数不超过给定前缀的位数。即floor(log10(num)) < maxval
必须得到满足。
要确保至少存在最小数量的前任num * power(10, maxval - floor(log10(num)) - 1) - 1
,请使用UNION ALL
将其添加到基本集中。
就像您可以只用SELECT
来计算数字一样,没有任何循环(可能相对较慢)。
CREATE PROCEDURE getfreenum
(IN num integer,
IN maxval integer)
BEGIN
SELECT CASE
WHEN NOT EXISTS (SELECT *
FROM artikli t2
WHERE t2.sifra = num * power(10, maxval - floor(log10(num)) - 1)) THEN
num * power(10, maxval - floor(log10(num)) - 1)
ELSE
min(t1.sifra) + 1
END sifra
FROM artikli t1
WHERE floor(log10(num)) < maxval
AND EXISTS (SELECT *
FROM artikli t2
WHERE sifra = num * power(10, maxval - floor(log10(num)) - 1))
AND NOT EXISTS (SELECT *
FROM artikli t2
WHERE t2.sifra = t1.sifra + 1)
AND t1.sifra >= num * power(10, maxval - floor(log10(num)) - 1) - 1
AND t1.sifra < num * power(10, maxval - floor(log10(num)) - 1) + power(10, maxval - floor(log10(num)) - 1) - 1;
END;
如果要处理数字,则应使用适当的类型,而不要使用char
。