Nueva publicación

查找

Pregunta
· 28 mayo, 2025

How to use EnsLib.SQL.InboundAdapter in IRIS tables

Hi community.

I was wondering if it was possible to use something like EnsLib.SQL.InboundAdapter with tables in IRIS.

This library monitors when a record has been inserted into a table in an external database, so it requires a DSN to connect to that database.

My goal is to make a call to an external API that takes a long time, it could spend nearly an hour (or more) completing its processes, but I don't want to block the main process.

That's why I was thinking about having the original production store the indicators it needs to process in a table, and from another production, monitor when a record has been inserted and invoke the API (with a fairly high timeout) to process that record.

In short, I want to use IRIS as a queue manager (similar to MSMQ) and have it "listen" for changes to execute a process.

Is it possible to access IRIS tables using an InBoundAdapter?

Any suggestions for achieving the same result? That is, having a queue manager and processing as data enters the queue.

Best regards.
Kurro Lopez

2 comentarios
Comentarios (2)3
Inicie sesión o regístrese para continuar
Artículo
· 27 mayo, 2025 Lectura de 7 min

Uso de SQL Dinámico vs SQL Embebido en InterSystems IRIS y Plan de ejecución

InterSystems IRIS permite ejecutar consultas SQL directamente desde ObjectScript mediante:

  • SQL Embebido (Embedded SQL): consultas SQL compiladas en tiempo de desarrollo, con chequeo de tipos y mayor eficiencia.
  • SQL Dinámico (Dynamic SQL): permite construir y ejecutar sentencias SQL en tiempo de ejecución, ideal para casos flexibles o condicionales.

Que es SQL (Structured Query Language) es un lenguaje estándar utilizado para interactuar con bases de datos relacionales. Permite realizar operaciones como:

  • Consultar datos (SELECT)
  • Insertar registros (INSERT)
  • Actualizar datos (UPDATE)
  • Eliminar registros (DELETE)
  • Crear y modificar estructuras (tablas, índices, vistas, etc.)

SQL es usado en...

  • Bases de datos tradicionales: Oracle, MySQL, SQL Server, PostgreSQL
  • Bases de datos modernas: InterSystems IRIS, Snowflake, BigQuery, etc.
  • Aplicaciones web y móviles para acceder a datos desde backend o APIs

 

¿Por qué es importante?

  • Es el lenguaje universal para bases de datos
  • Permite extraer información útil desde grandes volúmenes de datos
  • Es compatible con herramientas de BI, ETL, dashboards, análisis y más

Según la documentación de intersystems en el siguiente link pueden obtener mayor detalle https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=GSQL

Incluye:

  • Sintaxis general de SQL
  • Consultas SELECT, INSERT, UPDATE, DELETE
  • Uso de índices
  • Funciones agregadas (COUNT, SUM, AVG, etc.)
  • JOIN, subconsultas y UNION
  • Optimización de consultas
  • Vistas y procedimientos almacenados

 

En este artículo exploraremos ambos enfoques con ejemplos prácticos y su uso en clases definidas en IRIS.

Pero optimizar consultas SQL es una de las tareas más importantes para mantener el buen rendimiento de una aplicación basada en InterSystems IRIS. Muchas veces, pequeñas mejoras en el diseño de la consulta o en los índices pueden producir mejoras significativas en velocidad, especialmente cuando se trabaja con grandes volúmenes de datos.

En este artículo técnico, exploraremos también cómo usar El Plan de Ejecución, cómo interpretar los planes de ejecución y qué prácticas seguir para escribir consultas eficientes.

También agregue imagenes y detalle del paso a paso para poder probar y ejecutar un caso práctico con clases cargadas y un proyecto en Github, el cual tiene toda la estructura de clases y ejecución para usar con Docker

Definición de clase de ejemplo

Primero, crearemos una clase de ejemplo para almacenar datos de pacientes:

Class Demo.Paciente Extends (%Persistent)

{

    Property Nombre As %String;
    Property Edad As %Integer;
    Property Diagnostico As %String;
}

 

Y crearemos otra clase de ejemplo para almacenar datos de pacientes pero con índice:

Class Demo.PacienteIndice Extends (%Persistent)

{

    Property Nombre As %String;
    Property Edad As %Integer;
    Property Diagnostico As %String;
    Index EdadIndex On Edad;
}

 

Cómo funciona la ejecución de consultas en IRIS

El motor SQL de InterSystems IRIS convierte una consulta en un plan de ejecución, que define cómo se van a recuperar los datos. Este plan puede incluir:

  • Escaneos completos de tabla
  • Uso de índices
  • Ordenamientos intermedios
  • Tipos de join (nested loop, merge join, etc.)

Entender ese plan permite mejorar consultas que de otro modo serían lentas.

 

Continuamos con el script para insertar los datos  

https://github.com/kathitadurcon/sql-iris-demo/blob/main/sql-iris-demo/i...

SQL Embebido

¿Qué es?

SQL Embebido te permite insertar consultas SQL dentro del código ObjectScript. Estas consultas se compilan con el código, proporcionando rendimiento y verificación anticipada.

Ahora un ejemplo práctico

Class Demo.SQLEmbebido

{

    ClassMethod BuscarPacientes(minEdad As %Integer)

    {

        &sql(DECLARE c CURSOR FOR
              SELECT Nombre, Edad FROM Demo.Paciente WHERE Edad >= :minEdad)



        &sql(OPEN c)

        While (SQLCODE = 0) {

            &sql(FETCH c INTO :nombre, :edad)

            If (SQLCODE = 0) {

                Write "Paciente: ", nombre, " (", edad, " años)", !

            }

        }

        &sql(CLOSE c)

    }

}

Ejecución:

USER>Do ##class(Demo.SQLEmbebido).BuscarPacientes(35)

Resultado:

Paciente: Luis (45 años)

SQL Dinámico

¿Qué es?

SQL Dinámico te permite construir sentencias SQL en tiempo de ejecución, ideal para situaciones en las que no sabes con anticipación los filtros o campos que se usarán.

Ejemplo práctico

Class Demo.SQLDinamico

{

    ClassMethod BuscarPorDiagnostico(diagnostico As %String)

    {

        Set consulta = "SELECT Nombre, Edad FROM Demo.Paciente WHERE Diagnostico = ?"
        Set rs = ##class(%SQL.Statement).%New()

        Set sc = rs.%Prepare(consulta)

        If $$$ISERR(sc) {

            Write "Error preparando consulta",!

            Quit
        }



        Set r = rs.%Execute(diagnostico)

        While r.%Next() {

            Write "Paciente: ", r.%Get("Nombre"), " (", r.%Get("Edad"), " años)", !

        }

    }

}

Ejecución:

Do ##class(Demo.SQLDinamico).BuscarPorDiagnostico("Diabetes")

Resultado:

Paciente: Luis (45 años)

 

 Comparación rápida

Característica

SQL Embebido

SQL Dinámico

Validación en compilación 

 Sí

 No (se evalúa en ejecución)

Rendimiento

 Rápido

 Ligeramente más lento

Flexibilidad

 Menor

 Alta (puedes construir consultas)

Uso recomendado

Lógica fija y conocida    

Filtros condicionales o configurables

 

Tanto el SQL Embebido como el Dinámico son herramientas valiosas en InterSystems IRIS. Puedes usarlos según el contexto:

  • ¿Consultas conocidas, validadas y frecuentes? Usa SQL Embebido.
  • ¿Consultas variables o configurables? Usa SQL Dinámico.

 

Sigamos con un caso práctico!

Que necesitamos?

  • Un contenedor Docker con IRIS Community Edition.
  • Código fuente .cls con los ejemplos.
  • Script de inicialización para poblar la base de datos.
  • Instrucciones paso a paso.

Estructura del proyecto

sql-iris-demo/

├── Dockerfile

├── iris.script

└── cls/

    ├── Demo.Paciente.cls

    ├── Demo.SQL_Embebido.cls

    └── Demo.SQL_Dinamico.cls

Cómo ejecutar la demo

  1. Crea una carpeta local, por ejemplo: sql-iris-demo/
  2. Clonamos el repo https://github.com/kathitadurcon/sql-iris-demo
  3. Abre una terminal y navega a esa carpeta
  4. Ejecuta:

docker build -t iris-sql-demo .

docker run -d --name iris-sql -p 52773:52773 -p 1972:1972 iris-sql-demo

  1. Inicia sesión en la terminal de IRIS:

docker exec -it iris-sql iris session IRIS

  1. Dentro de la sesión, ejecuta:

Do ##class(Demo.SQLEmbebido).BuscarPacientes(35)

Do ##class(Demo.SQLDinamico).BuscarPorDiagnostico("Diabetes")

 

Salida esperada

Paciente: Luis (45 años)

Paciente: Luis (45 años)

 

Portal de Gestión para ver el Plan de ejecución

Entramos al Portal de Gestión, normalmente usamos usuario SuperUser clave SYS y nos pedirá cambiar la clave

http://localhost:52773/csp/sys/%25CSP.Portal.Home.zen

Vamos a SQL

Y nos aseguramos que el NameSpace sea USER

 

Anteriormente creamos dos clase Demo.Paciente y la clase Demo.PacienteIndice que tiene creado el índice para edad

Index EdadIndex On Edad;

 

Ejecutamos lo siguiente
SELECT

ID, Diagnostico, Edad, Nombre

FROM Demo.Paciente

WHERE Edad=32

 

Resultado

Ejecutamos lo siguiente

SELECT

ID, Diagnostico, Edad, Nombre

FROM Demo.PacienteIndice

WHERE Edad=32

 

Resultado

Interpretación:

Al agregar los indices a una clase y después hacer las consultas el costo relativo baja, a mayor volumen de datos se ve reflejado con respuestas más rápidas.

 

Reescritura de consultas para mejorar rendimiento

Algunos consejos útiles:

Problema

Solución sugerida

WHERE YEAR(Fecha) = 2023  

WHERE Fecha BETWEEN '2023-01-01' AND '2023-12-31'

SELECT *

Seleccionar solo las columnas necesarias

WHERE sin condición clara

Asegurarse de usar claves o índices en join o where

 

Ahora Vamos con el VIDEO

3 comentarios
Comentarios (3)3
Inicie sesión o regístrese para continuar
Pregunta
· 27 mayo, 2025

How to programmatically create SQL Gateway Connection?

In Management Portal one can create and configure connection in:

System Administration
 > Configuration
  > Connectivity
   > SQL Gateway Connections
    > Create New Connection

But how to create new connection programmatically?

2 comentarios
Comentarios (2)2
Inicie sesión o regístrese para continuar
Anuncio
· 27 mayo, 2025

Meet the Winners of the AI Programming Contest at InterSystems READY 2025 @ Tech Exchange!

Hi Community!

We’re excited to announce that several winners of the InterSystems AI Programming Contest have been invited to showcase their projects at the Tech Exchange during InterSystems Ready 2025!

Join us on Wednesday, June 25, to explore innovative, real-world solutions built with InterSystems IRIS, AI, LLMs, and intelligent agent technologies — directly from the developers who created them:

Presenter Demo
@Muhammad Waseem, Technical Consultant, Traverse Health

Next generation of autonomous AI Agentic Applications

iris-AgenticAI

@Yuri Marx, Director, YM Services

Natural Language Control of IRIS

langchain-iris-tool

@Eric Fortenberry, Integration Analyst Senior, AdventHealth

A Minimalist View of AI: Exploring Embeddings and Vector Search with EasyBot

iris-easybot 

@Alena Krasinskiene, Quality and Customer Experience Manager, Banksia Global

AI Agents as First-Class Citizens in InterSystems IRIS

bg-iris-agent

@Henry Pereira, Tech Leader at BPlus tecnology
@Henrique Dias, Senior Platform Architect, AI at Zendesk
@José Pereira, Data Engineer at Shift

Command the Crew - create an AI crew to automate your work

Facilis

These developers have built cutting-edge solutions using InterSystems IRIS technologies, integrating AI, LLMs, and intelligent agents to solve real-world challenges.

Don't miss the chance to see these demos live and connect with the minds behind them at Ready 2025!

4 comentarios
Comentarios (4)3
Inicie sesión o regístrese para continuar
Pregunta
· 27 mayo, 2025

SQL Query returns <UNDEFINED> with OFFSET

I am testing vectorsearch, while doing so I am trying to paginate my resultset for a "next page" function to give me the first, second, third 15 entries within a table. 

For this I have two embedding classes. One with a HNSW Index (vectornomicembedtextlatest) , and one without (vectornomicembedtexttest).

Calling SELECT ID,PRIMKEY FROM SQLUser.vectornomicembedtexttest LIMIT 5 OFFSET 1 works fine with the first entry having the rowID of 486448. (I deleted old entries in the beginning and reused the table)

SELECT ID,PRIMKEY FROM SQLUser.vectornomicembedtexttest ORDER BY PRIMKEY DESC LIMIT 5 OFFSET 1  -> This works fine.

Calling my Vectorsearch SQL command however gives an <UNDEFINED> error: 
SELECT Primkey FROM SQLUser.vectornomicembedtexttest WHERE Mandant = '0' AND Klasse = 'CRMSHOPARTIKEL' LIMIT 3 OFFSET 1 ORDER BY VECTOR_DOT_PRODUCT(Embedding, TO_VECTOR('-.3707275390625,-.092041015625,-3.88720703125,... ,.298583984375', DOUBLE, 768)) DESC 

SQLCODE 400
[%msg: <ObjectScript-Fehler: <UNDEFINED>%0Afirst+3^%sqlcq.PHARMBUY.cls113.HWwDnTI0TjK.1>]

If I do the same for my indexed table everything works fine
SELECT Primkey FROM SQLUser.vectornomicembedtextlatest WHERE Mandant = '0' AND Klasse = 'CRMSHOPARTIKEL' LIMIT 3 OFFSET 1 ORDER BY VECTOR_DOT_PRODUCT(Embedding, TO_VECTOR('-.3707275390625,-.092041015625,-3.88720703125,... ,.298583984375', DOUBLE, 768)) DESC 

This is the Index
Index HNSWIndex On (Embedding) As %SQL.Index.HNSW(Distance = "DotProduct") [ SqlName = HNSWIndex, Type = index ];

However vectornomicembedtextlatest also starts with a rowID of 1 instead of 486448 because I haven't deleted any entries. Not sure if that is the problem here. 

Comentarios (0)1
Inicie sesión o regístrese para continuar