mysql检查下一个自由值的过程

4xrmg8kj  于 2021-06-17  发布在  Mysql
关注(0)|答案(2)|浏览(201)

我应该如何写程序,将检查下一个自由数字(这是字符串)的基础上输入。过程应该有两个输入值,第一个是用户输入(数字),第二个是字符串中的最大字符数。
这是我试图写的程序:

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 .
所以 Call getfreenum(1,5) 如果从10000到100042(包括100042),程序应返回10043 Call getfreenum(11,5) 应该检查剩下的3个字符并返回11000。如果从11000到11599的所有数据都是11600。每次输入都应该是这样,即使我输入4个字符: Call getfreenum(1234,5) 过程应该检查12340、12341、12342,如果12349是免费的,它应该返回那个值,但是它不应该返回改变输入号码的值,也就是说,如果我调用 Call getfreenum(1234,5) 所有内容都被获取,包括“123459”,然后函数应该为所有错误返回null或某个固定值。

ajsxfq5m

ajsxfq5m1#

函数用于将项目编号指定给商店中的项目。有些项目的最大位数有时是3,有时是5。有些商品有起始编号:比如说香烟是“1254”。而“12”是奢侈品的起始数字。出纳在分配项目编号时更容易使用此逻辑。对我来说更复杂:)@schwern–3分钟前
这可以通过更好的模式设计得到更好的处理。
认识到“1254”实际上是两部分。有类别id 12和项目id 54。与其存储“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。

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    |
+---------+
3zwjbxry

3zwjbxry2#

你可以得到所有的一套 sifra 哪里 sifra + 1 与不存在 NOT EXISTS 以及相关子查询。 num * power(10, maxval - floor(log10(num)) - 1) 给出最小值,例如21、5和3的21000 num * power(10, maxval - floor(log10(num)) - 1) + power(10, maxval - floor(log10(num)) - 1) 比最大值多出一个,例如22000代表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 .

相关问题