Предотвращение посева уникальных ключевых нарушений

У меня есть уникальное ограничение в моей базе данных для двух столбцов.

$table->unique(array("table_a_id", "table_b_id"));

Теперь я использую Faker в классе сеялки, чтобы заполнить эту сводную таблицу:

$tableAIds = TableA::all()->lists("id")->toArray();
$tableBIds = TableB::all()->lists("id")->toArray();

foreach(range(1, 20) as $index) {
$tableAId = $faker->randomElement($tableAIds);
$tableBId = $faker->randomElement($tableBIds);

DB::table("table_a_table_b_pivot")->insert([
"table_a_id" => $tableAId,
"table_b_id" => $tableBId
]);
}

Однако это создает дубликаты, и заполнение не выполняется из-за ошибки SQL.

Как мне убедиться, что я не пытаюсь вставить дубликаты?

0

Решение

Вы можете использовать это:

$tableAIds = TableA::all()->lists("id")->toArray();
$tableBIds = TableB::all()->lists("id")->toArray();
foreach (range(1, 20) as $index) {
repeat:
$tableAId = $faker->randomElement($tableAIds);
$tableBId = $faker->randomElement($tableBIds);
try {
DB::table("table_a_table_b_pivot")->insert([
"table_a_id" => $tableAId,
"table_b_id" => $tableBId,
]);
} catch (\Illuminate\Database\QueryException $e) {
//look for integrity violation exception (23000)
if($e->errorInfo[0]==23000)
goto repeat;
}
}

PS: Это может не сработать, если исходные данные TableA и TableB не соответствуют друг другу (то есть из этих данных невозможно сформировать 20 уникальных пар).

0

Другие решения

$unique = $faker->unique()->regexify('[0-4][0-9][0-4][0-9]');

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

$firstId = ltrim(substr($unique, 0, 2), '0') + 1;
$secondId = ltrim(substr($unique, 2, 2), '0') + 1;

Два числа могут быть одинаковыми в строке, но строка всегда будет уникальной. Не забудьте добавить по одному для каждой части, потому что мы не хотим (и не можем) заполнять нашу базу данных нулями.

0

Вместо того, чтобы использовать фейкер, используйте коллекцию random метод:

$tableAIds = TableA::all()->lists('id')->random(20);
$tableBIds = TableB::all()->lists('id')->random(20);

foreach(range(0, 19) as $index) {
DB::table("table_a_table_b_pivot")->insert([
"table_a_id" => $tableAIds[$index],
"table_b_id" => $tableBIds[$index],
]);
}

Отрегулируйте это в соответствии с вашими потребностями.

Например, это может быть то, что вы действительно хотите:

$tableAIds = TableA::all()->lists('id');
$tableBIds = TableB::all()->lists('id');

foreach ($tableAIds->random(5) as $tableAId) {
foreach ($tableBIds->random(2) as $tableBId) {
DB::table("table_a_table_b_pivot")->insert([
"table_a_id" => $tableAId,
"table_b_id" => $tableBId,
]);
}
}

Что бы это ни было, играйте с этим сами. Нет необходимости для мошенника здесь.

-1
По вопросам рекламы [email protected]