Не собираюсь на работу. Самый близкий подход был бы следующим: защитить ваш первый запрос, заключив его в подзапрос:
SELECT NUM
FROM (SELECT 10000 + ROUND(RAND()*89999) AS NUM) AS SUBQ
WHERE NUM NOT IN (SELECT PHONE_NUMBER FROM PHONE);
Но, хотя он выбирает один номер между 10000 и 99999, он сможет проверить его не только , а затем . Если проверка завершится неудачно, запрос ничего не даст, и вам придется повторить его (или усложнить его с помощью UNION, что все еще не дает абсолютной гарантии).
Другой возможностью было бы создание другой таблицы с всеми числами от 10000 до 99999 и выполнение LEFT JOIN
, запрашивающее, чтобы правая сторона была NULL. Затем вы должны выбрать случайную запись из этого результата; Я не уверен, но в этом случае вам, возможно, придется запустить ORDER BY RAND (), а затем LIMIT 1, чтобы извлечь одну запись, после возможного выбора девятисот тысяч. Это будет дорого (но см. Ответ в конце).
Наиболее эффективный способ , если таблица телефона почти пуста - использовать хранимую процедуру и продолжать выполнять первый запрос (или генерацию, сопровождаемую проверкой), пока она не завершится успешно, что, если телефон таблица редкая, она должна быть сделана за очень мало попыток.
В противном случае вы можете предварительно заполнить таблицу телефона всеми номерами (таблица уже значительно заполнена, так что это не большие дополнительные расходы), добавив столбец, в котором указано, что номер «свободен». Затем вы выбираете случайную запись из таблицы с условием, что свободный маркер дает значение true. В этом случае вы захотите прочитать этот ответ .