> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devinenterprise.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Playbook para corregir una migración de base de datos inestable

export const UseCaseHero = ({title, description, prompt, category, features, devinUrl, agent, intent, playbookId, type}) => {
  const encodedPrompt = encodeURIComponent(prompt || '');
  const tag = 'docs-use-case-gallery';
  const utm = 'utm_source=docs&utm_medium=use-case-gallery&utm_campaign=hero-cta';
  const agentParams = (agent ? '&agent=' + agent : '') + (intent ? '&intent=' + intent : '') + (playbookId ? '&playbookId=' + playbookId : '');
  const devinHref = type === 'schedule' ? 'https://app.devin.ai/settings/schedules/create?' + utm + agentParams + (prompt ? '&prompt=' + encodedPrompt : '') : type === 'review' ? 'https://app.devin.ai/review?' + utm : agent === 'ada' ? 'https://app.devin.ai/search?' + utm + '&noSubmit=true' + (prompt ? '&prompt=' + encodedPrompt : '') : devinUrl ? devinUrl.includes('?') ? devinUrl + '&' + utm + agentParams : devinUrl + '?' + utm + agentParams : prompt ? 'https://app.devin.ai/?tags=' + tag + '&' + utm + agentParams + '&prompt=' + encodedPrompt : 'https://app.devin.ai/?' + utm + agentParams;
  const buttonLabel = type === 'schedule' ? 'Schedule in Devin ↗' : type === 'review' ? 'Set Up Devin Review ↗' : agent === 'advanced' ? 'Try in Devin ↗' : agent === 'dana' ? 'Try in Dana ↗' : agent === 'ada' ? 'Try in Ask Devin ↗' : 'Try in Devin ↗';
  const featureList = features ? features.split(',').map(f => f.trim()) : [];
  return <div className="uc-hero">
      <div className="uc-hero-inner">
        <div className="uc-hero-left">
          <h1 className="uc-hero-title">{title}</h1>
          <p className="uc-hero-desc">{description}</p>
          <div>
            <a href={devinHref} target="_blank" rel="noopener noreferrer" className="try-in-devin-btn">
              {buttonLabel}
            </a>
          </div>
        </div>
        <div className="uc-hero-meta">
          <div className="uc-meta-item">
            <span className="uc-meta-label">Author</span>
            <span className="uc-meta-value">Cognition</span>
          </div>
          <div className="uc-meta-item">
            <span className="uc-meta-label">Category</span>
            <span className="uc-meta-value">{category}</span>
          </div>
          {featureList.length > 0 && <div className="uc-meta-item">
              <span className="uc-meta-label">Features</span>
              <span className="uc-meta-value">{featureList.join(', ')}</span>
            </div>}
        </div>
      </div>
    </div>;
};

export const PromptBlock = ({children, type, agent, intent, playbookId}) => {
  var utm = 'utm_source=docs&utm_medium=use-case-gallery&utm_campaign=prompt-block';
  var tag = 'docs-use-case-gallery';
  var agentParams = (agent ? '&agent=' + agent : '') + (intent ? '&intent=' + intent : '') + (playbookId ? '&playbookId=' + playbookId : '');
  var label = type === 'schedule' ? 'Schedule in Devin' : type === 'playbook' ? 'Create Playbook' : type === 'knowledge' ? 'Add to Knowledge' : agent === 'advanced' ? 'Try in Devin' : agent === 'dana' ? 'Try in Dana' : agent === 'ada' ? 'Try in Ask Devin' : 'Try in Devin';
  var buildUrl = function (text) {
    var encoded = encodeURIComponent(text);
    if (type === 'schedule') return 'https://app.devin.ai/settings/schedules/create?' + utm + agentParams + '&prompt=' + encoded;
    if (type === 'playbook') return 'https://app.devin.ai/settings/playbooks/create?' + utm + '&body=' + encoded;
    if (type === 'knowledge') return 'https://app.devin.ai/knowledge?' + utm + '&body=' + encoded;
    if (agent === 'ada') return 'https://app.devin.ai/search?' + utm + '&noSubmit=true&prompt=' + encoded;
    return 'https://app.devin.ai/?tags=' + tag + '&' + utm + agentParams + '&prompt=' + encoded;
  };
  const ref = React.useRef(null);
  const [href, setHref] = React.useState('#');
  React.useEffect(() => {
    if (!ref.current) return;
    var codeEl = ref.current.querySelector('pre code');
    if (codeEl) {
      var text = codeEl.textContent.trim();
      if (text) setHref(buildUrl(text));
    }
    var header = ref.current.querySelector('[data-component-part="code-block-header"]');
    if (header && !header.querySelector('.prompt-block-devin-link')) {
      var link = document.createElement('a');
      link.href = href;
      link.target = '_blank';
      link.rel = 'noopener noreferrer';
      link.className = 'prompt-block-devin-link';
      link.style.cssText = 'display:inline-flex;align-items:center;gap:6px;text-decoration:none;color:#fff;font-size:11px;font-weight:500;padding:4px 10px;border-radius:6px;white-space:nowrap;background:#317CFF;transition:background 0.2s;margin-left:8px;';
      link.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg> ' + label;
      link.onmouseenter = function () {
        link.style.background = '#2968D9';
      };
      link.onmouseleave = function () {
        link.style.background = '#317CFF';
      };
      header.appendChild(link);
    }
    var existingLink = ref.current.querySelector('.prompt-block-devin-link');
    if (existingLink && href !== '#') existingLink.href = href;
  });
  return <div className="prompt-block" ref={ref}>{children}</div>;
};

<UseCaseHero title="Corregir un playbook de migración de base de datos inestable" description="Tu playbook de migración de base de datos funciona con esquemas simples, pero se rompe con claves foráneas. Pasa cuatro enlaces de sesiones a Devin y deja que cubra las lagunas." prompt="Nuestro playbook de !db-migration sigue fallando cuando las sesiones chocan con restricciones de clave foránea. Aquí tienes 4 sesiones recientes: las sesiones 1 y 2 se completaron correctamente en tablas independientes, pero las sesiones 3 y 4 fallaron con errores de FK. Analiza los fallos, compáralos con los casos exitosos y actualiza el playbook para manejar las dependencias de FK antes de cualquier operación destructiva." category="Devin Optimization" features="Advanced, Playbooks" agent="advanced" intent="improve" />

<div className="uc-detail-wrapper">
  <Tip>¿No quieres configurar esto manualmente? Pega un enlace a esta página en una sesión de Devin y pídele que lo configure todo por ti.</Tip>

  <Steps>
    <Step title="Detecta el patrón entre sesiones">
      Tu equipo ha estado usando el playbook `!db-migration` durante unas semanas. Ha manejado el cambio de nombre de columnas y la adición de índices sin problema, pero las dos últimas sesiones se bloquearon a mitad de la migración cuando intentaron eliminar una columna referenciada por otras tablas.

      Abre cada sesión y revisa el punto de fallo. En este caso, las sesiones 3 y 4 dieron error en el mismo paso:

      ```
      ERROR: cannot drop column "account_id" because other objects depend on it
      DETAIL: constraint fk_orders_account_id on table orders depends on column account_id
      HINT: Use DROP ... CASCADE to drop dependent objects too.
      ```

      Ahora tienes una señal clara: el playbook no tiene un paso para comprobar las dependencias de claves foráneas antes de operaciones destructivas. Dos sesiones tuvieron éxito porque afectaron a tablas independientes; dos fallaron porque no lo hicieron.
    </Step>

    <Step title="Abre la pestaña Improve Playbook con enlaces a sesiones">
      Ve a [app.devin.ai](https://app.devin.ai/?utm_source=docs\&utm_medium=use-case-gallery) y haz clic en **Advanced** debajo del cuadro de entrada. Selecciona la pestaña **Improve Playbook**.

      Elige `!db-migration` en el desplegable de playbooks y luego selecciona las cuatro sesiones en el **session multi-dropdown**, tanto las exitosas como las fallidas. Incluir sesiones exitosas permite que Devin vea en qué funciona bien el playbook, no solo dónde se rompe.

      <PromptBlock agent="advanced" intent="improve">
        ```txt Improve the db-migration playbook theme={null}
        Our !db-migration playbook works for simple table changes but fails
        when sessions hit foreign key constraints. Sessions 1 and 2 succeeded
        on standalone tables, but sessions 3 and 4 crashed on FK errors.

        Analyze all 4. Figure out what the successful sessions did differently
        (they hit standalone tables with no incoming FKs). Then update the
        playbook to:
        1. Query information_schema for FK dependencies before any DROP or ALTER
        2. Generate ALTER TABLE ... DROP CONSTRAINT statements when FKs exist
        3. Add a rollback step that re-creates dropped constraints if the
           migration fails partway through
        ```
      </PromptBlock>

      Qué hace que este prompt sea eficaz:

      * **Nombra el fallo exacto** — "foreign key constraints" en lugar de "a veces falla"
      * **Contrasta éxitos y fallos** — Devin puede comparar las transcripciones de las sesiones para ver dónde divergen
      * **Enumera correcciones concretas** mientras deja espacio para que Devin saque a la luz problemas que pasaste por alto
    </Step>

    <Step title="Revisa el diff del playbook">
      Devin lee las transcripciones de las cuatro sesiones, identifica dónde los fallos divergen de los éxitos y propone ediciones específicas. La salida se ve como un changelog de tu playbook:

      ```
      ## Analysis

      Sessions 1-2 succeeded because they only modified tables with no
      incoming foreign keys. Sessions 3-4 failed at step 4 ("Drop the
      old column") because the orders and invoices tables had FK
      references to the target column.

      ## Changes to !db-migration

      Added step 3a: "Before any DROP or ALTER that removes a column,
        query information_schema.key_column_usage to list dependent FKs.
        If any exist, generate ALTER TABLE ... DROP CONSTRAINT statements
        and execute them first. Save the original constraint DDL for
        rollback."

      Added step 7: "Rollback procedure — if any step after FK removal
        fails, re-create the dropped constraints using the saved DDL
        from step 3a."

      Updated Advice section: "Always run the migration against a staging
        database first. FK chains can be deeper than expected — a column
        in table A may be referenced by B, which is referenced by C.
        Query recursively."
      ```

      El playbook se guarda automáticamente. Si algo no encaja, responde en la misma sesión; por ejemplo: "Also add a step to notify the #database Slack channel before running destructive migrations."
    </Step>

    <Step title="Verifica la corrección en una migración nueva">
      No necesitas salir de tu sesión actual de Devin. Una vez que se guarde la actualización del playbook, usa la misma sesión para iniciar una sesión estándar de Devin que pruebe el playbook actualizado contra el mismo escenario que falló antes:

      <PromptBlock>
        ```txt Test the updated playbook theme={null}
        Use the !db-migration playbook to drop the legacy_account_id column
        from the users table. This column is referenced by orders.account_id
        and invoices.billing_account_id — the playbook should handle the FK
        dependencies automatically.
        ```
      </PromptBlock>

      Si esta sesión tiene éxito, la corrección funciona. Si encuentra un nuevo caso límite (por ejemplo, referencias de FK circulares), vuelve a enviar esa sesión a la pestaña Improve Playbook para otra iteración.
    </Step>
  </Steps>
</div>
