Обнаружение пропущенных значений в (с автоматическим увеличением) последовательности - PullRequest
3 голосов
/ 28 декабря 2011

У меня есть столбец INT 'Port', который должен быть в диапазоне от 30000 до 50000.

Итак, у меня есть хранимая процедура, вставляющая значения (Port is NOT NULL).Поэтому я должен выбрать «вручную» значение для хранения в этом поле.Проблема в том, что хотя я могу вставлять пошагово (30000,30001,30002 ....), в определенный момент некоторые записи удаляются (становится 30000, 30002, 30004 ....), поэтому есть отверстия, которые нужно установить.

Мне нужно разместить в моем SP способ, чтобы соответствовать этим отверстиям (на моем примере они 30001,30003 ....).Моя проблема заключается в том, как проверить в SP, если определенное значение уже «занято».

Я думал, используя LOOP из MySQL.Пробовал что-то вроде этого:

CREATE PROCEDURE teste()
BEGIN
DECLARE p INT;
DECLARE aux INT;
SET p = 30000;

  label1: LOOP

    SELECT Port FROM Reg WHERE Port = p INTO aux;

    IF p = 50000 THEN
    LEAVE label1;
    END IF;


    IF aux IS NULL THEN -- aux-1 is not null, so I can verify the "next  miminum available position"
        aux = aux - 1;
        LEAVE label1;

    ELSE
        SET p = p + 1;
        ITERATE label1;


    END IF;

  END LOOP label1;

 RETURN aux;

END $$

Моя проблема заключается в получении значения результата.Если я размещу эту инструкцию RETURN, я получу информацию, которая разрешена только для FUNCTION.И результат SELECT всегда равен нулю, когда я заканчиваю цикл.

Что я могу сделать?

Ответы [ 4 ]

5 голосов
/ 28 декабря 2011

Вот как вы можете найти пропущенные значения в вашей последовательности.

SELECT a.id+1 AS start, MIN(b.id) - 1 AS end
    FROM seq AS a, seq AS b
    WHERE a.id < b.id
    GROUP BY a.id
    HAVING start < MIN(b.id)

Пример вывода:

    +-------+------+
    | start | end  |
    +-------+------+
    |     4 |    4 |
    |     7 |    9 |
    +-------+------+

Это означает, что в id значение последовательности 4 отсутствует, а такжецифры от 7 до 9 (включительно).

Адаптируйте этот код для своих нужд, заменив соответствующие имена.

2 голосов
/ 28 декабря 2011
SELECT IFNULL(MIN(r1.Port) + 1, 30000) as minport
FROM Reg r1
LEFT JOIN Reg r2 ON r1.Port + 1 = r2.Port
WHERE r2.Port IS NULL:
1 голос
/ 28 декабря 2011

Можете ли вы сделать что-то подобное?

SELECT
    MIN(Port + 1)
FROM
    Reg
WHERE
    Port + 1 NOT IN (
        SELECT Port FROM Reg WHERE Port > 0
    )
ORDER BY
    Port ASC
0 голосов
/ 28 декабря 2011

Просто вставьте IGNORE для всех значений от 30000 до 50000 (при условии, что у вас есть уникальный ключ на поле). Нет ничего быстрее, чем сама БД в обнаружении, существует ли значение или нет.

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