Compartilhar via


Programação de procedimentos armazenados estendidos do Mecanismo de Banco de Dados

Aplica-se: SQL Server

Importante

Esse recurso será removido em uma versão futura do SQL Server. Evite usar esse recurso em desenvolvimentos novos e planeje modificar os aplicativos que atualmente o utilizam. Em vez disso, use a integração CLR.

Como funcionam os procedimentos armazenados estendidos

O processo pelo qual um procedimento armazenado estendido funciona é o seguinte:

  1. Quando um cliente executa um procedimento armazenado estendido, a solicitação é transmitida no formato TDS (fluxo de dados tabulares) ou SOAP (Simple Object Access Protocol) do aplicativo cliente para o SQL Server.

  2. O SQL Server procura a DLL associada ao procedimento armazenado estendido e carrega a DLL se ela ainda não estiver carregada.

  3. SQL Server chama o procedimento armazenado estendido solicitado (implementado como uma função dentro da DLL).

  4. O procedimento armazenado estendido passa conjuntos de resultados e parâmetros de retorno de volta ao servidor por meio da API de procedimento armazenado estendido.

No passado, o Open Data Services era usado para gravar aplicativos de servidor, como gateways para ambientes de banco de dados que não fossem o SQL Server. O SQL Server não dá suporte às partes obsoletas da API do Open Data Services. A única parte da API original do Open Data Services ainda com suporte do SQL Server são as funções de procedimento armazenado estendidas, portanto, a API foi renomeada para API de Procedimento Armazenado Estendido.

Com o surgimento de consultas distribuídas e integração CLR, a necessidade de aplicativos de API de Procedimento Armazenado Estendido foi amplamente substituída.

Se você tiver aplicativos de gateway existentes, não poderá usar o que acompanha o opends60.dll SQL Server para executar os aplicativos. Os aplicativos de gateway já não são mais suportados.

Procedimentos armazenados estendidos versus integração CLR

A integração CLR fornece uma alternativa mais robusta para escrever lógica do lado do servidor que era difícil de expressar ou impossível de escrever no Transact-SQL. Em versões anteriores do SQL Server, os XPs (procedimentos armazenados estendidos) forneciam o único mecanismo disponível para os desenvolvedores de aplicativos de banco de dados escreverem esse código.

Com a integração CLR, a lógica que costumava ser escrita na forma de procedimentos armazenados geralmente é melhor expressa como funções com valor de tabela, que permitem que os resultados construídos pela função sejam consultados em SELECT instruções inserindo-os na FROM cláusula.

Para obter mais informações, consulte Visão geral da integração CLR.

Características de execução de procedimentos armazenados estendidos

A execução de um procedimento armazenado estendido tem as seguintes características:

  • A função de procedimento armazenado estendido é executada no contexto de segurança do SQL Server.

  • A função de procedimento armazenado estendido é executada no espaço de processo do SQL Server.

  • O thread associado com a execução do procedimento armazenado estendido é igual ao usado na conexão do cliente.

Importante

Antes de adicionar procedimentos armazenados estendidos ao servidor e conceder permissões de execução a outros usuários, o administrador do sistema deve examinar minuciosamente cada procedimento armazenado estendido para garantir que ele não contenha código prejudicial ou mal-intencionado.

Depois que a DLL de procedimento armazenado estendido é carregada, a DLL permanece carregada no espaço de endereço do servidor até que o SQL Server seja interrompido ou o administrador descarregue explicitamente a DLL usando DBCC <DLL_name> (FREE).

O procedimento armazenado estendido pode ser executado no Transact-SQL como um procedimento armazenado usando a EXECUTE instrução:

EXECUTE @retval = xp_extendedProcName @param1, @param2 OUTPUT;

Parâmetros

@ retval

Um valor retornado.

@ param1

Um parâmetro de entrada.

@ param2

Um parâmetro de entrada/saída.

Cuidado

Os procedimentos armazenados estendidos oferecem aprimoramentos de desempenho e estendem a funcionalidade do SQL Server. No entanto, como a DLL de procedimento armazenado estendido e o SQL Server compartilham o mesmo espaço de endereço, um procedimento problemático pode afetar negativamente o funcionamento do SQL Server. Embora as exceções geradas pela DLL de procedimento armazenado estendido sejam tratadas pelo SQL Server, é possível danificar as áreas de dados do SQL Server. Como precaução de segurança, somente os administradores de sistema do SQL Server podem adicionar procedimentos armazenados estendidos ao SQL Server. Esses procedimentos devem ser extensivamente testados antes ser instalados.

Enviar conjuntos de resultados para o servidor com a API de Procedimento Armazenado Estendido

Ao enviar um conjunto de resultados para o SQL Server, o procedimento armazenado estendido deve chamar a API apropriada da seguinte maneira:

  • A srv_sendmsg função pode ser chamada em qualquer ordem antes ou depois de todas as linhas (se houver) estarem com srv_sendrow. Todas as mensagens devem ser enviadas ao cliente antes que o status de conclusão seja enviado com srv_senddone.

  • A srv_sendrow função é chamada uma vez para cada linha enviada ao cliente. Todas as linhas devem ser enviadas ao cliente antes que quaisquer mensagens, valores de status ou status de conclusão sejam enviados com srv_sendmsg, o srv_status argumento de srv_pfield, ou srv_senddone.

  • Enviar uma linha que não tem todas as suas colunas definidas faz srv_describe com que o aplicativo gere uma mensagem de erro informativa e retorne FAIL ao cliente. Nesse caso, a linha não é enviada.

Criar procedimentos armazenados estendidos

Um procedimento armazenado estendido é uma função C/C++ com um protótipo:

SRVRETCODE xp_extendedProcName ( SRVPROC *);

O uso do prefixo xp_ é opcional. Os nomes de procedimento armazenado estendidos diferenciam maiúsculas de minúsculas quando referenciados em instruções Transact-SQL, independentemente da página de código/ordem de classificação instalada no servidor. Quando você compila uma DLL:

  • Se um ponto de entrada for necessário, escreva uma DllMain função.

    Esta função é opcional. Se você não fornecê-lo no código-fonte, o compilador vinculará sua própria versão, que não faz nada além de retornar TRUE. Se você fornecer uma DllMain função, o sistema operacional chamará essa função quando um thread ou processo for anexado ou desanexado da DLL.

  • Todas as funções chamadas de fora da DLL (todas as Efunctions do procedimento armazenado estendido) devem ser exportadas.

    Você pode exportar uma função listando seu nome na EXPORTS seção de um .def arquivo ou pode prefixar o nome da função no código-fonte com __declspec(dllexport), uma extensão do compilador da Microsoft (__declspec() começa com dois sublinhados).

Estes arquivos são necessários para criar uma DLL de procedimento armazenado estendido.

Arquivo Descrição
srv.h Arquivo de cabeçalho da API do Procedimento Armazenado Estendido
opends60.lib Importar biblioteca para opends60.dll

Para criar uma DLL de procedimento armazenado estendido, crie um projeto do tipo Biblioteca de Vínculo Dinâmico. Para obter mais informações sobre a criação de uma DLL, consulte a documentação do ambiente de desenvolvimento.

Todas as DLLs de procedimento armazenado estendidas devem implementar e exportar a seguinte função:

__declspec(dllexport) ULONG __GetXpVersion()
{
   return ODS_VERSION;
}

__declspec(dllexport) é uma extensão do compilador específica da Microsoft. Se o compilador não der suporte a essa diretiva, você deverá exportar essa função em seu DEF arquivo na EXPORTS seção.

Quando o SQL Server é iniciado com o sinalizador -T260 de rastreamento ou se um usuário com privilégios de administrador do sistema é executado DBCC TRACEON (260)e se a DLL de procedimento armazenado estendido não oferece suporte a __GetXpVersion(), a seguinte mensagem de aviso é impressa no log de erros (__GetXpVersion() começa com dois sublinhados).

Error 8131: Extended stored procedure DLL '%' does not export __GetXpVersion().

Se a DLL de procedimento armazenado estendido for exportada __GetXpVersion(), mas a versão retornada pela função for menor que a versão exigida pelo servidor, uma mensagem de aviso informando a versão retornada pela função e a versão esperada pelo servidor será impressa no log de erros. Se você receber essa mensagem, está retornando um valor incorreto de __GetXpVersion(), ou está compilando com uma versão mais antiga do srv.h.

Observação

SetErrorMode, uma função Win32, não deve ser chamada em procedimentos armazenados estendidos.

Os procedimentos armazenados estendidos de longa execução devem ser chamados srv_got_attention periodicamente, para que o procedimento possa ser encerrado se a conexão for interrompida ou o lote for anulado.

Para depurar uma DLL de procedimento armazenado estendida, copie-a para o diretório do SQL Server \Binn . Para especificar o executável para a sessão de depuração, insira o caminho e o nome do arquivo executável do SQL Server (por exemplo, C:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\Binn\sqlservr.exe). Para obter informações sobre sqlservr argumentos, consulte Aplicativo sqlservr.

Adicionar um procedimento armazenado estendido ao SQL Server

Uma DLL que contém funções de procedimento armazenado estendidas atua como uma extensão para SQL Server. Para instalar a DLL, copie o arquivo para um diretório, como aquele que contém os arquivos DLL padrão do SQL Server (C:\Program Files\Microsoft SQL Server\MSSQL16.0.<x>\MSSQL\Binn por padrão).

Depois que a DLL de procedimento armazenado estendido é copiada para o servidor, um administrador de sistema do SQL Server deve registrar no SQL Server cada função de procedimento armazenado estendido na DLL. Isso é feito usando o procedimento armazenado do sp_addextendedproc sistema.

Importante

O administrador do sistema deve examinar minuciosamente um procedimento armazenado estendido para garantir que ele não contenha código prejudicial ou mal-intencionado antes de adicioná-lo ao servidor e conceder permissões de execução a outros usuários. Valide todas as entradas de usuário. Não concatene a entrada do usuário antes de validá-la. Nunca execute um comando construído por uma entrada de usuário inválida.

O primeiro parâmetro de sp_addextendedproc especifica o nome da função e o segundo parâmetro especifica o nome da DLL na qual essa função reside. Você deve especificar o caminho completo da DLL.

Observação

As DLLs existentes que não foram registradas com um caminho completo não funcionam após a atualização para o SQL Server 2005 (9.x) ou uma versão posterior. Para corrigir o problema, use sp_dropextendedproc para cancelar o registro da DLL e, em seguida, registre-a novamente especificando sp_addextendedproc, o caminho completo.

O nome da função especificada em sp_addextendedproc deve ser exatamente igual, inclusive maiúsculas e minúsculas, ao nome da função na DLL. Por exemplo, esse comando registra uma função xp_hello, localizada em uma dll chamada xp_hello.dll, como um procedimento armazenado estendido do SQL Server:

sp_addextendedproc 'xp_hello', 'c:\Program Files\Microsoft SQL Server\MSSQL13.0.MSSQLSERVER\MSSQL\Binn\xp_hello.dll';

Se o nome da função especificada em sp_addextendedproc não corresponder exatamente ao nome da função na DLL, o novo nome será registrado no SQL Server, mas o nome não poderá ser usado. Por exemplo, embora xp_Hello esteja registrado como um procedimento armazenado estendido do SQL Server localizado no xp_hello.dll, o SQL Server não poderá encontrar a função na DLL se você usar xp_Hello para chamar a função posteriormente.

-- Register the function (xp_hello) with an initial upper case
sp_addextendedproc 'xp_Hello', 'c:\xp_hello.dll';

-- Use the newly registered name to call the function
DECLARE @txt VARCHAR(33);
EXEC xp_Hello @txt OUTPUT;

Aqui está a mensagem de erro:

Server: Msg 17750, Level 16, State 1, Procedure xp_Hello, Line 1
Could not load the DLL xp_hello.dll, or one of the DLLs it references. Reason: 127(The specified procedure could not be found.).

Se o nome da função especificada em sp_addextendedproc corresponder exatamente ao nome da função na DLL e a ordenação da instância do SQL Server não diferenciar maiúsculas de minúsculas, o usuário poderá chamar o procedimento armazenado estendido usando qualquer combinação de letras minúsculas e maiúsculas do nome.

-- Register the function (xp_hello)
sp_addextendedproc 'xp_hello', 'c:\xp_hello.dll';

-- The following example succeeds in calling xp_hello
DECLARE @txt VARCHAR(33);
EXEC xp_Hello @txt OUTPUT;

DECLARE @txt VARCHAR(33);
EXEC xp_HelLO @txt OUTPUT;

DECLARE @txt VARCHAR(33);
EXEC xp_HELLO @txt OUTPUT;

Quando o agrupamento da instância do SQL Server diferencia maiúsculas de minúsculas, o SQL Server não poderá chamar o procedimento armazenado estendido se o procedimento for chamado com maiúsculas e minúsculas diferentes. Isso é verdadeiro mesmo que ele tenha sido registrado com exatamente o mesmo nome e ordenação que a função na DLL.

-- Register the function (xp_hello)
sp_addextendedproc 'xp_hello', 'c:\xp_hello.dll';

-- The following example results in an error
DECLARE @txt VARCHAR(33);
EXEC xp_HELLO @txt OUTPUT;

Aqui está a mensagem de erro:

Server: Msg 2812, Level 16, State 62, Line 1

Você não precisa parar e reiniciar o SQL Server.

Consultar procedimentos armazenados estendidos instalados no SQL Server

Um usuário autenticado do SQL Server pode exibir os procedimentos armazenados estendidos definidos no momento e o nome da DLL à qual cada um pertence executando o procedimento do sp_helpextendedproc sistema. Por exemplo, o exemplo a seguir retorna a DLL à qual xp_hello pertence:

sp_helpextendedproc 'xp_hello';

Se sp_helpextendedproc for executado sem especificar um procedimento armazenado estendido, todos os procedimentos armazenados estendidos e suas DLLs serão exibidos.

Remover um procedimento armazenado estendido do SQL Server

Para descartar cada função de procedimento armazenado estendido em uma DLL de procedimento armazenado estendido definida pelo usuário, um administrador do sistema SQL Server deve executar o procedimento armazenado do sp_dropextendedproc sistema, especificando o nome da função e o nome da DLL na qual essa função reside. Por exemplo, esse comando remove a função xp_hello, localizada em uma DLL nomeada xp_hello.dll, do SQL Server:

sp_dropextendedproc 'xp_hello';

sp_dropextendedproc não descarta procedimentos armazenados estendidos do sistema. Em vez disso, o administrador do sistema deve negar EXECUTE permissão no procedimento armazenado estendido para a função pública .

Descarregar uma DLL de procedimento armazenado estendida

O SQL Server carrega uma DLL de procedimento armazenado estendida assim que uma chamada é feita para uma das funções da DLL. A DLL permanece carregada até que o servidor seja desligado ou até que o administrador do sistema use a DBCC instrução para descarregá-la. Por exemplo, este comando descarrega o xp_hello.dll, permitindo que o administrador do sistema copie uma versão mais recente deste arquivo para o diretório sem desligar o servidor:

DBCC xp_hello(FREE);