Процедура MySQL для проверки следующего свободного значения - PullRequest
0 голосов
/ 30 декабря 2018

Как мне написать процедуру, которая будет проверять следующий свободный номер (который является строкой) на основе ввода.Процедура должна иметь 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.

Таким образом, процедура Call getfreenum(1,5) должна вернуть 10043, если все взято из 10000 до 100042 включительно, а Call getfreenum(11,5) должна проверить оставшиеся 3 символа и вернуть, скажем, 11000. Или 11600, если все взято из 11000 в11599. И он должен работать так же для каждого ввода, даже если я введу 4 символа: Call getfreenum(1234,5) процедура должна проверить 12340, 12341, 12342 и, если 12349 свободна, она должна вернуть это, но она не должна возвращать значение, которое изменяет вводчисло, означающее, что если я вызываю Call getfreenum(1234,5) и все берется, включая '123459', то функция должна возвращать NULL или некоторое фиксированное значение для всех ошибок.

Ответы [ 2 ]

0 голосов
/ 30 декабря 2018

Функция используется для присвоения номеров предметов товарам в магазине.Иногда для некоторых предметов максимальное количество цифр равно 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.Наклейте удостоверение личности в соответствии с категорией.

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    |
+---------+
0 голосов
/ 30 декабря 2018

Вы можете получить набор всех 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 для 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;

DB Fiddle

И если вы имеете делос числами вы должны использовать соответствующий тип, а не char.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...