@@ -450,87 +450,88 @@ within your seed class and then use the ``insert()`` method to insert data:
450450 You must call the ``saveData() `` method to commit your data to the table.
451451 Migrations will buffer data until you do so.
452452
453- Upserting Data
454- --------------
453+ Insert Modes
454+ ============
455+
456+ In addition to the standard ``insert() `` method, Migrations provides specialized
457+ insert methods for handling conflicts with existing data.
455458
456- .. versionadded :: 5.0.0
457- `` insertOrUpdate() `` and `` insertOrSkip() `` were added in 5.0.0.
459+ Insert or Skip
460+ --------------
458461
459- For seeds that may be run multiple times, you can use ``insertOrUpdate() `` to insert
460- new records or update existing ones based on conflict columns. This is particularly
461- useful for configuration or reference data that should always reflect certain values:
462+ The ``insertOrSkip() `` method inserts rows but silently skips any that would
463+ violate a unique constraint:
462464
463465.. code-block :: php
464466
465467 <?php
466468
467469 use Migrations\BaseSeed;
468470
469- class ConfigSeed extends BaseSeed
471+ class CurrencySeed extends BaseSeed
470472 {
471473 public function run(): void
472474 {
473475 $data = [
474- [
475- 'key' => 'site_name',
476- 'value' => 'My Application',
477- ],
478- [
479- 'key' => 'maintenance_mode',
480- 'value' => 'false',
481- ],
476+ ['code' => 'USD', 'name' => 'US Dollar'],
477+ ['code' => 'EUR', 'name' => 'Euro'],
482478 ];
483479
484- $settings = $this->table('settings');
485- // For PostgreSQL and SQLite, you must specify the conflict column(s)
486- $settings->insertOrUpdate($data, ['key'])
487- ->saveData();
488-
489- // For MySQL, conflict columns are optional (uses all unique constraints)
490- // $settings->insertOrUpdate($data)->saveData();
480+ $this->table('currencies')
481+ ->insertOrSkip($data)
482+ ->saveData();
491483 }
492484 }
493485
494- .. note ::
495-
496- The ``$conflictColumns `` parameter behavior differs by database:
486+ Insert or Update (Upsert)
487+ -------------------------
497488
498- - **MySQL **: The parameter is ignored because MySQL's ``ON DUPLICATE KEY UPDATE ``
499- automatically applies to all unique constraints.
500- - **PostgreSQL/SQLite **: The parameter is required and specifies which column(s)
501- to use for conflict detection.
502-
503- Insert or Skip
504- ~~~~~~~~~~~~~~
505-
506- If you want to insert records only when they don't already exist (without updating),
507- use the ``insertOrSkip() `` method:
489+ The ``insertOrUpdate() `` method performs an "upsert" operation - inserting new
490+ rows and updating existing rows that conflict on unique columns:
508491
509492.. code-block :: php
510493
511494 <?php
512495
513496 use Migrations\BaseSeed;
514497
515- class DefaultRolesSeed extends BaseSeed
498+ class ExchangeRateSeed extends BaseSeed
516499 {
517500 public function run(): void
518501 {
519502 $data = [
520- ['name' => 'admin', 'description' => 'Administrator'],
521- ['name' => 'user', 'description' => 'Regular User'],
522- ['name' => 'guest', 'description' => 'Guest User'],
503+ ['code' => 'USD', 'rate' => 1.0000],
504+ ['code' => 'EUR', 'rate' => 0.9234],
523505 ];
524506
525- $roles = $this->table('roles');
526- // Skip inserting if a role with the same name already exists
527- $roles->insertOrSkip($data, ['name'])
528- ->saveData();
507+ $this->table('exchange_rates')
508+ ->insertOrUpdate($data, ['rate'], ['code'])
509+ ->saveData();
529510 }
530511 }
531512
532- This is useful for seeding default data that should not overwrite any customizations
533- made by users.
513+ The method takes three arguments:
514+
515+ - ``$data ``: The rows to insert (same format as ``insert() ``)
516+ - ``$updateColumns ``: Which columns to update when a conflict occurs
517+ - ``$conflictColumns ``: Which columns define uniqueness (must have a unique index)
518+
519+ .. warning ::
520+
521+ Database-specific behavior differences:
522+
523+ **MySQL **: Uses ``ON DUPLICATE KEY UPDATE ``. The ``$conflictColumns `` parameter
524+ is ignored because MySQL automatically applies the update to *all * unique
525+ constraint violations on the table. Passing ``$conflictColumns `` will trigger
526+ a warning. If your table has multiple unique constraints, be aware that a
527+ conflict on *any * of them will trigger the update.
528+
529+ **PostgreSQL/SQLite **: Uses ``ON CONFLICT (...) DO UPDATE SET ``. The
530+ ``$conflictColumns `` parameter is required and specifies exactly which unique
531+ constraint should trigger the update. A ``RuntimeException `` will be thrown
532+ if this parameter is empty.
533+
534+ **SQL Server **: Not currently supported. Use separate insert/update logic.
534535
535536Truncating Tables
536537=================
0 commit comments