Vistas SQL
Vistas SQL
Las Vistas SQL (o Vistas personalizadas) son una pantalla de a3ERP en la que el usuario puede ejecutar consultas o procesos sobre la base de datos sin salir de la aplicación. El funcionamiento es sencillo: el usuario abre la vista desde el menú y pulsa el botón de ejecutar; si la vista tiene parámetros, aparece entonces una ventana para rellenarlos (fechas, códigos, filtros...), y al aceptar se lanza el SQL.
A partir de ahí, la vista se comporta de una de estas dos maneras según lo que contenga:
- Consulta (SELECT): devuelve una tabla de resultados que el usuario puede revisar, exportar a Excel, etc. Funciona como cualquier listado, pero sin diseño de impresión.
- Proceso (DML): ejecuta una operación sobre los datos — actualizar campos, marcar registros... — sin devolver filas. Es el equivalente a un botón de "ejecutar proceso masivo".
Hay esqueletos completos de ambos tipos en las plantillas.
Las vistas de proceso son destructivas
Una vista de proceso modifica la base de datos en el momento en que el usuario acepta la ventana de parámetros. Debe llevar un comentario de advertencia al principio y seguir el patrón de salida descrito más abajo, para que quien la lance sepa siempre qué ha pasado.
Parámetros#
El intérprete de a3ERP sustituye los marcadores [...] por los valores que el usuario introduce en la ventana de parámetros antes de ejecutar.
El mismo mecanismo funciona en listados y parrillas
Los parámetros de usuario no son exclusivos de las vistas: un listado de impresión o una parrilla de búsqueda también pueden llevarlos, aunque es poco común. Se documentan aquí porque las vistas son su hábitat natural — son su única forma de recibir datos del usuario.
Forma básica#
[Nombre humano,TIPO]
[Nombre humano,TIPO,ValorPorDefecto]
SET @MES = [Mes,VARCHAR(2),01];
SET @FECHA = [Fecha Mínima,DATETIME,01/01/2021];
Solo el nombre y el tipo son obligatorios; el valor por defecto, si se indica, es lo que aparece precargado en la ventana de parámetros. Un detalle casi obvio, pero que conviene dejar dicho: el nombre humano no puede contener comas — la coma es precisamente lo que separa los bloques del marcador.
Con selector de tabla#
Se puede añadir un cuarto bloque que indica a a3ERP qué tabla y campo usar para abrir una pantalla de selección cuando el usuario hace doble clic en el parámetro — así no tiene que saberse los códigos de memoria:
[Nombre humano,TIPO,ValorPorDefecto,(TABLA,CAMPO,FILTRO_OPCIONAL)]
SET @TARIFA = [Tarifa,CUADRADO(8), ,(TARIFAS,TARIFA,TARIFA.TIPO = 'V')];
SET @CAR1 = [Fabricante,CUADRADO(8), ,(CARACTERISTICAS,CODCAR,CARACTERISTICAS.NUMCAR = 1 AND CARACTERISTICAS.TIPCAR = 'A')];
El tercer elemento del filtro es opcional y acota qué registros ofrece la pantalla de selección (en los ejemplos, solo tarifas de venta y solo características de artículo de la posición 1).
Tipos de parámetro#
| Tipo | Comportamiento |
|---|---|
VARCHAR(n) |
Cadena libre de hasta n caracteres, sin transformar |
INT |
Número entero |
MONEY |
Importe con decimales |
DATETIME |
Fecha; el usuario la introduce en formato DD/MM/AAAA |
CUADRADO(n) |
Cadena de exactamente n caracteres, mayúsculas y completada con espacios por la izquierda |
Cuándo usar CUADRADO
Los códigos de a3ERP están "cuadrados": guardados con padding de espacios por la izquierda a longitud fija, normalmente 8 caracteres (CODPRO = ' 1770', TARIFA = ' 1'); las excepciones (CODART a 15, lotes a 25...) están en la visión general. Con CUADRADO(n) la aplicación genera ese padding automáticamente. Si cambias el tipo a VARCHAR sin ajustar el WHERE, la consulta no encontrará nada.
Directos en la consulta o asignados a variables#
Los marcadores pueden ir directamente en el WHERE:
WHERE ART.CAR1 = [Fabricante,CUADRADO(8)]
AND TV.FECMIN = [Fecha Mínima,DATETIME,01/01/2021]
O asignarse a variables, que es lo cómodo cuando el valor se usa varias veces o sirve para calcular otros:
SET @MES = [Mes,VARCHAR(2),01];
SET @ANO = [Año,VARCHAR(4),2025];
SET @FECHAINI = '01-' + @MES + '-' + @ANO;
SET @FECHAFIN = DATEADD(DD, -1, DATEADD(MM, 1, @FECHAINI));
Trampas frecuentes#
- No usar
:ni[...]en comentarios SQL. El intérprete lee:textocomo parámetro runtime y[texto]como marcador de parámetro estén donde estén, comentarios incluidos (--y/* */), y la vista peta en ambos casos. Cuidado especial con el dos puntos al final de la línea: un:justo antes del salto también lo trata como parámetro. Reformular sin esos caracteres: - ❌
-- Solo afecta a periodicidad distinta de M (mensual): - ✅
-- Solo afecta a periodicidad distinta de M (mensual) — es decir, - ❌
-- Pasos: 1) ... - ✅
-- Pasos. 1) ... - No usar corchetes como alias de columna. Por el mismo motivo,
SELECT col AS [Nombre]rompe la vista. Los alias van siempre con comillas simples:SELECT col 'Nombre'. - No hay transacción implícita. a3ERP lanza el SQL sin envolverlo en una transacción propia. Si el proceso hace varios
UPDATEy el segundo falla, el primero ya está confirmado y los datos quedan a medias. Si el proceso necesita atomicidad, hay que abrir la transacción dentro de la propia vista (BEGIN TRANSACTION / COMMIT / ROLLBACK). SET NOCOUNT ONen vistas de proceso. Sin él, cada sentencia DML devuelve su mensaje de "N filas afectadas" y a3ERP abre una pestaña de resultado por cada uno: el usuario acaba ante varias pestañas con números sueltos, sin saber qué significa cada una. Se desactiva (SET NOCOUNT OFF) justo antes delSELECTfinal para que el resultado que ve sea solo ese.
Patrón recomendado para vistas de proceso#
Una vista de proceso, tal cual, tiene un problema de experiencia: el usuario la ejecuta y no recibe una respuesta clara. Si el DML va sin SET NOCOUNT ON, le aparecen varias pestañas de "N filas afectadas" sin contexto; si va con él, no ve nada en absoluto. En ninguno de los dos casos sabe si el proceso ha funcionado, ha fallado o cuántos registros ha tocado.
La solución es que toda vista de proceso envuelva su DML en TRY/CATCH y termine con un SELECT que cuente el resultado. a3ERP renderiza ese SELECT como la parrilla de salida: si todo fue bien, el usuario ve el contador de filas afectadas; si algo falló, ve el mensaje de error con el detalle para depurar.
Así se ve una vista de proceso real que sigue el patrón, en la pantalla de edición de Vistas personalizadas — con su comentario de advertencia al principio, los parámetros de usuario en el WHERE y los dos SELECT de salida:

Plantilla básica (un solo UPDATE o INSERT)#
Cuando el proceso es una única sentencia DML no hace falta transacción explícita — la sentencia ya es atómica por sí misma:
SET NOCOUNT ON;
BEGIN TRY
UPDATE ... -- la lógica del proceso
DECLARE @filas INT = @@ROWCOUNT;
SET NOCOUNT OFF;
SELECT
'OK' 'Estado',
'Proceso finalizado sin errores' 'Mensaje',
@filas 'Líneas actualizadas';
END TRY
BEGIN CATCH
SET NOCOUNT OFF;
SELECT
'ERROR' 'Estado',
ERROR_MESSAGE() 'Mensaje',
ERROR_NUMBER() 'Número',
ERROR_SEVERITY() 'Severidad',
ERROR_STATE() 'Estado SQL',
ERROR_LINE() 'Línea',
ERROR_PROCEDURE() 'Procedimiento';
END CATCH
Plantilla con transacción explícita (varios DML)#
Si el proceso ejecuta más de una sentencia DML, hay que envolverlas en una transacción para que sean atómicas — sin ella, un fallo a mitad deja confirmadas las anteriores y el estado queda inconsistente:
SET NOCOUNT ON;
BEGIN TRY
BEGIN TRANSACTION;
UPDATE ... ;
UPDATE ... ;
DECLARE @filas INT = @@ROWCOUNT; -- la cuenta del UPDATE que interesa al usuario
COMMIT TRANSACTION;
SET NOCOUNT OFF;
SELECT
'OK' 'Estado',
'Proceso finalizado sin errores' 'Mensaje',
@filas 'Filas actualizadas';
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
SET NOCOUNT OFF;
SELECT
'ERROR' 'Estado',
ERROR_MESSAGE() 'Mensaje',
ERROR_NUMBER() 'Número',
ERROR_SEVERITY() 'Severidad',
ERROR_STATE() 'Estado SQL',
ERROR_LINE() 'Línea',
ERROR_PROCEDURE() 'Procedimiento';
END CATCH
Reglas a respetar#
Mensajejusto después deEstadoen elSELECTdelCATCH. Es la única columna que el usuario lee de verdad; si queda al final de la fila, tendrá que hacer scroll horizontal y no la verá.@@ROWCOUNTse captura inmediatamente después delUPDATEque interesa. Cualquier sentencia intermedia — otroUPDATE, una asignación — lo pisa.- Etiqueta del contador descriptiva del dominio, no genérica:
Tramos actualizados,Facturas marcadas OK... Si el usuario ve "Filas: 0" no sabe si eso es bueno o malo; si ve "Facturas marcadas OK: 0", entiende lo que ha pasado. - Alias con comillas simples, nunca corchetes (
'Estado', no[Estado]) — la regla general de las vistas, aplicada a las columnas delSELECTfinal. SET NOCOUNT OFFantes de cadaSELECTfinal (uno en elTRY, otro en elCATCH), para que a3ERP renderice la parrilla limpia.IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;en elCATCHde la versión con transacción. Sin elIF, si el error rompe la transacción antes de llegar alROLLBACK— raro, pero pasa — el propioROLLBACKtambién peta.