Share via


Gerenciando dados ntext, texto e imagem

Observação importanteImportante

Esse recurso será removido em uma versão futura do Microsoft SQL Server. Evite usar esse recurso em desenvolvimentos novos e planeje modificar os aplicativos que atualmente o utilizam. Em vez disso, use os tipos de dados varchar(max), nvarchar(max) e varbinary(max). Para obter mais informações, consulte Usando tipos de dados de valor grande.

Os tipos de dados SQL Serverntext, text e image têm a capacidade de conter quantidades extremamente altas de dados, até 2 GB, em um único valor. Geralmente, um único valor de dados é maior de que o valor que pode ser recuperado por um aplicativo em uma etapa, alguns valores podem ser maiores de que a memória virtual disponível para o cliente. Assim sendo, etapas especiais são necessárias para recuperar esses valores.

Se um valor de dados ntext, text e image não for mais longo de que um Unicode, 4.000 caracteres, caractere, 8.000 caracteres; ou uma cadeia de caracteres binária, 8.000 bytes, o valor pode ser referenciado nas instruções SELECT, UPDATE e INSERT da mesma forma dos tipos de dados menores. Por exemplo, uma coluna ntext com um valor curto pode ser referenciada em uma lista de seleção da instrução SELECT da mesma maneira em que uma coluna nvarchar é referenciada. Algumas restrições que devem ser observadas, como não poder referenciar diretamente uma coluna ntext, text, ou image em uma cláusula WHERE. Essas colunas podem ser incluídas em uma cláusula WHERE como parâmetros de função que retorna outro tipo de dados, como ISNULL, SUBSTRING ou PATINDEX, ou em uma expressão IS NULL, IS NOT NULL, ou LIKE.

Lidando com valores de dados maiores

Porém, quando os valores dos dados ntext, text e image ficam maiores, eles devem ser tratados com base em bloco por bloco. O Transact-SQL e as APIs do banco de dados contêm funções que fazem com que os aplicativos trabalhem com dados ntext, text e image de bloco por bloco.

As APIs do banco de dados seguem um padrão comum da maneira que elas tratam as colunas compridas ntext, text e image:

  • Para ler uma coluna longa, o aplicativo simplesmente inclui a coluna ntext, text ou image em uma lista de seleção e, em seguida, associa a coluna a uma variável de programa grande o suficiente para conter um bloco razoável de dados. O aplicativo executa então a instrução e usa um método ou uma função de API para recuperar os dados na variável associada, um bloco por vez.

  • Para gravar uma coluna comprida, o aplicativo executa a instrução INSERT ou UPDATE com um marcador de parâmetros (?) ao invés do valor a ser colocado na coluna ntext, text ou image. O marcador de parâmetros (ou parâmetro no caso de ADO) é associado a uma variável de programa grande o suficiente para conter os blocos de dados. O aplicativo vai para um loop, no qual, primeiro, ele move o conjunto seguinte de dados para a variável associada e, em seguida, chama um método ou função de API para gravar aquele bloco de dados. Isto é repetido até que todo o valor de dados seja enviado.

Usando texto em linha

No SQL Server, os usuários podem habilitar a opção text in row em uma tabela de modo a poder armazenar os dados text, ntext ou image na sua linha de dados.

Para habilitar a opção, execute o procedimento armazenado sp_tableoption, especificando text in row como o nome da opção e on como o valor da opção. O tamanho máximo padrão que pode ser armazenado em uma linha para o BLOB, objeto binário grande como os dados text, ntext ou image é de 256 bytes, mas os valores podem variar de 24 a 7000. Para especificar o tamanho máximo diferente do padrão, especifique um inteiro dentro da faixa como um valor de opção.

As cadeias de caracteres text, ntext ou image serão armazenadas na linha de dados se as seguintes condições se aplicarem:

  • text in row estiver habilitado.

  • O comprimento da cadeia de caracteres é mais curto que o limite especificado em @OptionValue

  • Há bastante espaço disponível na linha de dados.

Quando cadeias BLOB são armazenadas na linha de dados, ler e gravar as cadeias text, ntext ou image podem ser tão rápidos quanto ler ou gravar cadeias binárias ou de caracteres. O SQL Server não tem que acessar páginas separadas para ler ou gravar a cadeia BLOB.

Se uma cadeia de caracteres text, ntext ou image for maior que o limite especificado ou o espaço disponível na linha, os ponteiros serão armazenados na linha, em substituição. As condições para armazenar as cadeias BLOB na linha, ainda assim se aplicam: deve haver espaço suficiente na linha de dados para conter os ponteiros.

Para obter mais informações, consulte sp_tableoption (Transact-SQL).

Usando ponteiros de texto

A menos que a opção text in row esteja especificada, as cadeias de caracteres text, ntext ou image serão armazenadas fora da linha de dados, somente os ponteiros de texto para essas cadeias residem nas linhas de dados. Os ponteiros de texto apontam para o nó raiz de uma árvore construída por ponteiros internos que mapeiam as páginas nas quais os fragmentos das cadeias de caracteres dos dados text, ntext e image estão, de fato, armazenados.

Os ponteiros de texto em linha no SQL Server 2000 são diferentes dos ponteiros de texto nas versões anteriores do SQL Server. Os ponteiros de texto em linha se comportam como tratadores de arquivo para os dados BLOB; ponteiros de texto mais antigos funcionam como endereços para os dados BLOB. Assim, ao usar ponteiros de texto de linha, lembre das seguintes características:

Observação importanteImportante

Embora o texto em linha seja permitido em um cursor, um ponteiro de texto em linha não é. O SQL Server retorna o erro 328 se tentar declarar um cursor que contém um ponteiro de texto em linha.

  1. Número

    Um máximo de 1024 ponteiros de texto ativos em linha é permitido por transação por banco de dados.

  2. Bloqueio

    Quando um usuário obtém um ponteiro de texto ativo, o SQL Server 2000 bloqueia a linha de dados e garante que nenhum outro usuário modifique ou exclua a linha enquanto o primeiro usuário tiver o ponteiro de texto. O bloqueio é liberado quando o ponteiro de texto tornar-se inválido. Para invalidar um ponteiro de texto, use sp_invalidate_textptr (Transact-SQL).

    Um ponteiro de texto não pode ser usado para atualizar valores de BLOB quando o nível de isolamento da transação é lido como não confirmado, ou o banco de dados está no modo somente leitura.

    SQL Server 2000 não bloqueia a linha de dados se o banco de dados estiver em modo de usuário único.

    Para ilustrar, determinada a tabela a seguir:

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

    A transação seguinte será bem-sucedida:

    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
    

    A transação a seguir falhará:

    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. Duração

    Os ponteiros de texto em linha serão válidos somente em uma transação. Quando uma transação for confirmada, o ponteiro de texto torna-se inválido.

    Em uma transação, os ponteiros de texto em linha podem ser invalidados quando qualquer uma das ações a seguir ocorre:

    • A sessão termina.

    • A linha de dados é excluída na mesma transação. (Outras transações não podem excluir uma linha de dados devido ao bloqueio obtido.)

    • O esquema de uma tabela na qual o ponteiro de texto reside é alterado. As ações de alteração de esquema que invalidam os ponteiros de texto incluem: a criação ou o descarte de índice cluster, alteração ou descarte de tabela, truncamento de tabela, alteração na opção text in row por meio da sp_tableoption e execução do sp_indexoption.

    Usando o exemplo anterior, o script a seguir funcionaria em versões anteriores do SQL Server, mas geraria um erro no 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
    

    No SQL Server 2000, o ponteiro de texto em linha deve ser usado dentro de uma transação:

    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

    Você pode obter um ponteiro de texto em linha em texto NULL gerado por INSERT. Anteriormente, você só podia obter ponteiros de texto após atualizar um BLOB para NULL.

    Por exemplo, o código a seguir não funciona no SQL Server 7.0, mas funciona no 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
    

    No SQL Server 7.0, você deve fazer o seguinte:

    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 tabela resume as diferenças.

Diferença

ponteiro de texto em linha

Sem ponteiro de texto em linha

Número

Máximo de 1024 ativos por transação por banco de dados.

Ilimitado.

Bloqueio

Linha de dados é bloqueada S até que o ponteiro torna-se inválido.

Os bloqueios não são obtidos quando a transação for 'leitura não confirmada', ou o banco de dados for 'único usuário' ou no modo 'somente leitura'.

A linha de dados não está bloqueada.

Duração

Torna-se inválida no final da transação ou da sessão, quando uma linha for excluída ou o esquema da tabela for alterado.

Torna-se inválido quando a linha for excluída.

Texto NULL

Direito alcançável após a inserção de texto NULL.

Alcançável somente após atualização.

Usando os dados ntext, texto e imagem Dados com as APIs de banco de dados

Esse é um resumo dos modos que as APIs do banco de dados lidam com os dados ntext, text e image:

  • ADO

    ADO pode mapear colunas ou parâmetros ntext, text ou image para um objeto Campo ou Parâmetro. Use o método GetChunk para recuperar os dados de um bloco por vez e o método AppendChunk para gravar os dados de um bloco por vez.

  • OLE DB

    O OLE DB usa a interface ISequentialStream para dar suporte aos tipos de dados ntext, text e image. O método ISequentialStream::Read lê os dados longos de um bloco por vez, e ISequentialStream::Write grava os dados longos no banco de dados um bloco por vez. Para obter mais informações, consulte BLOBs e objetos OLE

  • ODBC

    O ODBC tem um recurso chamado "dados-em-execução" para lidar com os tipos de dados ODBC para dados longos: SQL_WLONGVARCHAR (ntext), SQL_LONGVARCHAR (text) e SQL_LONGVARBINARY (image). Esses tipos de dados estão associados a uma variável de programa. SQLGetData é, então, chamado para recuperar os dados longos um bloco por vez e o SQLPutData é chamado para enviar os dados longos um bloco por vez. Para obter mais informações, consulte Gerenciando colunas de texto e imagem.

  • Biblioteca-DB

    Os aplicativos da Biblioteca-DB também associam as colunas ntext, text e image a variáveis de programa. A função Biblioteca-DB dbtxtptr é usada para obter um ponteiro para o local da ocorrência de coluna longa no banco de dados. O dbreadtext é usado para ler os dados longos um bloco por vez. As funções como dbwritetext, dbupdatetext e dbmoretext são usadas para gravar os dados longos um bloco por vez.

    ObservaçãoObservação

    O acesso do texto em linha com a Biblioteca-DB não terá suporte.

Para obter mais informações, consulte Funções de texto e imagem (Transact-SQL).