Trabalhando com SQL CLR: Stored Procedure – Step 1

Para a nossa primeira funcionalidade da série de artigos sobre SQL CLR, vamos tratar das Stored Procedure (procedimento armazenado), que podem ser utilizadas basicamente para retornar valores, várias consultas e/ou manipular dados.

Depois de criado o projeto SQL CLR, para criarmos uma Stored Procedure com CLR, nós precisaremos adicionar um novo item (“New Item…” ou “Stored Procedure…”) no projeto, determinando também as características básicas deste item, como o nome do arquivo e o template, no casso “Stored Procedure”.

Já com a Stored Procedure adicionada no projeto, partimos para o código da nossa primeira funcionalidade, que é basicamente imprimir um texto qualquer nas mensagens de notificação (como uma chamada ao comando PRINT do SQL).

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

public partial class StoredProcedures
{
    [SqlProcedure]
    public static void Primeiro()
    {
        SqlContext.Pipe.Send("SQL From Hell!!!");
    }
};

E adicionamos o seguinte comando SQL no arquivo script de teste do projeto para executar nossa Stored Procedure.

EXEC Primeiro

Mais informações sobre DEBUG de projetos SQL CLR:
https://sqlfromhell.wordpress.com/2009/10/03/debug-clr

Após o Debug (F5), podemos validar o resultado na caixa de Output do Visual Studio.

O segundo passo para desenvolver nosso procedimento armazenado é a criação de parâmetros, que basicamente consiste na criação de novos parâmetros no método.

using System;
using System.Data;
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

public partial class StoredProcedures
{
    [SqlProcedure]
    public static void Primeiro(SqlString texto)
    {
        SqlContext.Pipe.Send(texto.ToString());
    }
};
EXEC Primeiro 'SQL From Hell!!!'

E após o deploy deste procedimento armazenado, percebemos que o nome do método (ex.: “Primeiro”) também será o nome do procedimento armazenado no banco de dados, assim como os argumentos.

A possibilidade de criarmos sobrecargas uma procedure (dois ou mais métodos com mesmo nome, mas como parâmetros distintos) não é permitida pelo SQL Server, mesmo que seja possível gerar um assembly compilável. Desta forma é recomendado definir nomes adequados para os nomes dos métodos para que não se repitam.

Mas para não ser necessário alterar os nomes dos métodos podemos determinar os nomes das procedures, simplesmente pela customização do atributo SqlProcedure, conforme o exemplo:

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

public partial class StoredProcedures
{
    [SqlProcedure(Name = "USP_Primeiro")]
    public static void Primeiro(SqlString texto)
    {
        SqlContext.Pipe.Send(texto.ToString());
    }
};
EXEC USP_Primeiro 'SQL From Hell!!!'

Que se refletirá no banco de dados, sem necessidade de customização do script SQL de deploy do projeto CLR, conforme demonstrado abaixo:

Mais informações sobre Deploy de projetos SQL CLR:
https://sqlfromhell.wordpress.com/2010/05/15/publicando-assemblies-clr-no-sql-server-pelo-visual-studio/

Assim como podemos customizar o nome dos procedimentos armazenados, também é possível customizar algumas características dos parâmetros do método por meio de atributos (ex.: SqlFacet), conforme demonstrada abaixo a definição da quantidade máxima de 40 caracteres do parâmetro “texto”:

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

public partial class StoredProcedures
{
    [SqlProcedure(Name = "USP_Primeiro")]
    public static void Primeiro
        ([SqlFacet(MaxSize = 40)]SqlString texto)
    {
        SqlContext.Pipe.Send(texto.ToString());
    }
};
EXEC USP_Primeiro 'SQL From Hell!!!'

E como resultado, novamente sem qualquer customização no script SQL de deploy:

Desta forma, também será possível tratar as características dos tipos decimais (ou numéricos), como no exemplo que determinamos um parâmetro decimal de tamanho 10 (precisão), tendo duas casas após a vírgula (escala).

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

public partial class StoredProcedures
{
    [SqlProcedure(Name = "USP_Primeiro")]
    public static void Primeiro
        ([SqlFacet(Precision = 10, Scale = 2)]SqlDecimal valor)
    {
        SqlContext.Pipe.Send(valor.ToString());
    }
};
EXEC USP_Primeiro 12345678.90

Após o deploy, os valores determinados pelos atributos estarão refletidos no banco de dados, sem qualquer intervenção direta do desenvolvedor no script SQL:

Outras características também podem ser trabalhadas com os atributos, como atributos que recebem valores do procedimento armazenado (OUTPUT):

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

public partial class StoredProcedures
{
    [SqlProcedure(Name = "USP_Primeiro")]
    public static void Primeiro
        (out SqlString texto)
    {
        texto = new SqlString("Executado");
    }
};
DECLARE @VAR NVARCHAR(4000)
EXEC USP_Primeiro @VAR OUT
PRINT @VAR

Ou parâmetros que têm seus valores alterados durante a execução de procedimentos armazenados (INPUT/OUTPUT):

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

public partial class StoredProcedures
{
    [SqlProcedure(Name = "USP_Primeiro")]
    public static void Primeiro
        (ref SqlString texto)
    {
        SqlContext.Pipe.Send(texto.ToString());
        texto = new SqlString("VALOR 2");
    }
};
DECLARE @VAR NVARCHAR(4000)
SET @VAR = N'VALOR 1'
EXEC USP_Primeiro @VAR OUT
PRINT @VAR

Para as duas situações demonstradas anteriormente, o deploy se encarregará de criar estruturas adequadas para os procedimentos armazenados.

Com os procedimentos armazenados também é possível retornar valores inteiros, como detalhado abaixo.

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

public partial class StoredProcedures
{
    [SqlProcedure(Name = "USP_Primeiro")]
    public static SqlInt32 Primeiro()
    {
        return 333;
    }
};
DECLARE @VAR INT
EXEC @VAR = USP_Primeiro
PRINT @VAR

Concluindo este artigo, espero que tenham gostado esta primeira demonstração dos procedimentos armazenados, onde podemos identificar conceitos básicos de como o deploy se comporta com a customização do CLR, e a facilidade de customizar características dos procedimentos armazenados, sem a necessidade de envolvimento direto com o script de deploy.

No próximo artigo, estarei trabalhando as três principais formas de trabalhar com Stored Procedures desenvolvidas em CLR para retornar resultados de consultas ou simplesmente criar um resultado qualquer.

Anúncios

2 pensamentos sobre “Trabalhando com SQL CLR: Stored Procedure – Step 1

  1. Pingback: Trabalhando com SQL CLR – Resumo « SQL From Hell.com

  2. Pingback: Trabalhando com SQL CLR – Resumo « SQL From Hell.com

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s