Compatibilidad de tipos de datos

Al contrario de lo que ocurre con la mayoría de bases de datos SQL, el motor de base de datos SQL de Adobe AIR no exige que las columnas de las tablas contengan valores de tipos concretos. El motor de ejecución utiliza dos conceptos, las clases de almacenamiento y la afinidad de columnas, para controlar los tipos de datos. En esta sección se describen las clases de almacenamiento y la afinidad de columnas, así como el modo en que se resuelven distintos tipos de datos en diversas condiciones:

Clases de almacenamiento

Las clases de almacenamiento representan los tipos de datos reales que se utilizan para guardar valores en una base de datos. Se utilizan las siguientes clases de almacenamiento en la base de datos:

NULL
El valor es un valor NULL.

INTEGER
El valor es un entero con signo.

REAL
El valor es un valor numérico de coma flotante.

TEXT
El valor es una cadena de texto (limitada a 256 MB).

BLOB
El valor es un objeto grande binario (BLOB); dicho de otro modo, datos binarios sin procesar (limitados a 256 MB).

Todos los valores suministrados a la base de datos como literales incorporados en una declaración SQL o valores ligados al uso de parámetros en una declaración SQL preparada se asignan a una clase de almacenamiento antes de que se ejecute la declaración SQL.

A los literales que forman parte de una declaración SQL se les asigna una clase de almacenamiento TEXT si están encerrados con comillas simples o dobles, una clase INTEGER si el literal está especificado como un número sin comillas, sin punto decimal ni exponente, una clase REAL si el literal es un número sin comillas, con punto decimal o exponente y una clase de almacenamiento NULL si el valor es NULL. Los literales con clase de almacenamiento BLOB se especifican con la notación X'ABCD'. Para obtener más información, consulte Valores literales en expresiones.

Los valores suministrados como parámetros con el conjunto asociativo SQLStatement.parameters se asignan a la clase de almacenamiento que mejor coincidencia tenga con el tipo de datos. Por ejemplo, los valores int se vinculan a una clase de almacenamiento INTEGER, los valores Number a la clase REAL, los valores String a la clase de almacenamiento TEXT y los objetos ByteArray a la clase de almacenamiento BLOB.

Afinidad de columnas

La afinidad de una columna es el tipo recomendado para los datos guardados en dicha columna. Cuando se guarda un valor en una columna (mediante una declaración INSERT o UPDATE), el motor de ejecución intenta convertir el valor de su tipo de datos en la afinidad especificada. Por ejemplo, si se inserta un valor Date (instancia de Date en ActionScript o JavaScript) en una columna cuya afinidad es TEXT, el valor Date se convertirá a la representación de String (equivale a llamar al método toString() del objeto) antes de guardarlo en la base de datos. Si el valor no se puede convertir a la afinidad especificada, se produce un error y la operación no se lleva a cabo. Cuando se recupera un valor de la base de datos mediante una declaración SELECT, se devuelve como una instancia de la clase correspondiente a la afinidad, independientemente de si se convirtió a un tipo de datos distinto al guardarse.

Si una columna acepta valores NULL, el valor null de ActionScript o JavaScript se puede utilizar como valor de parámetros para almacenar NULL en la columna. Cuando se recupera una clase de almacenamiento NULL de una declaración SELECT, siempre se devuelve como el valor null de ActionScript o JavaScript, independientemente de la afinidad de la columna. Si una columna acepta valores NULL, siempre comprueba los valores recuperados de dicha columna para determinar si son null antes de intentar convertir los valores a un tipo que no pueda ser NULL (como Number o Boolean).

A cada columna de la base de datos se le asigna uno de los siguientes tipos de afinidad:

  • TEXT (o String)

  • NUMERIC

  • INTEGER (o int)

  • REAL (o Number)

  • Boolean

  • Date

  • XML

  • XMLLIST

  • Object

  • NONE

TEXT (o String)

Una columna con afinidad TEXT o String almacena todas las clases de almacenamiento NULL, TEXT o BLOB. Si se insertan datos numéricos en una columna con afinidad TEXT, se convierten a texto antes de guardarlos.

NUMERIC

Una columna con afinidad NUMERIC contiene valores que utilizan clases de almacenamiento NULL, REAL o INTEGER. Cuando se insertan datos de texto en una columna NUMERIC, se intenta convertir en un número entero o real antes de guardarlo. Si la conversión se realiza correctamente, el valor se guarda con la clase de almacenamiento INTEGER o REAL (por ejemplo, un valor de '10.05' se convierte a una clase de almacenamiento REAL antes de ordenarlo). Si no se puede realizar la conversión, se produce un error. No se intenta convertir a un valor NULL. Se devuelve un valor recuperado de una columna NUMERIC como una instancia del tipo numérico más específico con el que encaje el valor. Dicho de otro modo, si el valor es un entero positivo o 0, se devuelve como una instancia de uint. Si es un entero negativo, se devuelve como instancia de int. Finalmente, si tiene un componente de coma flotante (no es un entero), se devuelve como instancia de Number.

INTEGER (o int)

Una columna que utiliza afinidad INTEGER se comporta del mismo modo que una columna con afinidad NUMERIC, con una excepción. Si el valor se va a guardar como un valor real (instancia de Number) sin componente de coma flotante o si el valor es un valor de texto que se puede convertir a un valor real sin componente de coma flotante, se convierte a un entero y se guarda utilizando la clase de almacenamiento INTEGER. Si se intenta guardar un valor real con un componente de coma flotante se produce un error.

REAL (o Number)

Una columna con afinidad REAL o NUMBER se comporta como una columna con afinidad NUMERIC con la diferencia de que fuerza los valores enteros a una representación de coma flotante. Siempre se devuelve un valor de una columna REAL de la base de datos como una instancia de Number.

Boolean

Una columna con afinidad Boolean almacena valores true o false. Una columna Boolean acepta un valor que es una instancia de Boolean en ActionScript o JavaScript. Si el código intenta guardar un valor String, un elemento String con longitud mayor que cero se considerará true y un elemento vacío String se considerará false. Si el código intenta guardar datos numéricos, se guardará cualquier valor distinto de cero como true y 0 se guardará como false. Cuando se recupera un valor Boolean con una declaración SELECT, se devuelve como instancia de Boolean. Los valores no NULL se guardan con la clase de almacenamiento INTEGER (0 para false; 1 para true) y se convierten en objetos Boolean cuando se recuperan los datos.

Date

Una columna con afinidad Date almacena valores de fecha y hora. Una columna Date está diseñada para aceptar valores que sean instancias de Date de ActionScript o JavaScript. Si se intenta guardar un valor String en una columna Date, el motor de ejecución intentará convertirlo en una fecha de calendario juliano. Si falla la conversión, se produce un error. Si el código intenta guardar un valor Number, int o uint, no se realiza ningún intento para validar los datos y se asume que se trata de un valor de fecha de calendario juliano correcto. Un valor Date recuperado con una declaración SELECT se convierte automáticamente en una instancia de Date. Los valores de DATE se guardan como valores de fecha de calendario juliano con la clase de almacenamiento REAL. Por ello, las operaciones de ordenación y comparación funcionan del modo esperado.

XML o XMLList

Una columna que utiliza afinidad XML o XMLList almacena estructuras XML. Cuando el código intenta guardar datos en una columna XML con un parámetro SQLStatement, el motor de ejecución intenta convertir y validar el valor con la función XML() o XMLList() de ActionScript. Si el valor no se puede convertir a XML válido, se produce un error. Si se intenta guardar los datos con un valor de texto SQL literal (por ejemplo, INSERT INTO (col1) VALUES ('Invalid XML (no closing tag)'), el valor no se analiza ni se valida: se asume que está bien expresado. Si se guarda un valor no válido, se devuelve un objeto vacío XML al recuperarlo. Los datos XML y XMLList se almacenan con la clase de almacenamiento TEXT o NULL.

Object

Una columna con afinidad Object almacena objetos complejos de ActionScript o JavaScript, incluidas instancias de la clase Object, así como instancias de subclases de Object como instancias de Array e incluso instancias de clases personalizadas. Los datos de la columna OBJECT están serializados en formato AMF3 y se guardan con la clase de almacenamiento BLOB. Cuando se recupera una valor, se deserializa de AMF3 y se devuelve como una instancia de la clase tal como se guardó. Tenga en cuenta que algunas clases de ActionScript, especialmente los objetos de visualización, no se pueden deserializar como instancias de su tipo de datos original. Antes de guardar una instancia de clase personalizada, debe registrar un apodo para la clase con el método flash.net.registerClassAlias() (o, en Flex, agregando metadatos [RemoteObject] a la declaración de la clase). Asimismo, antes de recuperar los datos debe registrar el mismo apodo para la clase. Cualquier dato que no pueda deserializarse correctamente, bien porque la clase no se puede deserializar inherentemente o porque falta o no coincide un apodo de la clase, se devuelve como un objeto anónimo (una instancia de la clase Object con propiedades y valores que se corresponden con la instancia original tal como se guardó.

NONE

Una columna con afinidad NONE no tiene preferencia sobre una clase de almacenamiento frente a otra. No intenta convertir los datos antes de insertarlos.

Determinación de la afinidad

El tipo de afinidad de una columna se determina mediante el tipo declarado de la columna de la declaración CREATE TABLE. Al determinar el tipo, se aplican las siguientes reglas (no distinguen entre mayúsculas y minúsculas):

  • Si el tipo de datos de la columna contiene alguna de las cadenas "CHAR", "CLOB", "STRI" o "TEXT", dicha columna tiene afinidad TEXT/String. Tenga en cuenta que el tipo VARCHAR contiene la cadena "CHAR" y, por lo tanto, se le asigna afinidad TEXT.

  • Si el tipo de datos de la columna contiene la cadena "BLOB" o si no hay ningún tipo de datos especificado, la columna tiene afinidad NONE.

  • Si el tipo de datos de la columna contiene la cadena "XMLL" la columna tiene afinidad XMLList.

  • Si el tipo de datos es la cadena "XML", la columna tiene afinidad XML.

  • Si el tipo de datos contiene la cadena "OBJE", la columna tiene afinidad Object.

  • Si el tipo de datos contiene la cadena "BOOL", la columna tiene afinidad Boolean.

  • Si el tipo de datos contiene la cadena "DATE", la columna tiene afinidad de datos Date.

  • Si el tipo de datos contiene la cadena "INT" (incluida "UINT"), se le asigna afinidad INTEGER/int.

  • Si el tipo de datos contiene cualquiera de las cadenas "REAL", "NUMB", "FLOA" o "DOUB", la columna tiene afinidad REAL/Number.

  • En caso contrario, la afinidad es NUMERIC.

  • Si se crea una tabla con una declaración CREATE TABLE t AS SELECT... ninguna columna tendrá un tipo de datos especificado y se le dará la afinidad NONE.

Tipos de datos y operadores de comparación

Se admiten los siguientes operadores de comparación binarios =, <, <=, >= y != además de una operación para probar la pertenencia, IN y el operador de comparación ternario BETWEEN. Para obtener más información sobre estos operadores, consulte Operadores.

Los resultados de una comparación dependen de las clases de almacenamiento de los dos valores que se comparan. Cuando se comparan dos valores, se aplican las siguientes reglas:

  • Un valor con clase de almacenamiento NULL sed considera menor que cualquier otro valor (incluidos valores con clase de almacenamiento NULL).

  • Un valor INTEGER o REAL es menor que cualquier otro valor TEXT o BLOB. Cuando se compara un INTEGER o un REAL con otro INTEGER o REAL, se lleva a cabo una comparación numérica.

  • Un valor TEXT es menor que un valor BLOB. Cuando se comparan dos valores TEXT, se lleva a cabo una comparación binaria.

  • Cuando se comparan dos valores BLOB, el resultado siempre se determina mediante una comparación binaria.

El operador ternario BETWEEN siempre se recrea como la expresión binaria equivalente. Por ejemplo, BETWEEN b AND c se recrea como >= b AND a <= c, incluso si esto significa que se deben aplicar distintas afinidades a IN en cada una de las comparaciones necesarias para producir la expresión.

Las expresiones de tipo a IN (SELECT b ....) se gestionan mediante tres reglas enumeradas previamente para comparaciones binarias, es decir, de un modo similar a a = b. Por ejemplo, si b es un valor de columna y a es una expresión, la afinidad de b se aplica a a antes de realizar ninguna comparación. La expresión a IN (x, y, z) se recrea como a = +x OR a = +y OR a = +z. Los valores a la derecha del operador IN (los valores x, y y z en este ejemplo) se consideran expresiones incluso si se encuentran en los valores de columna. Si el valor a la izquierda del operador IN es una columna, se utiliza la afinidad de dicha columna. Si el valor es una expresión, no se produce ninguna conversión.

El modo en que se realizan las comparaciones también se puede ver afectado al utilizar una cláusula COLLATE. Para obtener más información, consulte COLLATE.

Tipos de datos y operadores matemáticos

Para cada uno de los operadores matemáticos admitidos, *, /, %, + and -, se aplica la afinidad numérica a todos los operandos antes de evaluar la expresión. Si algún operando no se puede convertir a la clase de almacenamiento NUMERIC correctamente, la expresión produce como resultado NULL.

Cuando se utiliza el operador de concatenación ||, cada operando se convierte a la clase de almacenamiento TEXT antes de evaluar la expresión. Si algún operando no se puede convertir a la clase de almacenamiento TEXT, el resultado de la expresión es NULL. Esta imposibilidad de convertir el valor puede aparecer en dos situaciones: si el valor del operando es NULL o si se trata de un BLOB que contiene una clase de almacenamiento no TEXT.

Tipos de datos y ordenación

Cuando se ordenan valores mediante una cláusula ORDER BY los valores con clase de almacenamiento NULL tienen preferencia. Luego van los valores INTEGER y REAL, en orden numérico, seguidos de los valores TEXT en orden binario o basados en la intercalación especificada (BINARY o NOCASE). Por último, van los valores BLOB en orden binario. No se producen conversiones de clase de almacenamiento antes de la ordenación.

Tipos de datos y agrupación

Cuando se agrupan valores con la cláusula GROUP BY, los valores con distintas clases de almacenamiento se consideran diferentes. Una excepción son los valores INTEGER y REAL, que se consideran iguales aunque sean equivalentes numéricamente. No se aplica ninguna afinidad a ningún valor como resultado de una cláusula GROUP BY.

Tipos de datos y declaraciones SELECT compuestas

Los operadores SELECT compuestosUNION, INTERSECT y EXCEPT llevan a cabo comparaciones implícitas entre valores. Antes de realizar estas comparaciones, es posible aplicar una afinidad a cada valor. Esa misma afinidad (si existe) se aplica a todos los valores que se puedan devolver en una sola columna del conjunto de resultados del SELECT compuesto. La afinidad aplicada es la de la columna devuelta por la declaración SELECT del primer componente que tenga un valor de columna (y no cualquier otra expresión) en dicha posición. Si, en una columna SELECT compuesta dada, ninguna de las declaraciones SELECT del componente devuelven un valor de columna, no se aplica ninguna afinidad a los valores de dicha columna antes de la comparación.