Постоянно пытаться вставить случайные уникальные значения в таблицу

#php #mysql

#php #mysql

Вопрос:

Итак, у меня есть функция, которая генерирует случайное число в базе 62, и я хотел бы попытаться вставить случайное уникальное число длиной 7 в таблицу. Изначально у меня было автоматическое увеличение строк по мере ввода значений, но для этого требовалось много вставок, выбора, а затем обновления строк. Вот новый код, который пока не работал:

 do {
    if (isset($query)) { mysqli_stmt_close($query); }
    $query = mysqli_prepare($connection, "INSERT INTO table1 value1=?");
    mysqli_stmt_bind_param($query, 's', rand_64(7));
} while (!mysqli_stmt_execute($query));
mysqli_stmt_close($query);
  

Мой вопрос: можно ли достичь чего-то подобного, или было бы лучше сгенерировать случайные числа, попробовать оператор SELECT, и если возвращаемые строки == 0, прекратить цикл и вставить значения?

Редактировать: я должен отметить, что он правильно вставляет значения, если значение уникально (т. Е. Его еще нет в таблице), но не может вставить, если значение уже существует.

Большое спасибо. 🙂

Комментарии:

1. Вы пробовали ON DUPLICATE KEY или INSERT IGNORE ?

2. Сколько из них вы должны вставить? Это одноразовое требование или вам нужно будет делать это повторно?

3. Фред: В этом случае, вероятно, не сработал бы ДУБЛИРУЮЩИЙ КЛЮЧ, потому что мне нужно было бы знать, какое число генерируется. Майк: Пользователь загружает файлы, и это переименовывает их с помощью генератора случайных строк, чтобы к ним можно было позже подключиться. Конечная цель — продолжать цикл и пытаться вставить, пока не произойдет столкновения.

4. будут ли ‘uniqid’ и ‘base_convert’ или ‘base64_encode’ делать то, что вы хотите?

Ответ №1:

Вот простой способ присвоить случайное уникальное значение каждой строке в таблице:

 SET @r = 0;

UPDATE table1
SET value1 = (@r:=@r 1)
ORDER BY RAND();
  

Вы получаете значения от 1 до количества строк в таблице, но значения распределяются псевдослучайно, а не увеличиваются, как при автоинкременте.

Ответ №2:

Вы не можете привязать результат вызова функции или литерал к подготовленному оператору — это должна быть переменная. Если вы присвоите возвращаемое значение rand_64() переменной перед ее привязкой, у вас должно быть больше успеха.

Кроме того, вам нужно подготовить запрос только один раз, чтобы вы могли вывести его из цикла.

Это дает вам:

 if (isset($query)) { mysqli_stmt_close($query); }

$query = mysqli_prepare($connection, "INSERT INTO table1 set value1=?");

do {
    $rand = rand_64(7)
    mysqli_stmt_bind_param($query, 's', $rand);
} while (!mysqli_stmt_execute($query));

mysqli_stmt_close($query);
  

Все это говорит о том, что, поскольку вы генерируете переменную самостоятельно и, скорее всего, потребуется только один вызов базы данных, вы, вероятно, получите лучшую общую производительность, не используя здесь подготовленный оператор.

Предполагая, что ваша rand_64() функция не возвращает никаких строк, содержащих одинарные кавычки, вы получаете:

 $success = true;
do {
    $rand = rand_64(7)
    $query = "INSERT INTO table1 set value1='$rand'";
    if (mysqli_query($connection, $query)) == true) {break;}
    if (mysqli_error($connection) != 1062) {
      $success = false;
      break;
    }
} while (true);
  

NB:

  • Я исправил синтаксическую ошибку в вашем SQL
  • ваш value1 должен быть помечен как уникальный, ненулевой.
  • Я еще не тестировал этот код.

Комментарии:

1. Спасибо за помощь. Я пробовал этот код, и он должен сработать, потому что mysqli_query возвращает true / false, верно? Но когда я это делаю, он помещает себя в бесконечный цикл. Есть какие-нибудь идеи, что может происходить?

2. Ваш исходный SQL-запрос был неправильным и сгенерировал синтаксическую ошибку, поэтому цикл будет продолжаться вечно. Я исправил свой фрагмент и добавил проверку цикла на разрыв, если ошибка не является дубликатом.