Aplicar actualizaciones de catálogo por versiones

SQLiteBeginner
Practicar Ahora

Introducción

MEND & MOSS está listo para aplicar las actualizaciones de los proveedores. Su puesto de recepción ya tiene una entrega cargada en la tabla intermedia y la inspección básica del laboratorio anterior. Este es un entorno independiente: no se necesitan archivos de una VM anterior.

Algunas líneas que parecen utilizables discrepan sobre la misma edición. Otras llegan tarde. Ampliarás la inspección para rechazar esas contradicciones y guardarás un script de actualización que avance solo a revisiones más recientes, conservando las notas locales de ubicación de la tienda. Se presupone el SQL básico del primer laboratorio guiado; aquí se explican las comprobaciones de conflictos, UPSERT y las transacciones.

Usa Terminal durante todo el laboratorio. Puedes modificar inspect.sql, crear apply.sql y volver a cargar raw_delivery. Conserva las identidades y notas de ubicación originales de las existencias, los proveedores y los dos archivos CSV. Los valores de nombre, precio y revisión que pertenecen al proveedor pueden avanzar según las reglas siguientes.

Rechazar ediciones contradictorias

En este paso, distinguirás una línea idéntica repetida de un conflicto de edición. Empieza en Terminal:

cd /home/labex/project/supplier-desk

Lee la entrega real de esta unidad y el script de inspección proporcionado:

cat deliveries/current.csv
cat inspect.sql

Las diez líneas de la entrega ya están cargadas en la tabla intermedia. Las líneas 3 y 7 repiten la misma identidad, nombre, precio y revisión de la cinta de reparación; repetir un dato no lo convierte en un producto nuevo. Las líneas 8 y 9 describen N / PIN-2, revisión 2, pero discrepan sobre el precio. Ninguna es una respuesta aprobada. La línea 10 asigna a N / WASH-2, revisión 1, un precio diferente al de la revisión 1 existente en las existencias. Un número de edición no puede significar dos contenidos diferentes.

Las reglas del primer laboratorio siguen vigentes. Hay dos motivos de rechazo adicionales: delivery conflict cuando filas válidas en los demás aspectos tienen el mismo proveedor/SKU/revisión pero distinto nombre o precio entero, y stock conflict cuando esa edición discrepa de las existencias actuales. Si se cumplen ambos, el conflicto de entrega tiene prioridad. Se aceptan las repeticiones idénticas. Las ediciones inferiores pueden aceptarse para la inspección, pero nunca deben sobrescribir existencias más recientes.

Consulta las existencias originales antes de modificarlas:

sqlite3 -header -column stock.db 'SELECT * FROM stock ORDER BY supplier,sku;'

Ejecuta la inspección básica para que existan sus vistas:

sqlite3 -bail stock.db < inspect.sql

Antes de editar, crea una copia de recuperación del script proporcionado. cp copia la primera ruta a la segunda sin modificar el original:

cp inspect.sql inspect-start.sql

El siguiente SQL usa los alias t, other, s y e para nombrar una fila de entrega, otra fila de entrega, una fila de existencias y una fila de error. EXISTS (SELECT 1 ...) pregunta si existe alguna fila coincidente; el 1 es solo un marcador porque no se devuelve el contenido de la fila. AND exige que coincidan todos los campos clave. <> significa distinto. NOT EXISTS conserva las filas sin error. UNION ALL combina los errores básicos y los conflictos sin perder las identidades de las líneas individuales.

Añade la ampliación al final de inspect.sql. >> añade en lugar de reemplazar, así que conserva encima las definiciones básicas proporcionadas. Pega este bloque una vez. Repetirlo resulta inocuo aquí porque cada ampliación solo vuelve a crear las dos vistas finales, pero evita duplicar texto innecesariamente:

cat >> inspect.sql <<'SQL'
DROP VIEW IF EXISTS delivery_ready;
DROP VIEW IF EXISTS delivery_errors;
CREATE VIEW delivery_errors AS
SELECT delivery_line,reason FROM delivery_check WHERE reason IS NOT NULL
UNION ALL
SELECT t.delivery_line,
  CASE WHEN EXISTS (
    SELECT 1 FROM typed_delivery AS other
    WHERE other.supplier=t.supplier AND other.sku=t.sku
      AND other.revision=t.revision
      AND (other.title<>t.title OR other.price_cents<>t.price_cents)
  ) THEN 'delivery conflict' ELSE 'stock conflict' END
FROM typed_delivery AS t
WHERE EXISTS (
  SELECT 1 FROM typed_delivery AS other
  WHERE other.supplier=t.supplier AND other.sku=t.sku
    AND other.revision=t.revision
    AND (other.title<>t.title OR other.price_cents<>t.price_cents)
) OR EXISTS (
  SELECT 1 FROM stock AS s
  WHERE s.supplier=t.supplier AND s.sku=t.sku AND s.revision=t.revision
    AND (s.title<>t.title OR s.price_cents<>t.price_cents)
);
CREATE VIEW delivery_ready AS
SELECT supplier,sku,title,price_cents,revision FROM typed_delivery AS t
WHERE NOT EXISTS (
  SELECT 1 FROM delivery_errors AS e WHERE e.delivery_line=t.delivery_line
);
SQL

Vuelve a ejecutar todo el script guardado:

sqlite3 -bail stock.db < inspect.sql
sqlite3 -header -column stock.db 'SELECT * FROM delivery_errors ORDER BY delivery_line;'

Deberías ver seis errores: línea 4 invalid price, 5 unknown supplier, 6 missing SKU, 8 y 9 delivery conflict, y 10 stock conflict. La cinta de reparación aparece dos veces en la revisión de datos aceptados porque ambas líneas fuente son aceptables; un par de líneas idénticas no debe duplicar un precio ni crear dos artículos de existencias.

sqlite3 -header -column stock.db 'SELECT * FROM delivery_ready ORDER BY supplier,sku;'

Hay cuatro filas de entrega aceptadas que representan tres identidades de producto. Las existencias siguen sin cambios. Si solo ves los tres errores básicos, comprueba que esté presente el bloque añadido y vuelve a ejecutar el script completo. Si hay un error de sintaxis en el bloque añadido, restaura la base proporcionada con cp inspect-start.sql inspect.sql, repite el bloque de ampliación completo y vuelve a ejecutar el script. Esta recuperación deja sin cambios las existencias y ambos archivos CSV.

Aplicar valores más recientes y repetir la entrega con seguridad

En este paso, aplicarás las filas aceptables sin cambiar las notas locales de ubicación y demostrarás que repetir la misma entrega o recibir una anterior no deshace tu trabajo. Empieza en el mismo directorio de Terminal.

La tabla stock tiene una clave primaria sobre (supplier,sku): esos dos campos identifican una fila. Una operación UPSERT inserta una identidad que falta o gestiona un conflicto con esa clave existente. excluded hace referencia a la fila entrante propuesta. Su revisión debe ser mayor que la revisión actual de las existencias para que se produzca una actualización. La columna proporcionada shelf_note pertenece a la tienda: omítela tanto de los valores entrantes como de las asignaciones de actualización. Una identidad nueva recibe el valor predeterminado preparado de nota vacía.

BEGIN inicia una transacción y COMMIT la guarda como una unidad. Un error detiene este comando con -bail; al cerrar su conexión se revierte una transacción sin terminar. Este ejemplo actualiza una base de datos pequeña y preparada; no es un sistema de sincronización concurrente ni de copias de seguridad.

El SELECT lee la vista real de datos aceptados. Su WHERE true conserva todas esas filas y evita que SQLite confunda el ON CONFLICT posterior con una condición de unión. Guarda el script completo:

cat > apply.sql <<'SQL'
BEGIN;
INSERT INTO stock(supplier,sku,title,price_cents,revision)
SELECT supplier,sku,title,price_cents,revision
FROM delivery_ready WHERE true
ON CONFLICT(supplier,sku) DO UPDATE SET
  title=excluded.title,
  price_cents=excluded.price_cents,
  revision=excluded.revision
WHERE excluded.revision>stock.revision;
COMMIT;
SQL

Activa las claves foráneas en la conexión utilizada para aplicarlo. -cmd ejecuta primero la configuración de conexión entre comillas; no se guarda globalmente. Después, < apply.sql proporciona el SQL:

sqlite3 -bail -cmd 'PRAGMA foreign_keys=ON;' stock.db < apply.sql
sqlite3 -header -column stock.db 'SELECT * FROM stock ORDER BY supplier,sku;'

Deberías ver cuatro filas de existencias:

supplier  sku     title        price_cents  revision  shelf_note
--------  ------  -----------  -----------  --------  ----------
N         BOLT-1  Steel bolt   135          3         Bin A
N         TAPE-4  Repair tape  450          1
N         WASH-2  Washer       40           1         Bin C
W         BOLT-1  Brass bolt   190          2         Drawer 4

La arandela sigue a 40 porque se rechazó su edición contradictoria. No se añadió ningún pasador, tapa no válida, artículo de proveedor desconocido ni artículo con SKU vacío. Se conservan las notas originales de ambos pernos. La cinta de reparación tiene una sola fila aunque aparecía dos veces en la entrega.

Repite el mismo script:

sqlite3 -bail -cmd 'PRAGMA foreign_keys=ON;' stock.db < apply.sql
sqlite3 -header -column stock.db 'SELECT * FROM stock ORDER BY supplier,sku;'

El resultado permanece igual. La condición de revisión permite repetir una importación idéntica con seguridad; no suma el precio ni reemplaza la nota local.

Ahora lee la entrega anterior antes de usarla:

cat deliveries/older.csv

Estas son ediciones anteriores de los pernos. Vuelve a cargar solo la tabla intermedia mediante el intérprete interactivo:

sqlite3 stock.db
DELETE FROM raw_delivery;
.import --csv --skip 1 deliveries/older.csv raw_delivery
.quit

Las vistas leen automáticamente las filas actuales de la tabla. Ejecuta la actualización sin cambios e inspecciona las existencias:

sqlite3 -bail -cmd 'PRAGMA foreign_keys=ON;' stock.db < apply.sql
sqlite3 -header -column stock.db 'SELECT * FROM stock ORDER BY supplier,sku;'

Las cuatro filas siguen teniendo los mismos valores. La inspección acepta números anteriores válidos, pero aplicarlos no puede hacer retroceder las existencias. Esto es distinto de una entrega no válida o contradictoria.

Deja el puesto preparado para revisar de nuevo la entrega de hoy. Vaciar la tabla intermedia no vacía las existencias:

sqlite3 stock.db
DELETE FROM raw_delivery;
.import --csv --skip 1 deliveries/current.csv raw_delivery
.quit
sqlite3 -header -column stock.db 'SELECT * FROM delivery_errors ORDER BY delivery_line;'

Las seis líneas rechazadas siguen visibles con sus motivos. Conserva ambos scripts: inspect.sql describe cómo se revisa otra entrega compatible; apply.sql describe cómo sus filas seguras hacen avanzar las existencias. Puedes recuperarte de una ruta incorrecta con el cd absoluto; un script mal escrito puede reemplazarse a partir del bloque completo. No vuelvas a crear stock.db ni borres registros para corregir un error de escritura.

Resumen

Usaste filas reales de SQLite para relacionar las identidades de los proveedores, los valores de las entregas y las existencias locales. Interpretaste los registros realmente aceptados y rechazados, conservaste las fuentes originales y guardaste SQL reutilizable para la próxima entrega.