Administrar datos ntext, text e image

Nota importanteImportante

Esta característica se quitará en una versión futura de Microsoft SQL Server. Evite utilizar esta característica en nuevos trabajos de desarrollo y tenga previsto modificar las aplicaciones que actualmente la utilizan. En su lugar, utilice los tipos de datos varchar(max), nvarchar(max) y varbinary(max). Para obtener más información, vea Usar tipos de datos de valores grandes.

Los tipos de datos ntext, text e image de SQL Server pueden contener cantidades extremadamente grandes de datos (hasta 2 GB) en un único valor. Normalmente, un valor individual de este tipo de datos es mayor de lo que una aplicación puede recuperar en un paso; algunos valores pueden ser incluso mayores que la memoria virtual disponible en el cliente. Esto significa que, para recuperarlos, normalmente se necesitan llevar a cabo procedimientos especiales.

Si un tipo de datos ntext, text e image no es mayor que una cadena Unicode (4.000 caracteres), una cadena de caracteres (8.000 caracteres) o una cadena binaria (8.000 bytes), se puede hacer referencia a su valor en las instrucciones SELECT, UPDATE e INSERT casi de la misma forma que se utiliza con los tipos de datos más pequeños. Por ejemplo, se puede hacer referencia a una columna ntext con un valor pequeño en una lista de selección de una instrucción SELECT del mismo modo que se hace referencia a una columna nvarchar. Se deben tener en cuenta algunas restricciones, como, por ejemplo, no poder hacer referencia directamente a una columna ntext, text o image en una cláusula WHERE. Estas columnas se pueden incluir en una cláusula WHERE como parámetros de una función que devuelve otro tipo de datos, como ISNULL, SUBSTRING o PATINDEX, o bien en una expresión IS NULL, IS NOT NULL o LIKE.

Controlar valores de datos mayores

Sin embargo, cuando los valores de datos ntext, text e image son mayores, deben tratarse de bloque en bloque. Tanto Transact-SQL como las API de bases de datos contienen funciones que permiten a las aplicaciones funcionar con los datos ntext, text e image bloque a bloque.

Las API de bases de datos siguen un patrón común en cuanto a la forma en la que tratan las columnas grandes de tipo ntext, text e image:

  • Para leer una columna con datos de gran tamaño, la aplicación simplemente incluye la columna ntext, text o image en una lista de selección y, a continuación, enlaza la columna con una variable de programa que sea suficientemente grande para contener un bloque razonable de los datos. La aplicación ejecuta entonces la instrucción y usa una función o método de la API para recuperar los datos en la variable enlazada, de bloque en bloque.

  • Para escribir una columna grande, la aplicación ejecuta una instrucción INSERT o UPDATE con un marcador de parámetro (?) en el lugar del valor que se va a colocar en la columna ntext, text o image. El marcador de parámetro (o parámetro, en el caso de ADO) se enlaza a una variable de programa suficientemente grande para contener los bloques de datos. La aplicación entra en un bucle donde primero mueve el siguiente conjunto de datos a la variable enlazada y luego llama a una función o método de la API para escribir ese bloque de datos. Esto se repite hasta que se hayan enviado todos los datos.

Utilizar text in row

En SQL Server, los usuarios pueden habilitar una opción text in row en una tabla para que ésta pueda almacenar datos text, ntext o image en su fila de datos.

Para habilitar la opción, ejecute el procedimiento almacenado sp_tableoption y especifique text in row como nombre de la opción y on como valor. El tamaño máximo predeterminado que se puede almacenar en una fila para un objeto BLOB (objeto binario grande), como los datos text, ntext o image, es de 256 bytes, pero los valores pueden oscilar entre 24 y 7000. Para especificar un tamaño máximo distinto del predeterminado, especifique un número entero de este intervalo como valor de la opción.

Las cadenas text, ntext e image se almacenan en la fila de datos si se cumplen las siguientes condiciones:

  • La opción text in row está habilitada.

  • La longitud de la cadena es menor que el límite especificado en @OptionValue.

  • Hay suficiente espacio disponible en la fila de datos.

Cuando se almacenan cadenas BLOB en la fila de datos, la lectura o escritura de cadenas text, ntext o image puede ser tan rápida como la lectura o escritura de cadenas de caracteres y binarias. SQL Server no necesita obtener acceso a páginas independientes para leer o escribir la cadena BLOB.

Si una cadena text, ntext o image es mayor que el límite especificado o que el espacio que hay disponible en la fila, lo que se almacena en la fila son punteros. Las condiciones para almacenar las cadenas BLOB en la fila siguen siendo válidas, aunque debe haber espacio suficiente para almacenar los punteros en la fila de datos.

Para obtener más información, vea sp_tableoption (Transact-SQL).

Utilizar punteros de texto

A menos que se especifique la opción text in row, las cadenas text, ntext e image se almacenan fuera de la fila de datos; en las filas de datos sólo residen los punteros de texto a estas cadenas. Los punteros de texto apuntan al nodo raíz de un árbol compuesto de punteros internos, que se asignan a las páginas en las que se almacenan realmente los fragmentos de cadena (de datos text, ntext e image).

Los punteros de texto de fila de SQL Server 2000 son diferentes de los punteros de texto de versiones anteriores de SQL Server. Los punteros de texto de fila se comportan como identificadores de archivos para los datos BLOB; los punteros de texto anteriores funcionan como direcciones relativas a los datos BLOB. En consecuencia, cuando utilice punteros de texto de fila deberá tener en cuenta las siguientes características:

Nota importanteImportante

Aunque en un cursor se permite texto de fila, no se permite un puntero de texto de fila. SQL Server devuelve el error 328 si intenta declarar un cursor que contenga un puntero de texto de fila.

  1. Número

    Se permite un máximo de 1024 punteros de texto de fila activos por transacción y por base de datos.

  2. Bloqueo

    Cuando un usuario obtiene un puntero de texto activo, SQL Server 2000 bloquea la fila de datos y garantiza que ningún otro usuario modifique o elimine la fila mientras el primer usuario tiene el puntero de texto. El bloqueo se libera cuando el puntero de texto deja de ser válido. Para invalidar un puntero de texto, utilice sp_invalidate_textptr (Transact-SQL).

    No se puede utilizar un puntero de texto para actualizar valores BLOB cuando el nivel de aislamiento de la transacción es de lectura no confirmada o cuando la base de datos está en modo de sólo lectura.

    SQL Server 2000 no bloquea la fila de datos si la base de datos está en modo de usuario único.

    Como ejemplo, vea la tabla siguiente:

    CREATE TABLE t1 (c1 int, c2 text)
    EXEC sp_tableoption 't1', 'text in row', 'on'
    INSERT t1 VALUES ('1', 'a')
    

    La transacción siguiente se completará correctamente:

    INSERT t1 VALUES ('1','This is text.')
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
    GO
    BEGIN TRAN
    DECLARE @ptr varbinary(16)
    SELECT @ptr = textptr(c2)
    FROM t1
    WHERE c1 = 1;
    READTEXT t1.c2 @ptr 0 5
    COMMIT TRAN
    GO
    

    La transacción siguiente producirá un error:

    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
    GO
    BEGIN TRAN
    DECLARE @ptr varbinary(16)
    SELECT @ptr = textptr(c2)
    FROM t1
    WHERE c1 = 1
    WRITETEXT t1.c2 @ptr 'xx'
    COMMIT TRAN
    GO
    
  3. Duración

    Los punteros de texto de fila sólo son válidos en una transacción. Cuando una transacción se confirma, el puntero de texto deja de ser válido.

    Dentro de una transacción, los punteros de texto de fila pueden dejar de ser válidos cuando tienen lugar las acciones siguientes:

    • La sesión termina.

    • La fila de datos se elimina en la misma transacción. Otras transacciones no pueden eliminar una fila de datos debido al bloqueo que se obtiene en ella.

    • Se cambia el esquema de la tabla en la que reside el puntero de texto. Entre las acciones de cambio de esquema que invalidan los punteros de texto se incluyen: crear o quitar un índice clúster, modificar o quitar la tabla, truncar la tabla, cambiar la opción text in row a través de sp_tableoption y ejecutar sp_indexoption.

    Utilizando el ejemplo anterior, el script siguiente funcionará en versiones anteriores de SQL Server, pero generará un error en SQL SQL Server 2000.

    DECLARE @ptrval varbinary(16)
    PRINT 'get error here'
    SELECT @ptrval = TEXTPTR(c2)
    FROM t1
    WHERE c1 = 1
    READTEXT t1.c2 @ptrval 0 1
    

    En SQL Server 2000, el puntero de texto de fila debe utilizarse dentro de una transacción:

    BEGIN TRAN
    DECLARE @ptrval varbinary(16)
    SELECT @ptrval = TEXTPTR(c2)
    FROM t1
    WHERE c1 = 1
    READTEXT t1.c2 @ptrval 0 1
    COMMIT
    
  4. Texto NULL

    Puede obtener un puntero de texto de fila para texto NULL generado por INSERT. Anteriormente, sólo era posible obtener punteros de texto después de actualizar un objeto BLOB a NULL.

    Por ejemplo, el código siguiente no funciona en SQL Server 7.0, pero sí en SQL Server 2000.

    SET TRANSACTION ISOLATION LEVEL READ COMMITTED
    GO
    INSERT INTO t1 VALUES (4, NULL)
    BEGIN TRAN
    DECLARE @ptrval VARBINARY(16)
    SELECT @ptrval = TEXTPTR(c2)
    FROM t1
    WHERE c1 = 4
    WRITETEXT t1.c2 @ptrval 'x4'
    COMMIT
    

    En SQL Server 7.0 debe hacerse lo siguiente:

    INSERT INTO t1 VALUES (4, NULL)
    UPDATE t1 
       SET c2 = NULL 
       WHERE c1 = 4
    DECLARE @ptrval VARBINARY(16)
    SELECT @ptrval = TEXTPTR(c2)
    FROM t1
    WHERE c1 = 4
    WRITETEXT t1.c2 @ptrval 'x4'
    

Esta tabla resume las diferencias.

Diferencia

Puntero de texto en fila

Puntero no de texto en fila

Número

Máximo de 1024 activos por transacción y por base de datos.

Sin límite.

Bloqueo

La fila de datos tiene un bloqueo tipo S hasta que el puntero deja de ser válido.

No se obtienen bloqueos cuando el estado de la transacción es 'lectura no confirmada' o la base de datos se encuentra en modo de 'usuario único' o 'sólo lectura'.

La fila de datos no se bloquea.

Duración

Deja de ser válido al final de la transacción o sesión, cuando se elimina una fila o cuando se cambia el esquema de la tabla.

Deja de ser válido cuando se elimina la fila.

Texto NULL

Puede obtenerse inmediatamente después de insertar el texto NULL.

Sólo puede obtenerse después de actualizar.

Utilizar datos ntext, text e image con las API de bases de datos

A continuación se muestra un resumen de la forma en que las API de bases de datos tratan los datos ntext, text e image:

  • ADO

    ADO puede asignar columnas o parámetros ntext, text o image a un objeto Field o Parameter. Use el método GetChunk para recuperar los datos de bloque en bloque y el método AppendChunk para escribir datos también de bloque en bloque.

  • OLE DB

    OLE DB usa la interfaz ISequentialStream para admitir los tipos de datos ntext, text e image. El método ISequentialStream::Read lee los datos de gran tamaño de bloque en bloque e ISequentialStream::Write los escribe en la base de datos del mismo modo. Para obtener más información, vea BLOB y objetos OLE

  • ODBC

    ODBC tiene una característica llamada "datos en ejecución" para tratar con los tipos de datos de ODBC en el caso de los datos largos: SQL_WLONGVARCHAR (ntext), SQL_LONGVARCHAR (text) y SQL_LONGVARBINARY (image).Estos tipos de datos se enlazan a una variable de programa. A continuación, se llama a SQLGetData para recuperar los datos grandes de bloque en bloque y a SQLPutData para enviar los datos grandes también de bloque en bloque. Para obtener más información, vea Administrar columnas de texto e imagen.

  • DB-Library

    Las aplicaciones de DB-Library también vinculan columnas ntext, text e image a variables de programa. La función dbtxtptr de DB-Library se usa para obtener un puntero a la ubicación de la columna de gran tamaño en la base de datos. dbreadtext se usa para leer los datos grandes de bloque en bloque. Las funciones como dbwritetext, dbupdatetext y dbmoretext se usan para escribir los datos grandes de bloque en bloque.

    Nota

    No se admite el acceso a texto de fila con DB-Library.

Para obtener más información, vea Funciones de texto e imagen (Transact-SQL).