Etiqueta

24 septiembre 2014

Uso de variables vinculadas (Bind) en sentencias SQL

Al ejecutarse (por defecto) cualquiera de los métodos disponibles para una instancia de tipo "Table", como por ejemplo $select() o $insert(), Omnis genera dinámicamente la sentencia SQL correspondiente, pero antes de su ejecución, compone (proceso conocido como “tokenize”) todos y cada uno de los elementos (variables, valores, etc) que conformaran la sentencia SQL que enviará al servidor.

Particularmente, esto significa que Omnis deberá localizar las referencias a las variables "bind" que hayamos utilizado, es decir las usadas mediante la notación @[variable]. Cuando Omnis "tokenize" la sentencia, tendrá en cuenta el ámbito en el que espera encontrar las variables referenciadas. En el caso de una instancia de tipo "Table", el ámbito de aplicación será, el de la propia instancia.

Llamamos "ámbito de aplicación" al medio en que podremos encontrar las variables declaradas, según sean "Task" (Nivel de Tarea), "Class" (Nivel de clase), "Local" (Nivel local), "Parameter" (Equivalente al nivel local) o "Hash" (Globales).

En el caso de que se trate de una lista creada en la instancia "Table" y definida mediante una clase "schema" o "query", se permitirá el uso de los siguientes ámbitos:

  • @[#...] - Una variable "hash", como por ejemplo @[#S1], o @[#10]. Con la excepción de #D, #T, #CT que son técnicamente "macro-hash" (evaluadas en el momento de ser referenciadas) y no pueden ser evaluadas durante el proceso "tokenize". Si necesitamos hacer uso de la fecha actual, podríamos optar por lo siguiente: Calculate lvCurrentDate as #D, para después, usar @[lCurrentDate].
  • @[taskvar] - una variable de tarea, siempre y cuando la tarea que ejecuta y define la lista sean la misma.
  • @[$cinst.column] - cuando se trata de una "row" definida con una clase SQL, "column", sería una de las columnas de la "row".
  • @[$cinst.N.column] - cuando se trata de una lista definida con una clase SQL, "column", sería una de las columnas de la lista, "N" sería un número de línea literal. Por ejemplo, @[$cinst.5.column] haría referencia al valor de "column" en la línea 5. No está permitido el uso de otras notaciones entre corchetes, dentro de éstas, es decir, la referencia @[$cinst.[lvRowNo].column] no es admitida como variable "bind". Una solución a esto, podría ser, hacer uso del comando Calculate $cinst.$line as lvRowNo, para después, usar @[$cinst.column].

A continuación mostramos un ejemplo sobre como hacer uso de una variable "bind" al obtener datos, en correspondencia con los almacenados en la columna "Col3" de una lista:

Begin Statement
   Sta: Select * from Table
   Sta: Where Col = @[iList.Col3]
End Statement

Do lStatementObj.$prepare() Returns lStatus
For iList.$line from 1 to iList.$linecount
   Do lStatementObj.$execute() return lStatus
   Do lStatementObj.$fetch(iRow)
   .....
End for

En el caso de que se trate de una lista creada en la instancia "Table" y definida mediante una clase "schema" o "query", también podría utilizar:

  • @[$cinst.iVar] donde "iVar" sería una variable de instancia en la clase "Table" y que podría haber sido configurada mediante la ejecución previa de un método, como por ejemplo MyList.$setbind('valor') antes de invocar al MyList.$select(), MyList.$insert(), etc

En el ejemplo siguiente, se invoca al método $setbind que contendría a su vez el parámetro "pVar" y un sola línea "Calculate iVar as pVar". Luego, desde fuera de la clase "Table" tendríamos lo siguiente:

Calculate lFruit as 'Oranges'
Do lList.$definefromsqlclass('MyTable')
Do lList.$setbind(lFruit)
Do lList.$sessionobject.$assign(iSessionObj)
Do lList.$select('WHERE Fruit=@[$cinst.iVar]')
Do lList.$fetch(kFetchAll)

La formula descrita en éste artículo nos permite el uso de variables que de otra manera no estarían a nuestro alcance desde la clase "Table".

No hay comentarios: