|
|
|
| Нужно исключить запись одинаковых значений в базу
Застрял на организации цикла с проверкой
В таблице в базе есть поле “kod”
1. Случайным образом генерируется число
2. Дальше сверяется есть ли уже такое значение в базе
3. Если есть увеличиваем это число на 1
4. Проверяем еще раз в базе
5. Если опять существует то пункт 3
6. Если совпадений нет то выполняем дальнейший код
Хотел вместо этого (генерация и сверка) использовать поле id, но мне нужно,
чтобы код был 9-ти значный и в полях записывался не в порядке счета как id (1,2,3,4,5…), а в перемешку.
Можно конечно каждый раз при совпадении перезагружать страницу, но уверен этого делать не стоит. | |
|
|
|
|
|
|
|
для: Sergey_555
(21.12.2014 в 14:44)
| | ну ваш алгоритм можно сократить при использовании цикла while
1. Случайным образом генерируется число
2. Пока в базе есть такое число, увеличиваем число на 1
3. Если совпадений нет то выполняем дальнейший код | |
|
|
|
|
|
|
|
для: lightning.say
(21.12.2014 в 15:02)
| | Вот именно на этом моменте и застрял.
Если просто вывести из базы в цикле, что-то по каким-либо критериям, то проблем нет.
Но до меня не доходит как в цикле организовать проверку и повторную генерацию. | |
|
|
|
|
|
|
|
для: Sergey_555
(21.12.2014 в 16:09)
| | так а в чем проблема? я так понимаю под "Если совпадений нет то выполняем дальнейший код" имеется в виду заносим запись с кодом числа которого не существует в БД, зачем опять генерировать что-то? Т.е. в этом случае уникальным кодом будет первый свободный код после существующих.
Или можно заново сгенерировать и проверить, если не найден - внести в БД, тогда не надо ничего прибавлять. В этом случае генерация будет продолжаться до тех пор пока не найдется свободный код. | |
|
|
|
|
|
|
|
для: lightning.say
(21.12.2014 в 16:35)
| | Да имеется в виду Если совпадений нет то заносим запись с кодом числа которого не существует в БД.
Генерировать новое еще раз только в том случае, если в базе уже имеется запись с таким кодом
--------------------------------
Выполняются какие либо действия результаты которых потом запишутся в поле 1 и поле 2
отношения к проблеме не имеет
но вместе с ними в поле kod должно записаться случайное число
id kod поле 1 поле 2 …
1 352 текст 1 текст 2 …
2 572 текст 3 текст 4 …
3 365 текст 5 текст 6 …
4 896 текст 7 текст 8 …
5 587 текст 9 текст 10 …
1 Генерируем число ( допустим сгенерировалось 572 )
2 проверяем в базе
3 Если такое уже есть возвращаемся в пункт 1, если такого нет то добавляем новую запись в таблицу
Дальше после добавления записи продолжаем дальнейшее выполнение каких-либо действий
отношения к проблеме уже не имеет
----------------------------------------
Помогите, пожалуйста, правильно написать код который это будет делать | |
|
|
|
|
|
|
|
для: Sergey_555
(21.12.2014 в 17:48)
| | >Помогите, пожалуйста, правильно написать код который это будет делать
так вы начните хоть писать что-то а люди тут вам помогут если что не правильно а за вас вряд ли кто-то будет писать.... | |
|
|
|
|
|
|
|
для: lightning.say
(21.12.2014 в 19:08)
| | Елки палки, есть некий проект не проект (незнаю как правильно) с выбором некоторых значений из базы, вставкой их в формы для последующего выбора пользователем (следовательно сама отправка форм и их обработка), запись в базу полученного . Далее возможность загрузки файлов с определенным расширением ( содержимое JSON ‘засраное другим записями в нескольких местах’, из-за чего пришлось плясать с бубном чтобы получить чистый JSON и вытянуть с него определенную информацию), опять же занести это в базу. По необходимости сделать выборку из базы одного или нескольких значений по определенны критериям и вывести в цикле, и т.д.
ЭТО ВСЕ Я СДЕЛАЛ
Теперь возникла необходимость при добавлении записи вписывать сгенерированное число.
Застрял я на проверке в цикле и генерации нового при совпадении.
Не знаю как правильно записать, Dreamweaver ошибку в этом куске кода подсвечивает.
Уверен, что это самый простой вариант и полностью исключит совпадения.
Что будет потом когда все числа будут использованы и все зациклится до бесконечности ?
Да ничего не будет. Не будет в базе 900 млн записей ( при условии длины значения в 9 символов ), от силы за долгое время наберется менее 1 млн. Да и зациклится до бесконечности сервер не даст, ошибку выдаст, связанную с превышением максимального времени исполнения. | |
|
|
|
|
|
|
|
для: Sergey_555
(21.12.2014 в 14:44)
| | а) Зачем требется случайность?
Девятизначность кода можно обеспечить и при последовательном переборе номеров.
б) Если все же генерировать случайный код, почему на шаге 3 просто не вернуться к шагу 1?
в) чтобы ключ оказался уникальным, совсем необязательно называть его id.
Куда важнее создать на этом поле уникальный индекс.
г) перезвагрузка страницы к логике генерации ключей не имеет отношения. То есть вообще и никакого. | |
|
|
|
|
|
|
|
для: Trianon
(21.12.2014 в 15:05)
| | а) Все должны быть в случайном порядке, а не как при автоинкременте.
думал отталкиваться именно от него дописывыя в начало и конец сгенерированное. В случае если в количество превысит (а оно превысит ) 9 символов, обрезать до нужной длины. В любом случае нужно будет брать из таблицы id последней записи. Так что лучше уж в цикле проверять и генерировать.
б) Увеличение на 1 при совпадении решил сделать по той причине, что будет меньше шансов попасть на последовательное число в базе
в) при совпадении будет ошибка во время записи … (не совсем понимаю), тогда нужно будет еще раз генерировать try catch ?
г) 100% не имеет, просто это приведет к повторному выполнению с начала страницы (генерация и проверка) типа если такое в базе есть то начинаем все сначала, если нет то записываем и идем дальше (это от моей безысходности) | |
|
|
|
|
|
|
|
для: Sergey_555
(21.12.2014 в 16:09)
| | >а) Все должны быть в случайном порядке, а не как при автоинкременте.
Порядок не может быть случайным.
Истинно случайным будет лишь беспорядок.
Отсюда вынужден повторить вопрос:
Зачем вам случайность?
И если достаточно кажущейся "беспорядочности" номеров может быть стоит опереться именно на автоинкрементное поле?
9 десятичных знаков то около 32 бит. То есть как раз емкость типа INT MySQL.
Если посчитать какой-нибудь аккуратный хеш вроде CRC32 от двоичного представления автоинкрементного поля id, получится число, весьма напоминающее случайное.
Его ничто не мешает запихнуть в поле kod безо всякой проверки, поскольку коллизия никогда не настанет, пока 32-битовый счетчик не переполнится.
Если же легкая псевдослучайность не устраивает (а она не устраивает обычно из соображений сильной криптографии) то тут придется применять очень специальные методы, до которых, судя по задаваемым вопросам, сильно боюсь, что ваш опыт несколько недорос.
и тем не менее.
Общий подход примерно таков. Таблица должна иметь уникальный индекс на поле kod.
1.Получить очередное значение из источника случайных величин.
2.Привести его к формату хранимого поля.
3.Записать его новой строкой в таблицу базы. Не проверить наличие, а именно записать.
Последняя операция может закончиться как успехом, так и неудачей (из-за наличия в таблице такой записи)
4 проверить успешность шага 3. Несли неудачно (то есть выявлен повтор) - перейти к шагу 1.
5. Profit!!! (как сейчас говорят) . То бишь результат достигнут.
Почему записать сразу, а не проверить?
Потому что пока 1 инстанс процесса проверяет, его параллельная теоретически тоже может чего-то проверить/вписать, тем самым вызвав нарушение логики. | |
|
|
|
|
|
|
|
для: Trianon
(21.12.2014 в 18:46)
| | Ваше предложение не смотря на мой несколько недоросший до нужного уровня опыт (судя по задаваемым вопросом) мне вполне понятно.
Кроме предложенного вами варианта было еще несколько других.
Использовать вместо него дату.
Дописывать id к дате.
Генерировать число с помощью microtime(), и брать 9 последних знаков, а в базу записывать через блок try catch.
Использовать hash от id с salt, затем обрезать до 9 символов.
Создать отдельную таблицу и нагенерировать в нее с перемешкой чисел (range shuffle), затем выбирать в общем порядке.
И т.д. и т.п.
Одни варианты просто не подходили, другие просто непонятно зачем такие извращения.
Вобщем похоже моего скудного ума хватило, вроде сделал.
<?php
$kod_gen = mt_rand(101, 149);
do
{
$kod=++$kod_gen;
$result = mysql_query("SELECT kod FROM table_11 WHERE kod = '$kod_gen'");
$myrow= mysql_fetch_array($result);
}
while ($myrow['kod'] == $kod_gen);
$sql = mysql_query("INSERT INTO table_11 (kod) VALUES('".$kod_gen."')");
if ($sql) { echo 'Данные добавленны';}
else{echo 'Ошибка';}
?> | |
|
|
|
|
|
|
|
для: Sergey_555
(21.12.2014 в 23:22)
| | В вашем коде возможна запись одинаковых чисел:
От Trianon:
Почему записать сразу, а не проверить?
Потому что пока 1 инстанс процесса проверяет, его параллельная теоретически тоже может чего-то проверить/вписать, тем самым вызвав нарушение логики.
|
Предложу свой вариант(не проверял м.б. ошибки, но принцип должен быть ясен)
<?
function gen_kod()
{
static $gen_kod = rand(101, 149);
//поле kod должно иметь уникальный индекс в mysql
if(mysql_query("INSERT INTO table_11 (kod) VALUES ('".$gen_kod."')") === true) return true;
$gen_kod++;
gen_kod();
}
gen_kod();
|
| |
|
|
|
|
|
|
|
для: tvv123456
(22.12.2014 в 19:04)
| | ваша функция в теле вызывает саму себя, она зациклится =)
да и так
static $gen_kod = rand(101, 149);
|
статической переменной не может быть выражение | |
|
|
|
|
|
|
|
для: lightning.say
(22.12.2014 в 21:22)
| | >ваша функция в теле вызывает саму себя, она зациклится =)
Если запись в БД произошла, то выполнение прекратится и будет инициирован выход из функции до того как она будет вызвана повторно.См. рекурсия
>да и так
>
static $gen_kod = rand(101, 149);
|
>статической переменной не может быть выражение
Может быть, может быть :), но думаю ТС сможет исправить данную строчку кода, но на всякий случай перепишу код:
<?
function gen_kod()
{
static $gen_kod = 0;
if($gen_kod===0) $gen_kod=rand(101,149);
//поле kod должно иметь уникальный индекс в mysql
if(mysql_query("INSERT INTO table_11 (kod) VALUES ('".$gen_kod."')") === true) return true;
$gen_kod++;
gen_kod();
}
gen_kod();
|
Есть один минус: можно превысить глубину рекурсии установленную в настройках сервера, но опять же цикл при удачном стечении обстоятельств тоже может быть остановлен из-за превышения, например, времени выполнения. Так что мне думается рекурсия более выгодный вариант, особенно если увеличить диапазон внутри rand | |
|
|
|
|
|
|
|
для: tvv123456
(22.12.2014 в 22:27)
| | Нарушение лимита в настройках - единственное, что вас беспокоит?
А то что процесс ресурсы при этом жрет как не в себя, это пофиг?
На ровном месте при чем. Где итеративный вариант - в двух строках правки.
Будь моя воля - откусывал бы голову лишал лицензии | |
|
|
|
|
|
|
|
для: Trianon
(22.12.2014 в 23:06)
| | Ну, есть конечно такая особенность на которую я забил забыл, но почему-то мне показалось в данном случае это несущественным(может ответами навеяло или самим вопросом?). Может время было позднее :) может еще что-то. | |
|
|
|